Skip to content

Commit 10cf4a1

Browse files
author
Elly Jones
committed
cargo: wip
1 parent 89e880d commit 10cf4a1

File tree

2 files changed

+190
-10
lines changed

2 files changed

+190
-10
lines changed

src/cargo/cargo.rc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
// cargo.rs - Rust package manager
44

5-
use std;
6-
use rustc;
7-
85
// Local Variables:
96
// fill-column: 78;
107
// indent-tabs-mode: nil
118
// c-basic-offset: 4
129
// buffer-file-coding-system: utf-8-unix
1310
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
1411
// End:
12+
13+
#[link(name = "cargo",
14+
vers = "0.1",
15+
uuid = "9ff87a04-8fed-4295-9ff8-f99bb802650b",
16+
url = "http://rust-lang.org/doc/cargo")];

src/cargo/cargo.rs

Lines changed: 185 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// cargo.rs - Rust package manager
22

3+
use rustc;
4+
use std;
5+
36
import rustc::syntax::{ast, codemap, visit};
47
import rustc::syntax::parse::parser;
58

@@ -9,18 +12,39 @@ import std::io;
912
import std::json;
1013
import option;
1114
import option::{none, some};
15+
import result;
16+
import std::map;
1217
import std::os;
1318
import std::run;
1419
import str;
1520
import std::tempfile;
1621
import vec;
1722

23+
tag _src {
24+
/* Break cycles in package <-> source */
25+
_source(source);
26+
}
27+
28+
type package = {
29+
source: _src,
30+
name: str,
31+
uuid: str,
32+
url: str
33+
};
34+
35+
type source = {
36+
name: str,
37+
url: str,
38+
mutable packages: [package]
39+
};
40+
1841
type cargo = {
1942
root: str,
2043
bindir: str,
2144
libdir: str,
2245
workdir: str,
23-
fetchdir: str
46+
sourcedir: str,
47+
sources: map::hashmap<str, source>
2448
};
2549

2650
type pkg = {
@@ -32,6 +56,14 @@ type pkg = {
3256
crate_type: option::t<str>
3357
};
3458

59+
fn info(msg: str) {
60+
io::stdout().write_line(msg);
61+
}
62+
63+
fn warn(msg: str) {
64+
io::stdout().write_line("warning: " + msg);
65+
}
66+
3567
fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
3668
option::t<str>,
3769
option::t<str>) {
@@ -118,6 +150,96 @@ fn need_dir(s: str) {
118150
}
119151
}
120152

153+
fn parse_source(name: str, j: json::json) -> source {
154+
alt j {
155+
json::dict(_j) {
156+
alt _j.find("url") {
157+
some(json::string(u)) {
158+
ret { name: name, url: u, mutable packages: [] };
159+
}
160+
_ { fail "Needed 'url' field in source."; }
161+
};
162+
}
163+
_ { fail "Needed dict value in source."; }
164+
};
165+
}
166+
167+
fn try_parse_sources(filename: str, sources: map::hashmap<str, source>) {
168+
if !fs::path_exists(filename) { ret; }
169+
let c = io::read_whole_file_str(filename);
170+
let j = json::from_str(result::get(c));
171+
alt j {
172+
some(json::dict(_j)) {
173+
_j.items { |k, v|
174+
sources.insert(k, parse_source(k, v));
175+
log #fmt["source: %s", k];
176+
}
177+
}
178+
_ { fail "malformed sources.json"; }
179+
}
180+
}
181+
182+
fn load_one_source_package(c: cargo, src: source, p: map::hashmap<str, json::json>) {
183+
let name = alt p.find("name") {
184+
some(json::string(_n)) { _n }
185+
_ {
186+
warn("Malformed source json: " + src.name + " (missing name)");
187+
ret;
188+
}
189+
};
190+
191+
let uuid = alt p.find("uuid") {
192+
some(json::string(_n)) { _n }
193+
_ {
194+
warn("Malformed source json: " + src.name + " (missing uuid)");
195+
ret;
196+
}
197+
};
198+
199+
let url = alt p.find("url") {
200+
some(json::string(_n)) { _n }
201+
_ {
202+
warn("Malformed source json: " + src.name + " (missing url)");
203+
ret;
204+
}
205+
};
206+
207+
vec::grow(src.packages, 1u, {
208+
source: _source(src),
209+
name: name,
210+
uuid: uuid,
211+
url: url
212+
});
213+
info(" Loaded package: " + src.name + "/" + name);
214+
}
215+
216+
fn load_source_packages(c: cargo, src: source) {
217+
info("Loading source: " + src.name);
218+
let dir = fs::connect(c.sourcedir, src.name);
219+
let pkgfile = fs::connect(dir, "packages.json");
220+
if !fs::path_exists(pkgfile) { ret; }
221+
let pkgstr = io::read_whole_file_str(pkgfile);
222+
let j = json::from_str(result::get(pkgstr));
223+
alt j {
224+
some(json::list(js)) {
225+
for _j: json::json in *js {
226+
alt _j {
227+
json::dict(_p) {
228+
load_one_source_package(c, src, _p);
229+
}
230+
_ {
231+
warn("Malformed source json: " + src.name + " (non-dict pkg)");
232+
ret;
233+
}
234+
}
235+
}
236+
}
237+
_ {
238+
warn("Malformed source json: " + src.name);
239+
}
240+
};
241+
}
242+
121243
fn configure() -> cargo {
122244
let p = alt generic_os::getenv("CARGO_ROOT") {
123245
some(_p) { _p }
@@ -129,25 +251,39 @@ fn configure() -> cargo {
129251
}
130252
};
131253

132-
log #fmt["p: %s", p];
133-
254+
let sources = map::new_str_hash::<source>();
255+
try_parse_sources(fs::connect(p, "sources.json"), sources);
256+
try_parse_sources(fs::connect(p, "local-sources.json"), sources);
134257
let c = {
135258
root: p,
136259
bindir: fs::connect(p, "bin"),
137260
libdir: fs::connect(p, "lib"),
138261
workdir: fs::connect(p, "work"),
139-
fetchdir: fs::connect(p, "fetch")
262+
sourcedir: fs::connect(p, "sources"),
263+
sources: sources
140264
};
141265

142266
need_dir(c.root);
143-
need_dir(c.fetchdir);
267+
need_dir(c.sourcedir);
144268
need_dir(c.workdir);
145269
need_dir(c.libdir);
146270
need_dir(c.bindir);
147271

272+
sources.values { |v|
273+
load_source_packages(c, v);
274+
};
275+
148276
c
149277
}
150278

