diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 813b5d1351605..9184e11db0aa6 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -4,20 +4,31 @@ 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; import std::vec; +type cargo = { + root: str, + bindir: str, + libdir: str, + workdir: str, + fetchdir: str +}; + type pkg = { name: str, 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 +61,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 +69,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 +91,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,50 +110,121 @@ 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 configure() -> cargo { + 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]; + + 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); + + c +} + +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 { + 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 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", [ct, c.bindir]); + } else { + log #fmt[" lib: %s", ct]; + run::run_program("cp", [ct, c.libdir]); + } + } +} + +fn install_source(c: cargo, 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(c, path, cf, _p); + } + } } } -fn install_file(_path: str) { - let wd = tempfile::mkdtemp("/tmp/cargo-work-", ""); - alt wd { - some(p) { - run::run_program("tar", ["-x", "--strip-components=1", - "-C", p, "-f", _path]); - install_source(p); - } - _ { } - } +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, wd: str, _path: str) { + run::run_program("tar", ["-x", "--strip-components=1", + "-C", wd, "-f", _path]); + install_source(c, wd); } -fn cmd_install(argv: [str]) { +fn cmd_install(c: cargo, argv: [str]) { // cargo install if vec::len(argv) < 3u { cmd_usage(); ret; } - if str::starts_with(argv[2], "file:") { + 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, 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(path); + install_file(c, wd, path); } } @@ -152,8 +237,9 @@ fn main(argv: [str]) { cmd_usage(); ret; } + let c = configure(); alt argv[1] { - "install" { cmd_install(argv); } + "install" { cmd_install(c, argv); } "usage" { cmd_usage(); } _ { cmd_usage(); } }