2011-11-30 17:57:46 -06:00
|
|
|
// cargo.rs - Rust package manager
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
use rustc;
|
|
|
|
use std;
|
|
|
|
|
2012-01-23 23:08:13 -06:00
|
|
|
import rustc::syntax::{ast, codemap};
|
2011-11-30 17:57:46 -06:00
|
|
|
import rustc::syntax::parse::parser;
|
2012-02-07 02:15:39 -06:00
|
|
|
import rustc::util::filesearch::{get_cargo_root, get_cargo_root_nearest,
|
2012-02-20 02:33:50 -06:00
|
|
|
get_cargo_sysroot, libdir};
|
2012-01-13 19:33:16 -06:00
|
|
|
import rustc::driver::diagnostic;
|
2011-11-30 17:57:46 -06:00
|
|
|
|
2011-12-01 21:37:56 -06:00
|
|
|
import std::fs;
|
2011-11-30 17:57:46 -06:00
|
|
|
import std::io;
|
2012-01-11 08:15:54 -06:00
|
|
|
import io::writer_util;
|
2011-12-15 19:27:55 -06:00
|
|
|
import std::json;
|
2011-12-16 19:33:39 -06:00
|
|
|
import result;
|
|
|
|
import std::map;
|
2011-12-08 22:41:29 -06:00
|
|
|
import std::os;
|
2011-11-30 17:57:46 -06:00
|
|
|
import std::run;
|
2011-12-13 18:25:51 -06:00
|
|
|
import str;
|
2011-11-30 17:57:46 -06:00
|
|
|
import std::tempfile;
|
2011-12-13 18:25:51 -06:00
|
|
|
import vec;
|
2012-02-05 03:30:03 -06:00
|
|
|
import std::getopts;
|
2012-02-07 02:15:39 -06:00
|
|
|
import getopts::{optflag, optopt, opt_present};
|
2011-11-30 17:57:46 -06:00
|
|
|
|
2012-01-19 18:21:33 -06:00
|
|
|
enum _src {
|
2011-12-16 19:33:39 -06:00
|
|
|
/* Break cycles in package <-> source */
|
2012-01-19 20:46:53 -06:00
|
|
|
_source(source),
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type package = {
|
2011-12-16 21:08:25 -06:00
|
|
|
// source: _src,
|
2011-12-16 19:33:39 -06:00
|
|
|
name: str,
|
|
|
|
uuid: str,
|
2011-12-16 21:08:25 -06:00
|
|
|
url: str,
|
2011-12-20 19:41:23 -06:00
|
|
|
method: str,
|
2012-01-23 20:23:31 -06:00
|
|
|
description: str,
|
2012-01-31 19:05:20 -06:00
|
|
|
ref: option<str>,
|
2011-12-20 19:41:23 -06:00
|
|
|
tags: [str]
|
2011-12-16 19:33:39 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
type source = {
|
|
|
|
name: str,
|
|
|
|
url: str,
|
2012-01-31 19:05:20 -06:00
|
|
|
sig: option<str>,
|
|
|
|
key: option<str>,
|
|
|
|
keyfp: option<str>,
|
2011-12-16 19:33:39 -06:00
|
|
|
mutable packages: [package]
|
|
|
|
};
|
|
|
|
|
2011-12-08 22:50:25 -06:00
|
|
|
type cargo = {
|
2011-12-20 18:59:37 -06:00
|
|
|
pgp: bool,
|
2011-12-08 22:50:25 -06:00
|
|
|
root: str,
|
|
|
|
bindir: str,
|
|
|
|
libdir: str,
|
|
|
|
workdir: str,
|
2011-12-16 19:33:39 -06:00
|
|
|
sourcedir: str,
|
2012-01-18 21:16:14 -06:00
|
|
|
sources: map::hashmap<str, source>,
|
2012-02-05 03:30:03 -06:00
|
|
|
opts: options
|
2011-12-08 22:50:25 -06:00
|
|
|
};
|
|
|
|
|
2011-11-30 17:57:46 -06:00
|
|
|
type pkg = {
|
|
|
|
name: str,
|
|
|
|
vers: str,
|
|
|
|
uuid: str,
|
2012-01-31 19:05:20 -06:00
|
|
|
desc: option<str>,
|
|
|
|
sigs: option<str>,
|
|
|
|
crate_type: option<str>
|
2011-11-30 17:57:46 -06:00
|
|
|
};
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
type options = {
|
|
|
|
test: bool,
|
2012-02-07 02:15:39 -06:00
|
|
|
mode: mode,
|
2012-02-05 03:30:03 -06:00
|
|
|
free: [str],
|
|
|
|
};
|
|
|
|
|
2012-02-07 02:15:39 -06:00
|
|
|
enum mode { system_mode, user_mode, local_mode }
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
fn opts() -> [getopts::opt] {
|
2012-02-07 02:15:39 -06:00
|
|
|
[optflag("g"), optflag("G"), optopt("mode"), optflag("test")]
|
2012-02-05 03:30:03 -06:00
|
|
|
}
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
fn info(msg: str) {
|
2012-01-18 21:16:14 -06:00
|
|
|
io::stdout().write_line("info: " + msg);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn warn(msg: str) {
|
|
|
|
io::stdout().write_line("warning: " + msg);
|
|
|
|
}
|
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
fn error(msg: str) {
|
|
|
|
io::stdout().write_line("error: " + msg);
|
|
|
|
}
|
|
|
|
|
2012-01-31 19:05:20 -06:00
|
|
|
fn load_link(mis: [@ast::meta_item]) -> (option<str>,
|
|
|
|
option<str>,
|
|
|
|
option<str>) {
|
2011-11-30 17:57:46 -06:00
|
|
|
let name = none;
|
|
|
|
let vers = none;
|
|
|
|
let uuid = none;
|
|
|
|
for a: @ast::meta_item in mis {
|
|
|
|
alt a.node {
|
|
|
|
ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
|
|
|
|
alt v {
|
|
|
|
"name" { name = some(s); }
|
|
|
|
"vers" { vers = some(s); }
|
|
|
|
"uuid" { uuid = some(s); }
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
}
|
2012-01-30 23:00:57 -06:00
|
|
|
_ { fail "load_link: meta items must be name-values"; }
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
(name, vers, uuid)
|
|
|
|
}
|
|
|
|
|
2012-01-31 19:05:20 -06:00
|
|
|
fn load_pkg(filename: str) -> option<pkg> {
|
2012-01-13 19:33:16 -06:00
|
|
|
let cm = codemap::new_codemap();
|
2012-01-24 23:42:54 -06:00
|
|
|
let handler = diagnostic::mk_handler(none);
|
2012-01-13 19:33:16 -06:00
|
|
|
let sess = @{
|
|
|
|
cm: cm,
|
2012-01-19 23:46:47 -06:00
|
|
|
mutable next_id: 1,
|
2012-01-24 23:42:54 -06:00
|
|
|
span_diagnostic: diagnostic::mk_span_handler(handler, cm),
|
2012-01-22 18:24:55 -06:00
|
|
|
mutable chpos: 0u,
|
|
|
|
mutable byte_pos: 0u
|
2012-01-13 19:33:16 -06:00
|
|
|
};
|
2011-11-30 17:57:46 -06:00
|
|
|
let c = parser::parse_crate_from_crate_file(filename, [], sess);
|
|
|
|
|
|
|
|
let name = none;
|
|
|
|
let vers = none;
|
|
|
|
let uuid = none;
|
|
|
|
let desc = none;
|
|
|
|
let sigs = none;
|
2011-12-08 22:41:29 -06:00
|
|
|
let crate_type = none;
|
2011-11-30 17:57:46 -06:00
|
|
|
|
|
|
|
for a in c.node.attrs {
|
|
|
|
alt a.node.value.node {
|
|
|
|
ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) {
|
|
|
|
alt v {
|
|
|
|
"desc" { desc = some(v); }
|
|
|
|
"sigs" { sigs = some(v); }
|
2011-12-08 22:41:29 -06:00
|
|
|
"crate_type" { crate_type = some(v); }
|
2011-11-30 17:57:46 -06:00
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast::meta_list(v, mis) {
|
|
|
|
if v == "link" {
|
|
|
|
let (n, v, u) = load_link(mis);
|
|
|
|
name = n;
|
|
|
|
vers = v;
|
|
|
|
uuid = u;
|
|
|
|
}
|
|
|
|
}
|
2012-01-30 23:00:57 -06:00
|
|
|
_ { fail "load_pkg: pkg attributes may not contain meta_words"; }
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
alt (name, vers, uuid) {
|
|
|
|
(some(name0), some(vers0), some(uuid0)) {
|
|
|
|
some({
|
|
|
|
name: name0,
|
|
|
|
vers: vers0,
|
|
|
|
uuid: uuid0,
|
|
|
|
desc: desc,
|
2011-12-08 22:41:29 -06:00
|
|
|
sigs: sigs,
|
|
|
|
crate_type: crate_type})
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
_ { ret none; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print(s: str) {
|
|
|
|
io::stdout().write_line(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn rest(s: str, start: uint) -> str {
|
2012-02-23 03:44:04 -06:00
|
|
|
if (start >= str::len(s)) {
|
2011-11-30 17:57:46 -06:00
|
|
|
""
|
|
|
|
} else {
|
2012-02-23 03:44:04 -06:00
|
|
|
str::slice(s, start, str::len(s))
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-08 22:41:29 -06:00
|
|
|
fn need_dir(s: str) {
|
2011-12-16 16:32:09 -06:00
|
|
|
if fs::path_is_dir(s) { ret; }
|
2011-12-08 22:41:29 -06:00
|
|
|
if !fs::make_dir(s, 0x1c0i32) {
|
|
|
|
fail #fmt["can't make_dir %s", s];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
fn parse_source(name: str, j: json::json) -> source {
|
|
|
|
alt j {
|
|
|
|
json::dict(_j) {
|
2011-12-20 18:59:37 -06:00
|
|
|
let url = alt _j.find("url") {
|
2011-12-16 19:33:39 -06:00
|
|
|
some(json::string(u)) {
|
2011-12-20 18:59:37 -06:00
|
|
|
u
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
_ { fail "Needed 'url' field in source."; }
|
|
|
|
};
|
2011-12-20 18:59:37 -06:00
|
|
|
let sig = alt _j.find("sig") {
|
|
|
|
some(json::string(u)) {
|
|
|
|
some(u)
|
|
|
|
}
|
|
|
|
_ { none }
|
|
|
|
};
|
|
|
|
let key = alt _j.find("key") {
|
|
|
|
some(json::string(u)) {
|
|
|
|
some(u)
|
|
|
|
}
|
|
|
|
_ { none }
|
|
|
|
};
|
|
|
|
let keyfp = alt _j.find("keyfp") {
|
|
|
|
some(json::string(u)) {
|
|
|
|
some(u)
|
|
|
|
}
|
|
|
|
_ { none }
|
|
|
|
};
|
|
|
|
ret { name: name, url: url, sig: sig, key: key, keyfp: keyfp,
|
|
|
|
mutable packages: [] };
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
_ { fail "Needed dict value in source."; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
fn try_parse_sources(filename: str, sources: map::hashmap<str, source>) {
|
|
|
|
if !fs::path_exists(filename) { ret; }
|
|
|
|
let c = io::read_whole_file_str(filename);
|
|
|
|
let j = json::from_str(result::get(c));
|
|
|
|
alt j {
|
|
|
|
some(json::dict(_j)) {
|
|
|
|
_j.items { |k, v|
|
|
|
|
sources.insert(k, parse_source(k, v));
|
2011-12-22 16:42:52 -06:00
|
|
|
#debug("source: %s", k);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ { fail "malformed sources.json"; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-16 21:27:04 -06:00
|
|
|
fn load_one_source_package(&src: source, p: map::hashmap<str, json::json>) {
|
2011-12-16 19:33:39 -06:00
|
|
|
let name = alt p.find("name") {
|
|
|
|
some(json::string(_n)) { _n }
|
|
|
|
_ {
|
|
|
|
warn("Malformed source json: " + src.name + " (missing name)");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let uuid = alt p.find("uuid") {
|
|
|
|
some(json::string(_n)) { _n }
|
|
|
|
_ {
|
|
|
|
warn("Malformed source json: " + src.name + " (missing uuid)");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let url = alt p.find("url") {
|
|
|
|
some(json::string(_n)) { _n }
|
|
|
|
_ {
|
|
|
|
warn("Malformed source json: " + src.name + " (missing url)");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
let method = alt p.find("method") {
|
|
|
|
some(json::string(_n)) { _n }
|
|
|
|
_ {
|
|
|
|
warn("Malformed source json: " + src.name + " (missing method)");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-20 22:41:22 -06:00
|
|
|
let ref = alt p.find("ref") {
|
|
|
|
some(json::string(_n)) { some(_n) }
|
|
|
|
_ { none }
|
|
|
|
};
|
|
|
|
|
2011-12-20 19:41:23 -06:00
|
|
|
let tags = [];
|
|
|
|
alt p.find("tags") {
|
|
|
|
some(json::list(js)) {
|
|
|
|
for j in *js {
|
|
|
|
alt j {
|
|
|
|
json::string(_j) { vec::grow(tags, 1u, _j); }
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
2012-01-23 21:42:29 -06:00
|
|
|
|
|
|
|
let description = alt p.find("description") {
|
|
|
|
some(json::string(_n)) { _n }
|
|
|
|
_ {
|
2012-01-23 23:14:48 -06:00
|
|
|
warn("Malformed source json: " + src.name
|
|
|
|
+ " (missing description)");
|
2012-01-23 21:42:29 -06:00
|
|
|
ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
vec::grow(src.packages, 1u, {
|
2011-12-16 21:08:25 -06:00
|
|
|
// source: _source(src),
|
2011-12-16 19:33:39 -06:00
|
|
|
name: name,
|
|
|
|
uuid: uuid,
|
2011-12-16 21:08:25 -06:00
|
|
|
url: url,
|
2011-12-20 19:41:23 -06:00
|
|
|
method: method,
|
2012-01-23 20:23:31 -06:00
|
|
|
description: description,
|
2011-12-20 22:41:22 -06:00
|
|
|
ref: ref,
|
2011-12-20 19:41:23 -06:00
|
|
|
tags: tags
|
2011-12-16 19:33:39 -06:00
|
|
|
});
|
2011-12-22 19:53:53 -06:00
|
|
|
log(debug, " Loaded package: " + src.name + "/" + name);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
fn load_source_packages(&c: cargo, &src: source) {
|
2011-12-22 19:53:53 -06:00
|
|
|
log(debug, "Loading source: " + src.name);
|
2011-12-16 19:33:39 -06:00
|
|
|
let dir = fs::connect(c.sourcedir, src.name);
|
|
|
|
let pkgfile = fs::connect(dir, "packages.json");
|
|
|
|
if !fs::path_exists(pkgfile) { ret; }
|
|
|
|
let pkgstr = io::read_whole_file_str(pkgfile);
|
|
|
|
let j = json::from_str(result::get(pkgstr));
|
|
|
|
alt j {
|
|
|
|
some(json::list(js)) {
|
|
|
|
for _j: json::json in *js {
|
|
|
|
alt _j {
|
|
|
|
json::dict(_p) {
|
2011-12-16 21:27:04 -06:00
|
|
|
load_one_source_package(src, _p);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
_ {
|
2011-12-16 22:15:13 -06:00
|
|
|
warn("Malformed source json: " + src.name +
|
|
|
|
" (non-dict pkg)");
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ {
|
|
|
|
warn("Malformed source json: " + src.name);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
fn build_cargo_options(argv: [str]) -> options {
|
|
|
|
let match = alt getopts::getopts(argv, opts()) {
|
|
|
|
result::ok(m) { m }
|
|
|
|
result::err(f) {
|
|
|
|
fail #fmt["%s", getopts::fail_str(f)];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let test = opt_present(match, "test");
|
2012-02-20 02:08:58 -06:00
|
|
|
let G = opt_present(match, "G");
|
|
|
|
let g = opt_present(match, "g");
|
|
|
|
let m = opt_present(match, "mode");
|
|
|
|
let is_install = vec::len(match.free) > 1u && match.free[1] == "install";
|
|
|
|
|
|
|
|
if G && g { fail "-G and -g both provided"; }
|
|
|
|
if g && m { fail "--mode and -g both provided"; }
|
|
|
|
if G && m { fail "--mode and -G both provided"; }
|
|
|
|
|
|
|
|
let mode = if is_install {
|
|
|
|
if G { system_mode }
|
|
|
|
else if g { user_mode }
|
|
|
|
else if m {
|
|
|
|
alt getopts::opt_str(match, "mode") {
|
|
|
|
"system" { system_mode }
|
|
|
|
"user" { user_mode }
|
|
|
|
"local" { local_mode }
|
|
|
|
_ { fail "argument to `mode` must be one of `system`" +
|
|
|
|
", `user`, or `local`";
|
|
|
|
}
|
2012-02-07 02:15:39 -06:00
|
|
|
}
|
2012-02-20 02:08:58 -06:00
|
|
|
} else { local_mode }
|
|
|
|
} else { system_mode };
|
2012-02-09 15:42:59 -06:00
|
|
|
|
2012-02-07 02:15:39 -06:00
|
|
|
{test: test, mode: mode, free: match.free}
|
2012-02-05 03:30:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn configure(opts: options) -> cargo {
|
2012-02-20 02:08:58 -06:00
|
|
|
let syscargo = result::get(get_cargo_sysroot());
|
2012-02-07 02:15:39 -06:00
|
|
|
let get_cargo_dir = alt opts.mode {
|
|
|
|
system_mode { get_cargo_sysroot }
|
|
|
|
user_mode { get_cargo_root }
|
|
|
|
local_mode { get_cargo_root_nearest }
|
2012-02-05 03:30:03 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
let p = alt get_cargo_dir() {
|
2012-02-07 02:15:39 -06:00
|
|
|
result::ok(p) { p }
|
|
|
|
result::err(e) { fail e }
|
2011-12-08 22:41:29 -06:00
|
|
|
};
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
let sources = map::new_str_hash::<source>();
|
2012-02-20 02:08:58 -06:00
|
|
|
try_parse_sources(fs::connect(syscargo, "sources.json"), sources);
|
|
|
|
try_parse_sources(fs::connect(syscargo, "local-sources.json"), sources);
|
2011-12-08 22:50:25 -06:00
|
|
|
let c = {
|
2011-12-20 18:59:37 -06:00
|
|
|
pgp: pgp::supported(),
|
2011-12-08 22:50:25 -06:00
|
|
|
root: p,
|
|
|
|
bindir: fs::connect(p, "bin"),
|
|
|
|
libdir: fs::connect(p, "lib"),
|
|
|
|
workdir: fs::connect(p, "work"),
|
2012-02-20 02:08:58 -06:00
|
|
|
sourcedir: fs::connect(syscargo, "sources"),
|
2012-01-18 21:16:14 -06:00
|
|
|
sources: sources,
|
2012-02-05 03:30:03 -06:00
|
|
|
opts: opts
|
2011-12-08 22:50:25 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
need_dir(c.root);
|
2011-12-16 19:33:39 -06:00
|
|
|
need_dir(c.sourcedir);
|
2011-12-08 22:50:25 -06:00
|
|
|
need_dir(c.workdir);
|
|
|
|
need_dir(c.libdir);
|
|
|
|
need_dir(c.bindir);
|
2011-12-08 22:41:29 -06:00
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
sources.keys { |k|
|
|
|
|
let s = sources.get(k);
|
|
|
|
load_source_packages(c, s);
|
|
|
|
sources.insert(k, s);
|
2011-12-16 19:33:39 -06:00
|
|
|
};
|
|
|
|
|
2011-12-20 18:59:37 -06:00
|
|
|
if c.pgp {
|
|
|
|
pgp::init(c.root);
|
2012-02-13 19:06:20 -06:00
|
|
|
} else {
|
|
|
|
warn("command \"gpg\" is not found");
|
|
|
|
warn("you have to install \"gpg\" from source " +
|
|
|
|
" or package manager to get it to work correctly");
|
2011-12-20 18:59:37 -06:00
|
|
|
}
|
|
|
|
|
2011-12-08 22:50:25 -06:00
|
|
|
c
|
2011-12-08 22:41:29 -06:00
|
|
|
}
|
|
|
|
|
2012-01-23 16:59:00 -06:00
|
|
|
fn for_each_package(c: cargo, b: fn(source, package)) {
|
2011-12-16 19:33:39 -06:00
|
|
|
c.sources.values({ |v|
|
2011-12-16 21:31:49 -06:00
|
|
|
for p in copy v.packages {
|
2011-12-16 21:08:25 -06:00
|
|
|
b(v, p);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2012-01-18 21:16:14 -06:00
|
|
|
// FIXME: deduplicate code with install_one_crate
|
2012-01-19 15:46:28 -06:00
|
|
|
fn test_one_crate(_c: cargo, _path: str, cf: str, _p: pkg) {
|
2012-01-18 21:24:07 -06:00
|
|
|
let buildpath = fs::connect(_path, "/test");
|
|
|
|
need_dir(buildpath);
|
|
|
|
#debug("Testing: %s -> %s", cf, buildpath);
|
2012-02-13 18:33:59 -06:00
|
|
|
let p = run::program_output(rustc_sysroot(),
|
|
|
|
["--out-dir", buildpath, "--test", cf]);
|
2012-01-18 21:24:07 -06:00
|
|
|
if p.status != 0 {
|
|
|
|
error(#fmt["rustc failed: %d\n%s\n%s", p.status, p.err, p.out]);
|
|
|
|
ret;
|
2011-12-08 22:41:29 -06:00
|
|
|
}
|
2012-01-18 21:24:07 -06:00
|
|
|
let new = fs::list_dir(buildpath);
|
|
|
|
for ct: str in new {
|
2012-01-21 13:59:10 -06:00
|
|
|
run::run_program(ct, []);
|
2012-01-18 21:24:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-18 21:16:14 -06:00
|
|
|
fn install_one_crate(c: cargo, _path: str, cf: str, _p: pkg) {
|
|
|
|
let buildpath = fs::connect(_path, "/build");
|
|
|
|
need_dir(buildpath);
|
|
|
|
#debug("Installing: %s -> %s", cf, buildpath);
|
2012-02-13 18:33:59 -06:00
|
|
|
let p = run::program_output(rustc_sysroot(),
|
|
|
|
["--out-dir", buildpath, cf]);
|
2012-01-18 21:16:14 -06:00
|
|
|
if p.status != 0 {
|
|
|
|
error(#fmt["rustc failed: %d\n%s\n%s", p.status, p.err, p.out]);
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
let new = fs::list_dir(buildpath);
|
|
|
|
let exec_suffix = os::exec_suffix();
|
|
|
|
for ct: str in new {
|
2011-12-16 03:08:24 -06:00
|
|
|
if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
|
2012-01-21 13:59:10 -06:00
|
|
|
(exec_suffix == "" && !str::starts_with(fs::basename(ct),
|
|
|
|
"lib")) {
|
2011-12-22 16:42:52 -06:00
|
|
|
#debug(" bin: %s", ct);
|
2011-12-08 22:41:29 -06:00
|
|
|
// FIXME: need libstd fs::copy or something
|
2011-12-08 22:50:25 -06:00
|
|
|
run::run_program("cp", [ct, c.bindir]);
|
2012-02-20 02:33:50 -06:00
|
|
|
if c.opts.mode == system_mode {
|
|
|
|
install_one_crate_to_sysroot(ct, "bin");
|
|
|
|
}
|
2011-12-08 22:41:29 -06:00
|
|
|
} else {
|
2011-12-22 16:42:52 -06:00
|
|
|
#debug(" lib: %s", ct);
|
2011-12-08 22:50:25 -06:00
|
|
|
run::run_program("cp", [ct, c.libdir]);
|
2012-02-20 02:33:50 -06:00
|
|
|
if c.opts.mode == system_mode {
|
|
|
|
install_one_crate_to_sysroot(ct, libdir());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn install_one_crate_to_sysroot(ct: str, target: str) {
|
|
|
|
alt os::get_exe_path() {
|
|
|
|
some(_path) {
|
|
|
|
let path = [_path, "..", target];
|
|
|
|
check vec::is_not_empty(path);
|
|
|
|
let target_dir = fs::normalize(fs::connect_many(path));
|
|
|
|
let p = run::program_output("cp", [ct, target_dir]);
|
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["Copying %s to %s is failed", ct, target_dir]);
|
|
|
|
}
|
2011-12-08 22:41:29 -06:00
|
|
|
}
|
2012-02-20 02:33:50 -06:00
|
|
|
none { }
|
2011-12-08 22:41:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-13 18:33:59 -06:00
|
|
|
fn rustc_sysroot() -> str {
|
|
|
|
alt os::get_exe_path() {
|
|
|
|
some(_path) {
|
|
|
|
let path = [_path, "..", "bin", "rustc"];
|
|
|
|
check vec::is_not_empty(path);
|
|
|
|
let rustc = fs::normalize(fs::connect_many(path));
|
|
|
|
#debug(" rustc: %s", rustc);
|
|
|
|
rustc
|
|
|
|
}
|
|
|
|
none { "rustc" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-08 22:50:25 -06:00
|
|
|
fn install_source(c: cargo, path: str) {
|
2011-12-22 16:42:52 -06:00
|
|
|
#debug("source: %s", path);
|
2011-12-01 21:37:56 -06:00
|
|
|
fs::change_dir(path);
|
|
|
|
let contents = fs::list_dir(".");
|
|
|
|
|
2011-12-22 16:42:52 -06:00
|
|
|
#debug("contents: %s", str::connect(contents, ", "));
|
2011-12-01 21:37:56 -06:00
|
|
|
|
2011-12-16 03:08:24 -06:00
|
|
|
let cratefiles =
|
2011-12-16 08:27:50 -06:00
|
|
|
vec::filter::<str>(contents, { |n| str::ends_with(n, ".rc") });
|
2011-12-01 21:37:56 -06:00
|
|
|
|
2011-12-08 22:41:29 -06:00
|
|
|
if vec::is_empty(cratefiles) {
|
|
|
|
fail "This doesn't look like a rust package (no .rc files).";
|
2011-12-01 21:37:56 -06:00
|
|
|
}
|
|
|
|
|
2011-12-08 22:41:29 -06:00
|
|
|
for cf: str in cratefiles {
|
|
|
|
let p = load_pkg(cf);
|
|
|
|
alt p {
|
2012-01-19 00:37:22 -06:00
|
|
|
none { cont; }
|
2011-12-08 22:41:29 -06:00
|
|
|
some(_p) {
|
2012-02-05 03:30:03 -06:00
|
|
|
if c.opts.test {
|
2012-01-18 21:16:14 -06:00
|
|
|
test_one_crate(c, path, cf, _p);
|
|
|
|
}
|
2011-12-08 22:50:25 -06:00
|
|
|
install_one_crate(c, path, cf, _p);
|
2011-12-08 22:41:29 -06:00
|
|
|
}
|
|
|
|
}
|
2011-12-01 21:37:56 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-31 19:05:20 -06:00
|
|
|
fn install_git(c: cargo, wd: str, url: str, ref: option<str>) {
|
2011-12-16 21:08:25 -06:00
|
|
|
run::run_program("git", ["clone", url, wd]);
|
2011-12-20 22:41:22 -06:00
|
|
|
if option::is_some::<str>(ref) {
|
|
|
|
let r = option::get::<str>(ref);
|
|
|
|
fs::change_dir(wd);
|
|
|
|
run::run_program("git", ["checkout", r]);
|
|
|
|
}
|
|
|
|
|
2011-12-08 23:39:41 -06:00
|
|
|
install_source(c, wd);
|
2011-12-08 23:34:06 -06:00
|
|
|
}
|
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
fn install_curl(c: cargo, wd: str, url: str) {
|
|
|
|
let tarpath = fs::connect(wd, "pkg.tar");
|
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o",
|
|
|
|
tarpath, url]);
|
|
|
|
if p.status != 0 {
|
|
|
|
fail #fmt["Fetch of %s failed: %s", url, p.err];
|
|
|
|
}
|
2011-12-08 23:39:41 -06:00
|
|
|
run::run_program("tar", ["-x", "--strip-components=1",
|
2011-12-16 21:08:25 -06:00
|
|
|
"-C", wd, "-f", tarpath]);
|
2011-12-16 21:27:04 -06:00
|
|
|
install_source(c, wd);
|
2011-12-16 21:08:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn install_file(c: cargo, wd: str, path: str) {
|
|
|
|
run::run_program("tar", ["-x", "--strip-components=1",
|
|
|
|
"-C", wd, "-f", path]);
|
2011-12-08 23:39:41 -06:00
|
|
|
install_source(c, wd);
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
|
2011-12-16 21:08:25 -06:00
|
|
|
fn install_package(c: cargo, wd: str, pkg: package) {
|
|
|
|
info("Installing with " + pkg.method + " from " + pkg.url + "...");
|
|
|
|
if pkg.method == "git" {
|
2011-12-20 22:41:22 -06:00
|
|
|
install_git(c, wd, pkg.url, pkg.ref);
|
2011-12-16 21:08:25 -06:00
|
|
|
} else if pkg.method == "http" {
|
|
|
|
install_curl(c, wd, pkg.url);
|
|
|
|
} else if pkg.method == "file" {
|
|
|
|
install_file(c, wd, pkg.url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-24 10:08:58 -06:00
|
|
|
fn cargo_suggestion(c: cargo, syncing: bool, fallback: fn())
|
|
|
|
{
|
|
|
|
if c.sources.size() == 0u {
|
|
|
|
error("No sources defined. You may wish to run " +
|
|
|
|
"\"cargo init\" then \"cargo sync\".");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
if !syncing {
|
|
|
|
let npkg = 0u;
|
|
|
|
c.sources.values({ |v| npkg += vec::len(v.packages) });
|
|
|
|
if npkg == 0u {
|
|
|
|
error("No packages known. You may wish to run " +
|
|
|
|
"\"cargo sync\".");
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fallback();
|
|
|
|
}
|
|
|
|
|
2011-12-15 19:27:55 -06:00
|
|
|
fn install_uuid(c: cargo, wd: str, uuid: str) {
|
2011-12-16 19:33:39 -06:00
|
|
|
let ps = [];
|
2011-12-16 21:08:25 -06:00
|
|
|
for_each_package(c, { |s, p|
|
|
|
|
info(#fmt["%s ? %s", p.uuid, uuid]);
|
2011-12-16 19:33:39 -06:00
|
|
|
if p.uuid == uuid {
|
2011-12-16 21:08:25 -06:00
|
|
|
vec::grow(ps, 1u, (s, p));
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
});
|
2011-12-16 21:08:25 -06:00
|
|
|
if vec::len(ps) == 1u {
|
2011-12-16 21:27:04 -06:00
|
|
|
let (_, p) = ps[0];
|
2011-12-16 21:08:25 -06:00
|
|
|
install_package(c, wd, p);
|
|
|
|
ret;
|
|
|
|
} else if vec::len(ps) == 0u {
|
2012-01-24 10:08:58 -06:00
|
|
|
cargo_suggestion(c, false, { || error("No packages match uuid."); });
|
2011-12-16 21:08:25 -06:00
|
|
|
ret;
|
|
|
|
}
|
|
|
|
error("Found multiple packages:");
|
|
|
|
for (s,p) in ps {
|
|
|
|
info(" " + s.name + "/" + p.uuid + " (" + p.name + ")");
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
2011-12-15 19:27:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn install_named(c: cargo, wd: str, name: str) {
|
2011-12-16 19:33:39 -06:00
|
|
|
let ps = [];
|
2011-12-16 21:08:25 -06:00
|
|
|
for_each_package(c, { |s, p|
|
2011-12-16 19:33:39 -06:00
|
|
|
if p.name == name {
|
2011-12-16 21:08:25 -06:00
|
|
|
vec::grow(ps, 1u, (s, p));
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
});
|
2011-12-16 21:08:25 -06:00
|
|
|
if vec::len(ps) == 1u {
|
2011-12-16 21:27:04 -06:00
|
|
|
let (_, p) = ps[0];
|
2011-12-16 21:08:25 -06:00
|
|
|
install_package(c, wd, p);
|
|
|
|
ret;
|
|
|
|
} else if vec::len(ps) == 0u {
|
2012-01-24 10:08:58 -06:00
|
|
|
cargo_suggestion(c, false, { || error("No packages match name."); });
|
2011-12-16 21:08:25 -06:00
|
|
|
ret;
|
|
|
|
}
|
|
|
|
error("Found multiple packages:");
|
|
|
|
for (s,p) in ps {
|
|
|
|
info(" " + s.name + "/" + p.uuid + " (" + p.name + ")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn install_uuid_specific(c: cargo, wd: str, src: str, uuid: str) {
|
|
|
|
alt c.sources.find(src) {
|
|
|
|
some(s) {
|
2011-12-16 21:31:49 -06:00
|
|
|
if vec::any(copy s.packages, { |p|
|
2011-12-16 21:08:25 -06:00
|
|
|
if p.uuid == uuid {
|
|
|
|
install_package(c, wd, p);
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}) { ret; }
|
|
|
|
}
|
|
|
|
_ { }
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
2011-12-16 21:08:25 -06:00
|
|
|
error("Can't find package " + src + "/" + uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn install_named_specific(c: cargo, wd: str, src: str, name: str) {
|
|
|
|
alt c.sources.find(src) {
|
|
|
|
some(s) {
|
2011-12-16 21:31:49 -06:00
|
|
|
if vec::any(copy s.packages, { |p|
|
2011-12-16 21:08:25 -06:00
|
|
|
if p.name == name {
|
|
|
|
install_package(c, wd, p);
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}) { ret; }
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
error("Can't find package " + src + "/" + name);
|
2011-12-15 19:27:55 -06:00
|
|
|
}
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
fn cmd_install(c: cargo) unsafe {
|
2011-11-30 17:57:46 -06:00
|
|
|
// cargo install <pkg>
|
2012-02-05 03:30:03 -06:00
|
|
|
if vec::len(c.opts.free) < 3u {
|
2011-11-30 17:57:46 -06:00
|
|
|
cmd_usage();
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
let target = c.opts.free[2];
|
2012-01-18 21:16:14 -06:00
|
|
|
|
2011-12-08 23:39:41 -06:00
|
|
|
let wd = alt tempfile::mkdtemp(c.workdir + fs::path_sep(), "") {
|
|
|
|
some(_wd) { _wd }
|
2012-01-19 00:37:22 -06:00
|
|
|
none { fail "needed temp dir"; }
|
2011-12-08 23:39:41 -06:00
|
|
|
};
|
|
|
|
|
2012-01-18 21:16:14 -06:00
|
|
|
if str::starts_with(target, "uuid:") {
|
|
|
|
let uuid = rest(target, 5u);
|
2012-02-23 01:46:45 -06:00
|
|
|
alt str::index(uuid, '/') {
|
2012-02-11 05:20:45 -06:00
|
|
|
option::some(idx) {
|
2012-02-23 01:46:45 -06:00
|
|
|
let source = str::slice(uuid, 0u, idx);
|
2012-02-23 03:44:04 -06:00
|
|
|
uuid = str::slice(uuid, idx + 1u, str::len(uuid));
|
2012-02-11 05:20:45 -06:00
|
|
|
install_uuid_specific(c, wd, source, uuid);
|
|
|
|
}
|
|
|
|
option::none {
|
|
|
|
install_uuid(c, wd, uuid);
|
|
|
|
}
|
2011-12-16 21:08:25 -06:00
|
|
|
}
|
2011-12-15 19:27:55 -06:00
|
|
|
} else {
|
2012-01-18 21:16:14 -06:00
|
|
|
let name = target;
|
2012-02-23 01:46:45 -06:00
|
|
|
alt str::index(name, '/') {
|
2012-02-11 05:20:45 -06:00
|
|
|
option::some(idx) {
|
2012-02-23 01:46:45 -06:00
|
|
|
let source = str::slice(name, 0u, idx);
|
2012-02-23 03:44:04 -06:00
|
|
|
name = str::slice(name, idx + 1u, str::len(name));
|
2012-02-11 05:20:45 -06:00
|
|
|
install_named_specific(c, wd, source, name);
|
|
|
|
}
|
|
|
|
option::none {
|
|
|
|
install_named(c, wd, name);
|
|
|
|
}
|
2011-12-16 21:08:25 -06:00
|
|
|
}
|
2011-12-01 21:37:56 -06:00
|
|
|
}
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
|
2011-12-16 19:33:39 -06:00
|
|
|
fn sync_one(c: cargo, name: str, src: source) {
|
|
|
|
let dir = fs::connect(c.sourcedir, name);
|
2011-12-20 18:59:37 -06:00
|
|
|
let pkgfile = fs::connect(dir, "packages.json.new");
|
|
|
|
let destpkgfile = fs::connect(dir, "packages.json");
|
|
|
|
let sigfile = fs::connect(dir, "packages.json.sig");
|
|
|
|
let keyfile = fs::connect(dir, "key.gpg");
|
2011-12-16 19:33:39 -06:00
|
|
|
let url = src.url;
|
|
|
|
need_dir(dir);
|
2011-12-16 21:08:25 -06:00
|
|
|
info(#fmt["fetching source %s...", name]);
|
2011-12-16 19:33:39 -06:00
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o", pkgfile, url]);
|
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["fetch for source %s (url %s) failed", name, url]);
|
|
|
|
} else {
|
|
|
|
info(#fmt["fetched source: %s", name]);
|
|
|
|
}
|
2011-12-20 18:59:37 -06:00
|
|
|
alt src.sig {
|
|
|
|
some(u) {
|
2011-12-20 20:52:50 -06:00
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o", sigfile,
|
|
|
|
u]);
|
2011-12-20 18:59:37 -06:00
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["fetch for source %s (sig %s) failed", name, u]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
alt src.key {
|
|
|
|
some(u) {
|
2011-12-20 20:52:50 -06:00
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o", keyfile,
|
|
|
|
u]);
|
2011-12-20 18:59:37 -06:00
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["fetch for source %s (key %s) failed", name, u]);
|
|
|
|
}
|
|
|
|
pgp::add(c.root, keyfile);
|
|
|
|
}
|
|
|
|
_ { }
|
|
|
|
}
|
|
|
|
alt (src.sig, src.key, src.keyfp) {
|
|
|
|
(some(_), some(_), some(f)) {
|
|
|
|
let r = pgp::verify(c.root, pkgfile, sigfile, f);
|
|
|
|
if !r {
|
2011-12-20 20:52:50 -06:00
|
|
|
warn(#fmt["signature verification failed for source %s",
|
|
|
|
name]);
|
2011-12-20 18:59:37 -06:00
|
|
|
ret;
|
|
|
|
} else {
|
|
|
|
info(#fmt["signature ok for source %s", name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ {
|
|
|
|
info(#fmt["no signature for source %s", name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
run::run_program("cp", [pkgfile, destpkgfile]);
|
2011-12-16 19:33:39 -06:00
|
|
|
}
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
fn cmd_sync(c: cargo) {
|
|
|
|
if vec::len(c.opts.free) == 3u {
|
|
|
|
sync_one(c, c.opts.free[2], c.sources.get(c.opts.free[2]));
|
2011-12-16 19:33:39 -06:00
|
|
|
} else {
|
2012-01-24 10:08:58 -06:00
|
|
|
cargo_suggestion(c, true, { || } );
|
2011-12-16 19:33:39 -06:00
|
|
|
c.sources.items { |k, v|
|
|
|
|
sync_one(c, k, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-20 20:52:50 -06:00
|
|
|
fn cmd_init(c: cargo) {
|
2011-12-20 18:59:37 -06:00
|
|
|
let srcurl = "http://www.rust-lang.org/cargo/sources.json";
|
|
|
|
let sigurl = "http://www.rust-lang.org/cargo/sources.json.sig";
|
|
|
|
|
|
|
|
let srcfile = fs::connect(c.root, "sources.json.new");
|
|
|
|
let sigfile = fs::connect(c.root, "sources.json.sig");
|
|
|
|
let destsrcfile = fs::connect(c.root, "sources.json");
|
|
|
|
|
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o", srcfile, srcurl]);
|
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["fetch of sources.json failed: %s", p.out]);
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
let p = run::program_output("curl", ["-f", "-s", "-o", sigfile, sigurl]);
|
|
|
|
if p.status != 0 {
|
|
|
|
warn(#fmt["fetch of sources.json.sig failed: %s", p.out]);
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
let r = pgp::verify(c.root, srcfile, sigfile, pgp::signing_key_fp());
|
|
|
|
if !r {
|
|
|
|
warn(#fmt["signature verification failed for sources.json"]);
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
info(#fmt["signature ok for sources.json"]);
|
|
|
|
run::run_program("cp", [srcfile, destsrcfile]);
|
2012-02-07 02:15:39 -06:00
|
|
|
|
|
|
|
info(#fmt["Initialized .cargo in %s", c.root]);
|
2011-12-20 18:59:37 -06:00
|
|
|
}
|
|
|
|
|
2011-12-20 19:41:23 -06:00
|
|
|
fn print_pkg(s: source, p: package) {
|
|
|
|
let m = s.name + "/" + p.name + " (" + p.uuid + ")";
|
|
|
|
if vec::len(p.tags) > 0u {
|
|
|
|
m = m + " [" + str::connect(p.tags, ", ") + "]";
|
|
|
|
}
|
|
|
|
info(m);
|
2012-01-23 20:23:31 -06:00
|
|
|
if p.description != "" {
|
2012-01-23 21:50:32 -06:00
|
|
|
print(" >> " + p.description + "\n")
|
2012-01-23 20:23:31 -06:00
|
|
|
}
|
2011-12-20 19:41:23 -06:00
|
|
|
}
|
2012-02-05 03:30:03 -06:00
|
|
|
fn cmd_list(c: cargo) {
|
2011-12-20 19:41:23 -06:00
|
|
|
for_each_package(c, { |s, p|
|
2012-02-05 03:30:03 -06:00
|
|
|
if vec::len(c.opts.free) <= 2u || c.opts.free[2] == s.name {
|
2011-12-20 19:41:23 -06:00
|
|
|
print_pkg(s, p);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-02-05 03:30:03 -06:00
|
|
|
fn cmd_search(c: cargo) {
|
|
|
|
if vec::len(c.opts.free) < 3u {
|
2011-12-20 19:41:23 -06:00
|
|
|
cmd_usage();
|
|
|
|
ret;
|
|
|
|
}
|
|
|
|
let n = 0;
|
2012-02-05 03:30:03 -06:00
|
|
|
let name = c.opts.free[2];
|
|
|
|
let tags = vec::slice(c.opts.free, 3u, vec::len(c.opts.free));
|
2011-12-20 19:41:23 -06:00
|
|
|
for_each_package(c, { |s, p|
|
|
|
|
if (str::contains(p.name, name) || name == "*") &&
|
2012-02-11 19:54:49 -06:00
|
|
|
vec::all(tags, { |t| vec::contains(p.tags, t) }) {
|
2011-12-20 19:41:23 -06:00
|
|
|
print_pkg(s, p);
|
|
|
|
n += 1;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
info(#fmt["Found %d packages.", n]);
|
|
|
|
}
|
|
|
|
|
2011-11-30 17:57:46 -06:00
|
|
|
fn cmd_usage() {
|
2012-02-07 02:15:39 -06:00
|
|
|
print("Usage: cargo <verb> [options] [args...]" +
|
|
|
|
"
|
|
|
|
|
|
|
|
init Set up .cargo
|
2012-02-20 02:33:50 -06:00
|
|
|
install [options] [source/]package-name Install by name
|
|
|
|
install [options] uuid:[source/]package-uuid Install by uuid
|
2012-02-07 02:15:39 -06:00
|
|
|
list [source] List packages
|
|
|
|
search <name | '*'> [tags...] Search packages
|
|
|
|
sync Sync all sources
|
|
|
|
usage This
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
2012-02-20 02:33:50 -06:00
|
|
|
cargo install
|
|
|
|
|
2012-02-07 02:15:39 -06:00
|
|
|
--mode=[system,user,local] change mode as (system/user/local)
|
|
|
|
-g equivalent to --mode=user
|
|
|
|
-G equivalent to --mode=system
|
|
|
|
|
|
|
|
NOTE:
|
2012-02-20 02:33:50 -06:00
|
|
|
\"cargo install\" installs bin/libs to local-level .cargo by default.
|
|
|
|
To install them into user-level .cargo, use option -g/--mode=user.
|
|
|
|
To install them into bin/lib on sysroot, use option -G/--mode=system.
|
2012-02-07 02:15:39 -06:00
|
|
|
");
|
2011-11-30 17:57:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main(argv: [str]) {
|
2012-02-05 03:30:03 -06:00
|
|
|
let o = build_cargo_options(argv);
|
|
|
|
|
|
|
|
if vec::len(o.free) < 2u {
|
2011-11-30 17:57:46 -06:00
|
|
|
cmd_usage();
|
|
|
|
ret;
|
|
|
|
}
|
2012-02-05 03:30:03 -06:00
|
|
|
|
|
|
|
let c = configure(o);
|
|
|
|
|
|
|
|
alt o.free[1] {
|
2011-12-20 20:52:50 -06:00
|
|
|
"init" { cmd_init(c); }
|
2012-02-05 03:30:03 -06:00
|
|
|
"install" { cmd_install(c); }
|
|
|
|
"list" { cmd_list(c); }
|
|
|
|
"search" { cmd_search(c); }
|
|
|
|
"sync" { cmd_sync(c); }
|
2011-11-30 17:57:46 -06:00
|
|
|
"usage" { cmd_usage(); }
|
|
|
|
_ { cmd_usage(); }
|
|
|
|
}
|
|
|
|
}
|