Skip to content

Commit 7f945ee

Browse files
Elly Jonesgraydon
Elly Jones
authored andcommitted
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.
1 parent e3a066b commit 7f945ee

File tree

1 file changed

+82
-19
lines changed

1 file changed

+82
-19
lines changed

src/cargo/cargo.rs

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import rustc::syntax::{ast, codemap, visit};
44
import rustc::syntax::parse::parser;
55

66
import std::fs;
7+
import std::generic_os;
78
import std::io;
89
import std::option;
910
import std::option::{none, some};
11+
import std::os;
1012
import std::run;
1113
import std::str;
1214
import std::tempfile;
@@ -17,7 +19,8 @@ type pkg = {
1719
vers: str,
1820
uuid: str,
1921
desc: option::t<str>,
20-
sigs: option::t<str>
22+
sigs: option::t<str>,
23+
crate_type: option::t<str>
2124
};
2225

2326
fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
@@ -50,13 +53,15 @@ fn load_pkg(filename: str) -> option::t<pkg> {
5053
let uuid = none;
5154
let desc = none;
5255
let sigs = none;
56+
let crate_type = none;
5357

5458
for a in c.node.attrs {
5559
alt a.node.value.node {
5660
ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
5761
alt v {
5862
"desc" { desc = some(v); }
5963
"sigs" { sigs = some(v); }
64+
"crate_type" { crate_type = some(v); }
6065
_ { }
6166
}
6267
}
@@ -78,7 +83,8 @@ fn load_pkg(filename: str) -> option::t<pkg> {
7883
vers: vers0,
7984
uuid: uuid0,
8085
desc: desc,
81-
sigs: sigs})
86+
sigs: sigs,
87+
crate_type: crate_type})
8288
}
8389
_ { ret none; }
8490
}
@@ -96,41 +102,97 @@ fn rest(s: str, start: uint) -> str {
96102
}
97103
}
98104

99-
fn install_source(path: str) {
105+
fn need_dir(s: str) {
106+
if fs::file_is_dir(s) { ret; }
107+
if !fs::make_dir(s, 0x1c0i32) {
108+
fail #fmt["can't make_dir %s", s];
109+
}
110+
}
111+
112+
fn setup_dirs() -> str {
113+
let p = alt generic_os::getenv("CARGO_ROOT") {
114+
some(_p) { _p }
115+
none. {
116+
alt generic_os::getenv("HOME") {
117+
some(_q) { fs::connect(_q, "/.cargo") }
118+
none. { fail "no CARGO_ROOT or HOME"; }
119+
}
120+
}
121+
};
122+
123+
log #fmt["p: %s", p];
124+
125+
need_dir(p);
126+
need_dir(fs::connect(p, "fetch"));
127+
need_dir(fs::connect(p, "work"));
128+
need_dir(fs::connect(p, "lib"));
129+
need_dir(fs::connect(p, "bin"));
130+
131+
p
132+
}
133+
134+
fn install_one_crate(cargo_root: str, path: str, cf: str, p: pkg) {
135+
let bindir = fs::connect(cargo_root, "bin");
136+
let libdir = fs::connect(cargo_root, "lib");
137+
let name = fs::basename(cf);
138+
let ri = str::index(name, '.' as u8);
139+
if ri != -1 {
140+
name = str::slice(name, 0u, ri as uint);
141+
}
142+
log #fmt["Installing: %s", name];
143+
let old = fs::list_dir(".");
144+
run::run_program("rustc", [cf]);
145+
let new = fs::list_dir(".");
146+
let created = vec::filter::<str>({ |n| !vec::member::<str>(n, old) }, new);
147+
for c: str in created {
148+
if str::ends_with(c, os::exec_suffix()) {
149+
log #fmt[" bin: %s", c];
150+
// FIXME: need libstd fs::copy or something
151+
run::run_program("cp", [c, fs::connect(bindir, c)]);
152+
} else {
153+
log #fmt[" lib: %s", c];
154+
run::run_program("cp", [c, fs::connect(libdir, c)]);
155+
}
156+
}
157+
}
158+
159+
fn install_source(cargo_root: str, path: str) {
100160
log #fmt["source: %s", path];
101161
fs::change_dir(path);
102162
let contents = fs::list_dir(".");
103163

104164
log #fmt["contents: %s", str::connect(contents, ", ")];
105165

106-
let cratefile = vec::find::<str>({ |n| str::ends_with(n, ".rc") }, contents);
166+
let cratefiles = vec::filter::<str>({ |n| str::ends_with(n, ".rc") }, contents);
107167

108-
// First, try a configure script:
109-
if vec::member("./configure", contents) {
110-
run::run_program("./configure", []);
168+
if vec::is_empty(cratefiles) {
169+
fail "This doesn't look like a rust package (no .rc files).";
111170
}
112171

113-
// Makefile?
114-
if vec::member("./Makefile", contents) {
115-
run::run_program("make", ["RUSTC=rustc"]);
116-
} else if option::is_some::<str>(cratefile) {
117-
run::run_program("rustc", [option::get(cratefile)]);
172+
for cf: str in cratefiles {
173+
let p = load_pkg(cf);
174+
alt p {
175+
none. { cont; }
176+
some(_p) {
177+
install_one_crate(cargo_root, path, cf, _p);
178+
}
179+
}
118180
}
119181
}
120182

121-
fn install_file(_path: str) {
122-
let wd = tempfile::mkdtemp("/tmp/cargo-work-", "");
183+
fn install_file(cargo_root: str, _path: str) {
184+
let wd = tempfile::mkdtemp(cargo_root + "/work/", "");
123185
alt wd {
124186
some(p) {
125187
run::run_program("tar", ["-x", "--strip-components=1",
126188
"-C", p, "-f", _path]);
127-
install_source(p);
189+
install_source(cargo_root, p);
128190
}
129-
_ { }
191+
_ { fail "needed temp dir"; }
130192
}
131193
}
132194

133-
fn cmd_install(argv: [str]) {
195+
fn cmd_install(cargo_root: str, argv: [str]) {
134196
// cargo install <pkg>
135197
if vec::len(argv) < 3u {
136198
cmd_usage();
@@ -139,7 +201,7 @@ fn cmd_install(argv: [str]) {
139201

140202
if str::starts_with(argv[2], "file:") {
141203
let path = rest(argv[2], 5u);
142-
install_file(path);
204+
install_file(cargo_root, path);
143205
}
144206
}
145207

@@ -152,8 +214,9 @@ fn main(argv: [str]) {
152214
cmd_usage();
153215
ret;
154216
}
217+
let cargo_root = setup_dirs();
155218
alt argv[1] {
156-
"install" { cmd_install(argv); }
219+
"install" { cmd_install(cargo_root, argv); }
157220
"usage" { cmd_usage(); }
158221
_ { cmd_usage(); }
159222
}

0 commit comments

Comments
 (0)