From 4d87605b9f139af7a8a460652249f92fb81a6b2a Mon Sep 17 00:00:00 2001 From: Elly Jones Date: Thu, 8 Dec 2011 23:41:29 -0500 Subject: [PATCH 1/5] cargo: support installing crates Introduce the notion of CARGO_ROOT to override HOME if need be. Build packages there instead of in /tmp. Install to CARGO_ROOT/bin and CARGO_ROOT/lib. --- src/cargo/cargo.rs | 101 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 19 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 813b5d1351605..20d3b3882bdb6 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -4,9 +4,11 @@ import rustc::syntax::{ast, codemap, visit}; import rustc::syntax::parse::parser; import std::fs; +import std::generic_os; import std::io; import std::option; import std::option::{none, some}; +import std::os; import std::run; import std::str; import std::tempfile; @@ -17,7 +19,8 @@ type pkg = { vers: str, uuid: str, desc: option::t, - sigs: option::t + sigs: option::t, + crate_type: option::t }; fn load_link(mis: [@ast::meta_item]) -> (option::t, @@ -50,6 +53,7 @@ fn load_pkg(filename: str) -> option::t { let uuid = none; let desc = none; let sigs = none; + let crate_type = none; for a in c.node.attrs { alt a.node.value.node { @@ -57,6 +61,7 @@ fn load_pkg(filename: str) -> option::t { alt v { "desc" { desc = some(v); } "sigs" { sigs = some(v); } + "crate_type" { crate_type = some(v); } _ { } } } @@ -78,7 +83,8 @@ fn load_pkg(filename: str) -> option::t { vers: vers0, uuid: uuid0, desc: desc, - sigs: sigs}) + sigs: sigs, + crate_type: crate_type}) } _ { ret none; } } @@ -96,41 +102,97 @@ fn rest(s: str, start: uint) -> str { } } -fn install_source(path: str) { +fn need_dir(s: str) { + if fs::file_is_dir(s) { ret; } + if !fs::make_dir(s, 0x1c0i32) { + fail #fmt["can't make_dir %s", s]; + } +} + +fn setup_dirs() -> str { + let p = alt generic_os::getenv("CARGO_ROOT") { + some(_p) { _p } + none. { + alt generic_os::getenv("HOME") { + some(_q) { fs::connect(_q, "/.cargo") } + none. { fail "no CARGO_ROOT or HOME"; } + } + } + }; + + log #fmt["p: %s", p]; + + need_dir(p); + need_dir(fs::connect(p, "fetch")); + need_dir(fs::connect(p, "work")); + need_dir(fs::connect(p, "lib")); + need_dir(fs::connect(p, "bin")); + + p +} + +fn install_one_crate(cargo_root: str, path: str, cf: str, p: pkg) { + let bindir = fs::connect(cargo_root, "bin"); + let libdir = fs::connect(cargo_root, "lib"); + let name = fs::basename(cf); + let ri = str::index(name, '.' as u8); + if ri != -1 { + name = str::slice(name, 0u, ri as uint); + } + log #fmt["Installing: %s", name]; + let old = fs::list_dir("."); + run::run_program("rustc", [cf]); + let new = fs::list_dir("."); + let created = vec::filter::({ |n| !vec::member::(n, old) }, new); + for c: str in created { + if str::ends_with(c, os::exec_suffix()) { + log #fmt[" bin: %s", c]; + // FIXME: need libstd fs::copy or something + run::run_program("cp", [c, fs::connect(bindir, c)]); + } else { + log #fmt[" lib: %s", c]; + run::run_program("cp", [c, fs::connect(libdir, c)]); + } + } +} + +fn install_source(cargo_root: str, path: str) { log #fmt["source: %s", path]; fs::change_dir(path); let contents = fs::list_dir("."); log #fmt["contents: %s", str::connect(contents, ", ")]; - let cratefile = vec::find::({ |n| str::ends_with(n, ".rc") }, contents); + let cratefiles = vec::filter::({ |n| str::ends_with(n, ".rc") }, contents); - // First, try a configure script: - if vec::member("./configure", contents) { - run::run_program("./configure", []); + if vec::is_empty(cratefiles) { + fail "This doesn't look like a rust package (no .rc files)."; } - // Makefile? - if vec::member("./Makefile", contents) { - run::run_program("make", ["RUSTC=rustc"]); - } else if option::is_some::(cratefile) { - run::run_program("rustc", [option::get(cratefile)]); + for cf: str in cratefiles { + let p = load_pkg(cf); + alt p { + none. { cont; } + some(_p) { + install_one_crate(cargo_root, path, cf, _p); + } + } } } -fn install_file(_path: str) { - let wd = tempfile::mkdtemp("/tmp/cargo-work-", ""); +fn install_file(cargo_root: str, _path: str) { + let wd = tempfile::mkdtemp(cargo_root + "/work/", ""); alt wd { some(p) { run::run_program("tar", ["-x", "--strip-components=1", "-C", p, "-f", _path]); - install_source(p); + install_source(cargo_root, p); } - _ { } + _ { fail "needed temp dir"; } } } -fn cmd_install(argv: [str]) { +fn cmd_install(cargo_root: str, argv: [str]) { // cargo install if vec::len(argv) < 3u { cmd_usage(); @@ -139,7 +201,7 @@ fn cmd_install(argv: [str]) { if str::starts_with(argv[2], "file:") { let path = rest(argv[2], 5u); - install_file(path); + install_file(cargo_root, path); } } @@ -152,8 +214,9 @@ fn main(argv: [str]) { cmd_usage(); ret; } + let cargo_root = setup_dirs(); alt argv[1] { - "install" { cmd_install(argv); } + "install" { cmd_install(cargo_root, argv); } "usage" { cmd_usage(); } _ { cmd_usage(); } } From a62963389de612f06ed7e808e111db70f310329e Mon Sep 17 00:00:00 2001 From: Elly Jones Date: Thu, 8 Dec 2011 23:50:25 -0500 Subject: [PATCH 2/5] cargo: refactor a bit --- src/cargo/cargo.rs | 64 ++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 20d3b3882bdb6..f6c3cc90334c1 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -14,6 +14,14 @@ import std::str; import std::tempfile; import std::vec; +type cargo = { + root: str, + bindir: str, + libdir: str, + workdir: str, + fetchdir: str +}; + type pkg = { name: str, vers: str, @@ -109,7 +117,7 @@ fn need_dir(s: str) { } } -fn setup_dirs() -> str { +fn configure() -> cargo { let p = alt generic_os::getenv("CARGO_ROOT") { some(_p) { _p } none. { @@ -122,18 +130,24 @@ fn setup_dirs() -> str { log #fmt["p: %s", p]; - need_dir(p); - need_dir(fs::connect(p, "fetch")); - need_dir(fs::connect(p, "work")); - need_dir(fs::connect(p, "lib")); - need_dir(fs::connect(p, "bin")); + let c = { + root: p, + bindir: fs::connect(p, "bin"), + libdir: fs::connect(p, "lib"), + workdir: fs::connect(p, "work"), + fetchdir: fs::connect(p, "fetch") + }; + + need_dir(c.root); + need_dir(c.fetchdir); + need_dir(c.workdir); + need_dir(c.libdir); + need_dir(c.bindir); - p + c } -fn install_one_crate(cargo_root: str, path: str, cf: str, p: pkg) { - let bindir = fs::connect(cargo_root, "bin"); - let libdir = fs::connect(cargo_root, "lib"); +fn install_one_crate(c: cargo, path: str, cf: str, p: pkg) { let name = fs::basename(cf); let ri = str::index(name, '.' as u8); if ri != -1 { @@ -144,19 +158,19 @@ fn install_one_crate(cargo_root: str, path: str, cf: str, p: pkg) { run::run_program("rustc", [cf]); let new = fs::list_dir("."); let created = vec::filter::({ |n| !vec::member::(n, old) }, new); - for c: str in created { - if str::ends_with(c, os::exec_suffix()) { - log #fmt[" bin: %s", c]; + for ct: str in created { + if str::ends_with(ct, os::exec_suffix()) { + log #fmt[" bin: %s", ct]; // FIXME: need libstd fs::copy or something - run::run_program("cp", [c, fs::connect(bindir, c)]); + run::run_program("cp", [ct, c.bindir]); } else { - log #fmt[" lib: %s", c]; - run::run_program("cp", [c, fs::connect(libdir, c)]); + log #fmt[" lib: %s", ct]; + run::run_program("cp", [ct, c.libdir]); } } } -fn install_source(cargo_root: str, path: str) { +fn install_source(c: cargo, path: str) { log #fmt["source: %s", path]; fs::change_dir(path); let contents = fs::list_dir("."); @@ -174,25 +188,25 @@ fn install_source(cargo_root: str, path: str) { alt p { none. { cont; } some(_p) { - install_one_crate(cargo_root, path, cf, _p); + install_one_crate(c, path, cf, _p); } } } } -fn install_file(cargo_root: str, _path: str) { - let wd = tempfile::mkdtemp(cargo_root + "/work/", ""); +fn install_file(c: cargo, _path: str) { + let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), ""); alt wd { some(p) { run::run_program("tar", ["-x", "--strip-components=1", "-C", p, "-f", _path]); - install_source(cargo_root, p); + install_source(c, p); } _ { fail "needed temp dir"; } } } -fn cmd_install(cargo_root: str, argv: [str]) { +fn cmd_install(c: cargo, argv: [str]) { // cargo install if vec::len(argv) < 3u { cmd_usage(); @@ -201,7 +215,7 @@ fn cmd_install(cargo_root: str, argv: [str]) { if str::starts_with(argv[2], "file:") { let path = rest(argv[2], 5u); - install_file(cargo_root, path); + install_file(c, path); } } @@ -214,9 +228,9 @@ fn main(argv: [str]) { cmd_usage(); ret; } - let cargo_root = setup_dirs(); + let c = configure(); alt argv[1] { - "install" { cmd_install(cargo_root, argv); } + "install" { cmd_install(c, argv); } "usage" { cmd_usage(); } _ { cmd_usage(); } } From b5c31c2e95207236c8742f6375f56fd929a715f0 Mon Sep 17 00:00:00 2001 From: Elly Jones Date: Thu, 8 Dec 2011 23:56:19 -0500 Subject: [PATCH 3/5] cargo: don't stick an extra / in CARGO_ROOT --- src/cargo/cargo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index f6c3cc90334c1..6f2be37097aa5 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -122,7 +122,7 @@ fn configure() -> cargo { some(_p) { _p } none. { alt generic_os::getenv("HOME") { - some(_q) { fs::connect(_q, "/.cargo") } + some(_q) { fs::connect(_q, ".cargo") } none. { fail "no CARGO_ROOT or HOME"; } } } From f8e8514154aa872cf2f036198e9c3b061945c8c0 Mon Sep 17 00:00:00 2001 From: Elly Jones Date: Fri, 9 Dec 2011 00:34:06 -0500 Subject: [PATCH 4/5] cargo: support git:// URIs. --- src/cargo/cargo.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 6f2be37097aa5..ff2e7a6346f86 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -194,6 +194,17 @@ fn install_source(c: cargo, path: str) { } } +fn install_git(c: cargo, _path: str) { + let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), ""); + alt wd { + some(p) { + run::run_program("git", ["clone", _path, p]); + install_source(c, p); + } + _ { fail "needed temp dir"; } + } +} + fn install_file(c: cargo, _path: str) { let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), ""); alt wd { @@ -213,6 +224,9 @@ fn cmd_install(c: cargo, argv: [str]) { ret; } + if str::starts_with(argv[2], "git:") { + install_git(c, argv[2]); + } if str::starts_with(argv[2], "file:") { let path = rest(argv[2], 5u); install_file(c, path); From c4dfd5fd461c5e8cfcf9074cc5a572a79c2ed4d9 Mon Sep 17 00:00:00 2001 From: Elly Jones Date: Fri, 9 Dec 2011 00:39:41 -0500 Subject: [PATCH 5/5] cargo: support github:/ --- src/cargo/cargo.rs | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index ff2e7a6346f86..9184e11db0aa6 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -194,27 +194,15 @@ fn install_source(c: cargo, path: str) { } } -fn install_git(c: cargo, _path: str) { - let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), ""); - alt wd { - some(p) { - run::run_program("git", ["clone", _path, p]); - install_source(c, p); - } - _ { fail "needed temp dir"; } - } +fn install_git(c: cargo, wd: str, _path: str) { + run::run_program("git", ["clone", _path, wd]); + install_source(c, wd); } -fn install_file(c: cargo, _path: str) { - let wd = tempfile::mkdtemp(c.workdir + fs::path_sep(), ""); - alt wd { - some(p) { - run::run_program("tar", ["-x", "--strip-components=1", - "-C", p, "-f", _path]); - install_source(c, p); - } - _ { fail "needed temp dir"; } - } +fn install_file(c: cargo, wd: str, _path: str) { + run::run_program("tar", ["-x", "--strip-components=1", + "-C", wd, "-f", _path]); + install_source(c, wd); } fn cmd_install(c: cargo, argv: [str]) { @@ -224,12 +212,19 @@ fn cmd_install(c: cargo, argv: [str]) { ret; } + let wd = alt tempfile::mkdtemp(c.workdir + fs::path_sep(), "") { + some(_wd) { _wd } + none. { fail "needed temp dir"; } + }; + if str::starts_with(argv[2], "git:") { - install_git(c, argv[2]); - } - if str::starts_with(argv[2], "file:") { + install_git(c, wd, argv[2]); + } else if str::starts_with(argv[2], "github:") { + let path = rest(argv[2], 7u); + install_git(c, wd, "git://github.com/" + path); + } else if str::starts_with(argv[2], "file:") { let path = rest(argv[2], 5u); - install_file(c, path); + install_file(c, wd, path); } }