279+
fn for_each_package(c: cargo, b: block(package)) {
280+
c.sources.values({ |v|
281+
for p in v.packages {
282+
b(p);
283+
}
284+
})
285+
}
286+
151287
fn install_one_crate(c: cargo, _path: str, cf: str, _p: pkg) {
152288
let name = fs::basename(cf);
153289
let ri = str::index(name, '.' as u8);
@@ -233,11 +369,29 @@ fn install_resolved(c: cargo, wd: str, key: str) {
233369
}
234370

235371
fn install_uuid(c: cargo, wd: str, uuid: str) {
236-
install_resolved(c, wd, "by-uuid/" + uuid);
372+
let ps = [];
373+
for_each_package(c, { |p|
374+
if p.uuid == uuid {
375+
vec::grow(ps, 1u, p);
376+
}
377+
});
378+
info("Found:");
379+
for p in ps {
380+
info(" " + p.source.name + "/" + p.name);
381+
}
237382
}
238383

239384
fn install_named(c: cargo, wd: str, name: str) {
240-
install_resolved(c, wd, "by-name/" + name);
385+
let ps = [];
386+
for_each_package(c, { |p|
387+
if p.name == name {
388+
vec::grow(ps, 1u, p);
389+
}
390+
});
391+
info("Found:");
392+
for p in ps {
393+
info(" " + p.source.name + "/" + p.name);
394+
}
241395
}
242396

243397
fn cmd_install(c: cargo, argv: [str]) {
@@ -268,6 +422,29 @@ fn cmd_install(c: cargo, argv: [str]) {
268422
}
269423
}
270424

425+
fn sync_one(c: cargo, name: str, src: source) {
426+
let dir = fs::connect(c.sourcedir, name);
427+
let pkgfile = fs::connect(dir, "packages.json");
428+
let url = src.url;
429+
need_dir(dir);
430+
let p = run::program_output("curl", ["-f", "-s", "-o", pkgfile, url]);
431+
if p.status != 0 {
432+
warn(#fmt["fetch for source %s (url %s) failed", name, url]);
433+
} else {
434+
info(#fmt["fetched source: %s", name]);
435+
}
436+
}
437+
438+
fn cmd_sync(c: cargo, argv: [str]) {
439+
if vec::len(argv) == 3u {
440+
sync_one(c, argv[2], c.sources.get(argv[2]));
441+
} else {
442+
c.sources.items { |k, v|
443+
sync_one(c, k, v);
444+
}
445+
}
446+
}
447+
271448
fn cmd_usage() {
272449
print("Usage: cargo <verb> [args...]");
273450
}
@@ -280,6 +457,7 @@ fn main(argv: [str]) {
280457
let c = configure();
281458
alt argv[1] {
282459
"install" { cmd_install(c, argv); }
460+
"sync" { cmd_sync(c, argv); }
283461
"usage" { cmd_usage(); }
284462
_ { cmd_usage(); }
285463
}

0 commit comments

Comments
 (0)