+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-// cargo.rs - Rust package manager
-
-// Local Variables:
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-
-#[link(name = "cargo",
- vers = "0.6",
- uuid = "9ff87a04-8fed-4295-9ff8-f99bb802650b",
- url = "https://github.com/mozilla/rust/tree/master/src/cargo")];
-
-#[crate_type = "lib"];
-
-#[no_core];
-
-#[legacy_modes];
-
-#[allow(vecs_implicitly_copyable,
- non_implicitly_copyable_typarams)];
-#[allow(non_camel_case_types)];
-#[allow(deprecated_mode)];
-#[allow(deprecated_pattern)];
-#[allow(deprecated_self)];
-
-extern mod core(vers = "0.6");
-extern mod std(vers = "0.6");
-extern mod rustc(vers = "0.6");
-extern mod syntax(vers = "0.6");
-
-mod pgp;
-
-use rustc::metadata::filesearch::{get_cargo_root, get_cargo_root_nearest};
-use rustc::metadata::filesearch::{get_cargo_sysroot, libdir};
-
-use core::*;
-
-use core::dvec::DVec;
-use core::io::WriterUtil;
-use core::result::{Ok, Err};
-use core::hashmap::linear::LinearMap;
-use std::getopts::{optflag, optopt, opt_present};
-use std::oldmap::HashMap;
-use std::{oldmap, json, tempfile, term, sort, getopts};
-use syntax::codemap::span;
-use syntax::diagnostic::span_handler;
-use syntax::diagnostic;
-use syntax::{ast, codemap, parse, visit, attr};
-
-pub struct Package {
- name: ~str,
- uuid: ~str,
- url: ~str,
- method: ~str,
- description: ~str,
- reference: Option<~str>,
- tags: ~[~str],
- versions: ~[(~str, ~str)]
-}
-
-pub impl cmp::Ord for Package {
- pure fn lt(&self, other: &Package) -> bool {
- if (*self).name.lt(&(*other).name) { return true; }
- if (*other).name.lt(&(*self).name) { return false; }
- if (*self).uuid.lt(&(*other).uuid) { return true; }
- if (*other).uuid.lt(&(*self).uuid) { return false; }
- if (*self).url.lt(&(*other).url) { return true; }
- if (*other).url.lt(&(*self).url) { return false; }
- if (*self).method.lt(&(*other).method) { return true; }
- if (*other).method.lt(&(*self).method) { return false; }
- if (*self).description.lt(&(*other).description) { return true; }
- if (*other).description.lt(&(*self).description) { return false; }
- if (*self).tags.lt(&(*other).tags) { return true; }
- if (*other).tags.lt(&(*self).tags) { return false; }
- if (*self).versions.lt(&(*other).versions) { return true; }
- return false;
- }
- pure fn le(&self, other: &Package) -> bool { !(*other).lt(&(*self)) }
- pure fn ge(&self, other: &Package) -> bool { !(*self).lt(other) }
- pure fn gt(&self, other: &Package) -> bool { (*other).lt(&(*self)) }
-}
-
-pub struct Source {
- name: ~str,
- mut url: ~str,
- mut method: ~str,
- mut key: Option<~str>,
- mut keyfp: Option<~str>,
- packages: DVec<Package>
-}
-
-pub struct Cargo {
- pgp: bool,
- root: Path,
- installdir: Path,
- bindir: Path,
- libdir: Path,
- workdir: Path,
- sourcedir: Path,
- sources: oldmap::HashMap<~str, @Source>,
- mut current_install: ~str,
- dep_cache: oldmap::HashMap<~str, bool>,
- opts: Options
-}
-
-pub struct Crate {
- name: ~str,
- vers: ~str,
- uuid: ~str,
- desc: Option<~str>,
- sigs: Option<~str>,
- crate_type: Option<~str>,
- deps: ~[~str]
-}
-
-pub struct Options {
- test: bool,
- mode: Mode,
- free: ~[~str],
- help: bool,
-}
-
-#[deriving_eq]
-pub enum Mode { SystemMode, UserMode, LocalMode }
-
-pub fn opts() -> ~[getopts::Opt] {
- ~[optflag(~"g"), optflag(~"G"), optflag(~"test"),
- optflag(~"h"), optflag(~"help")]
-}
-
-pub fn info(msg: ~str) {
- let out = io::stdout();
-
- if term::color_supported() {
- term::fg(out, term::color_green);
- out.write_str(~"info: ");
- term::reset(out);
- out.write_line(msg);
- } else { out.write_line(~"info: " + msg); }
-}
-
-pub fn warn(msg: ~str) {
- let out = io::stdout();
-
- if term::color_supported() {
- term::fg(out, term::color_yellow);
- out.write_str(~"warning: ");
- term::reset(out);
- out.write_line(msg);
- }else { out.write_line(~"warning: " + msg); }
-}
-
-pub fn error(msg: ~str) {
- let out = io::stdout();
-
- if term::color_supported() {
- term::fg(out, term::color_red);
- out.write_str(~"error: ");
- term::reset(out);
- out.write_line(msg);
- }
- else { out.write_line(~"error: " + msg); }
-}
-
-pub fn is_uuid(id: ~str) -> bool {
- let parts = str::split_str(id, ~"-");
- if vec::len(parts) == 5u {
- let mut correct = 0u;
- for vec::eachi(parts) |i, part| {
- fn is_hex_digit(+ch: char) -> bool {
- ('0' <= ch && ch <= '9') ||
- ('a' <= ch && ch <= 'f') ||
- ('A' <= ch && ch <= 'F')
- }
-
- if !part.all(is_hex_digit) {
- return false;
- }
-
- match i {
- 0u => {
- if part.len() == 8u {
- correct += 1u;
- }
- }
- 1u | 2u | 3u => {
- if part.len() == 4u {
- correct += 1u;
- }
- }
- 4u => {
- if part.len() == 12u {
- correct += 1u;
- }
- }
- _ => { }
- }
- }
- if correct >= 5u {
- return true;
- }
- }
- return false;
-}
-
-#[test]
-pub fn test_is_uuid() {
- assert is_uuid(~"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaafAF09");
- assert !is_uuid(~"aaaaaaaa-aaaa-aaaa-aaaaa-aaaaaaaaaaaa");
- assert !is_uuid(~"");
- assert !is_uuid(~"aaaaaaaa-aaa -aaaa-aaaa-aaaaaaaaaaaa");
- assert !is_uuid(~"aaaaaaaa-aaa!-aaaa-aaaa-aaaaaaaaaaaa");
- assert !is_uuid(~"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa-a");
- assert !is_uuid(~"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaป");
-}
-
-// FIXME (#2661): implement url/URL parsing so we don't have to resort
-// to weak checks
-
-pub fn has_archive_extension(p: ~str) -> bool {
- str::ends_with(p, ~".tar") ||
- str::ends_with(p, ~".tar.gz") ||
- str::ends_with(p, ~".tar.bz2") ||
- str::ends_with(p, ~".tar.Z") ||
- str::ends_with(p, ~".tar.lz") ||
- str::ends_with(p, ~".tar.xz") ||
- str::ends_with(p, ~".tgz") ||
- str::ends_with(p, ~".tbz") ||
- str::ends_with(p, ~".tbz2") ||
- str::ends_with(p, ~".tb2") ||
- str::ends_with(p, ~".taz") ||
- str::ends_with(p, ~".tlz") ||
- str::ends_with(p, ~".txz")
-}
-
-pub fn is_archive_path(u: ~str) -> bool {
- has_archive_extension(u) && os::path_exists(&Path(u))
-}
-
-pub fn is_archive_url(u: ~str) -> bool {
- // FIXME (#2661): this requires the protocol bit - if we had proper
- // url parsing, we wouldn't need it
-
- match str::find_str(u, ~"://") {
- option::Some(_) => has_archive_extension(u),
- _ => false
- }
-}
-
-pub fn is_git_url(url: ~str) -> bool {
- if str::ends_with(url, ~"/") { str::ends_with(url, ~".git/") }
- else {
- str::starts_with(url, ~"git://") || str::ends_with(url, ~".git")
- }
-}
-
-pub fn assume_source_method(url: ~str) -> ~str {
- if is_git_url(url) {
- return ~"git";
- }
- if str::starts_with(url, ~"file://") || os::path_exists(&Path(url)) {
- return ~"file";
- }
-
- ~"curl"
-}
-
-pub fn load_link(mis: ~[@ast::meta_item]) -> (Option<~str>,
- Option<~str>,
- Option<~str>) {
- let mut name = None;
- let mut vers = None;
- let mut uuid = None;
- for mis.each |a| {
- match a.node {
- ast::meta_name_value(v, codemap::spanned { node: ast::lit_str(s),
- _ }) => {
- match v {
- ~"name" => name = Some(*s),
- ~"vers" => vers = Some(*s),
- ~"uuid" => uuid = Some(*s),
- _ => { }
- }
- }
- _ => fail!(~"load_link: meta items must be name-values")
- }
- }
- (name, vers, uuid)
-}
-
-pub fn load_crate(filename: &Path) -> Option<Crate> {
- let sess = parse::new_parse_sess(None);
- let c = parse::parse_crate_from_file(filename, ~[], sess);
-
- let mut name = None;
- let mut vers = None;
- let mut uuid = None;
- let mut desc = None;
- let mut sigs = None;
- let mut crate_type = None;
-
- for c.node.attrs.each |a| {
- match a.node.value.node {
- ast::meta_name_value(v, codemap::spanned { node: ast::lit_str(_),
- _ }) => {
- match v {
- ~"desc" => desc = Some(v),
- ~"sigs" => sigs = Some(v),
- ~"crate_type" => crate_type = Some(v),
- _ => { }
- }
- }
- ast::meta_list(v, mis) => {
- if v == ~"link" {
- let (n, v, u) = load_link(mis);
- name = n;
- vers = v;
- uuid = u;
- }
- }
- _ => {
- fail!(~"crate attributes may not contain " +
- ~"meta_words");
- }
- }
- }
-
- struct Env {
- mut deps: ~[~str]
- }
-
- fn goto_view_item(ps: syntax::parse::parse_sess, e: @Env,
- i: @ast::view_item) {
- match i.node {
- ast::view_item_use(ident, metas, _) => {
- let name_items =
- attr::find_meta_items_by_name(metas, ~"name");
- let m = if name_items.is_empty() {
- metas + ~[attr::mk_name_value_item_str(
- ~"name", *ps.interner.get(ident))]
- } else {
- metas
- };
- let mut attr_name = ident;
- let mut attr_vers = ~"";
- let mut attr_from = ~"";
-
- for m.each |item| {
- match attr::get_meta_item_value_str(*item) {
- Some(value) => {
- let name = attr::get_meta_item_name(*item);
-
- match name {
- ~"vers" => attr_vers = value,
- ~"from" => attr_from = value,
- _ => ()
- }
- }
- None => ()
- }
- }
-
- let query = if !str::is_empty(attr_from) {
- attr_from
- } else {
- if !str::is_empty(attr_vers) {
- ps.interner.get(attr_name) + ~"@" + attr_vers
- } else { *ps.interner.get(attr_name) }
- };
-
- match *ps.interner.get(attr_name) {
- ~"std" | ~"core" => (),
- _ => e.deps.push(query)
- }
- }
- _ => ()
- }
- }
- fn goto_item(_e: @Env, _i: @ast::item) {
- }
-
- let e = @Env {
- mut deps: ~[]
- };
- let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
- visit_view_item: |a| goto_view_item(sess, e, a),
- visit_item: |a| goto_item(e, a),
- .. *visit::default_simple_visitor()
- });
-
- visit::visit_crate(*c, (), v);
-
- let deps = copy e.deps;
-
- match (name, vers, uuid) {
- (Some(name0), Some(vers0), Some(uuid0)) => {
- Some(Crate {
- name: name0,
- vers: vers0,
- uuid: uuid0,
- desc: desc,
- sigs: sigs,
- crate_type: crate_type,
- deps: deps })
- }
- _ => return None
- }
-}
-
-pub fn print(s: ~str) {
- io::stdout().write_line(s);
-}
-
-pub fn rest(s: ~str, start: uint) -> ~str {
- if (start >= str::len(s)) {
- ~""
- } else {
- str::slice(s, start, str::len(s))
- }
-}
-
-pub fn need_dir(s: &Path) {
- if os::path_is_dir(s) { return; }
- if !os::make_dir(s, 493_i32 /* oct: 755 */) {
- fail!(fmt!("can't make_dir %s", s.to_str()));
- }
-}
-
-pub fn valid_pkg_name(s: &str) -> bool {
- fn is_valid_digit(+c: char) -> bool {
- ('0' <= c && c <= '9') ||
- ('a' <= c && c <= 'z') ||
- ('A' <= c && c <= 'Z') ||
- c == '-' ||
- c == '_'
- }
-
- s.all(is_valid_digit)
-}
-
-pub fn parse_source(name: ~str, j: &json::Json) -> @Source {
- if !valid_pkg_name(name) {
- fail!(fmt!("'%s' is an invalid source name", name));
- }
-
- match *j {
- json::Object(ref j) => {
- let mut url = match j.find(&~"url") {
- Some(&json::String(u)) => copy u,
- _ => fail!(~"needed 'url' field in source")
- };
- let method = match j.find(&~"method") {
- Some(&json::String(u)) => copy u,
- _ => assume_source_method(url)
- };
- let key = match j.find(&~"key") {
- Some(&json::String(u)) => Some(copy u),
- _ => None
- };
- let keyfp = match j.find(&~"keyfp") {
- Some(&json::String(u)) => Some(copy u),
- _ => None
- };
- if method == ~"file" {
- url = os::make_absolute(&Path(url)).to_str();
- }
- return @Source {
- name: name,
- mut url: url,
- mut method: method,
- mut key: key,
- mut keyfp: keyfp,
- packages: DVec() };
- }
- _ => fail!(~"needed dict value in source")
- };
-}
-
-pub fn try_parse_sources(filename: &Path,
- sources: oldmap::HashMap<~str, @Source>) {
- if !os::path_exists(filename) { return; }
- let c = io::read_whole_file_str(filename);
- match json::from_str(c.get()) {
- Ok(json::Object(j)) => {
- for j.each |&(k, v)| {
- sources.insert(copy *k, parse_source(*k, v));
- debug!("source: %s", *k);
- }
- }
- Ok(_) => fail!(~"malformed sources.json"),
- Err(e) => fail!(fmt!("%s:%s", filename.to_str(), e.to_str()))
- }
-}
-
-pub fn load_one_source_package(src: @Source, p: &json::Object) {
- let name = match p.find(&~"name") {
- Some(&json::String(n)) => {
- if !valid_pkg_name(n) {
- warn(~"malformed source json: "
- + src.name + ~", '" + n + ~"'"+
- ~" is an invalid name (alphanumeric, underscores and" +
- ~" dashes only)");
- return;
- }
- n
- }
- _ => {
- warn(~"malformed source json: " + src.name + ~" (missing name)");
- return;
- }
- };
-
- let uuid = match p.find(&~"uuid") {
- Some(&json::String(n)) => {
- if !is_uuid(n) {
- warn(~"malformed source json: "
- + src.name + ~", '" + n + ~"'"+
- ~" is an invalid uuid");
- return;
- }
- copy n
- }
- _ => {
- warn(~"malformed source json: " + src.name + ~" (missing uuid)");
- return;
- }
- };
-
- let url = match p.find(&~"url") {
- Some(&json::String(n)) => copy n,
- _ => {
- warn(~"malformed source json: " + src.name + ~" (missing url)");
- return;
- }
- };
-
- let method = match p.find(&~"method") {
- Some(&json::String(n)) => copy n,
- _ => {
- warn(~"malformed source json: "
- + src.name + ~" (missing method)");
- return;
- }
- };
-
- let reference = match p.find(&~"ref") {
- Some(&json::String(n)) => Some(copy n),
- _ => None
- };
-
- let mut tags = ~[];
- match p.find(&~"tags") {
- Some(&json::List(ref js)) => {
- for js.each |j| {
- match *j {
- json::String(ref j) => tags.grow(1u, j),
- _ => ()
- }
- }
- }
- _ => ()
- }
-
- let description = match p.find(&~"description") {
- Some(&json::String(n)) => copy n,
- _ => {
- warn(~"malformed source json: " + src.name
- + ~" (missing description)");
- return;
- }
- };
-
- let newpkg = Package {
- name: name,
- uuid: uuid,
- url: url,
- method: method,
- description: description,
- reference: reference,
- tags: tags,
- versions: ~[]
- };
-
- match src.packages.position(|pkg| pkg.uuid == uuid) {
- Some(idx) => {
- src.packages.set_elt(idx, newpkg);
- log(debug, ~" updated package: " + src.name + ~"/" + name);
- }
- None => {
- src.packages.push(newpkg);
- }
- }
-
- log(debug, ~" loaded package: " + src.name + ~"/" + name);
-}
-
-pub fn load_source_info(c: &Cargo, src: @Source) {
- let dir = c.sourcedir.push(src.name);
- let srcfile = dir.push("source.json");
- if !os::path_exists(&srcfile) { return; }
- let srcstr = io::read_whole_file_str(&srcfile);
- match json::from_str(srcstr.get()) {
- Ok(ref json @ json::Object(_)) => {
- let o = parse_source(src.name, json);
-
- src.key = o.key;
- src.keyfp = o.keyfp;
- }
- Ok(_) => {
- warn(~"malformed source.json: " + src.name +
- ~"(source info is not a dict)");
- }
- Err(e) => {
- warn(fmt!("%s:%s", src.name, e.to_str()));
- }
- };
-}
-pub fn load_source_packages(c: &Cargo, src: @Source) {
- log(debug, ~"loading source: " + src.name);
- let dir = c.sourcedir.push(src.name);
- let pkgfile = dir.push("packages.json");
- if !os::path_exists(&pkgfile) { return; }
- let pkgstr = io::read_whole_file_str(&pkgfile);
- match json::from_str(pkgstr.get()) {
- Ok(json::List(ref js)) => {
- for js.each |j| {
- match *j {
- json::Object(ref p) => {
- load_one_source_package(src, *p);
- }
- _ => {
- warn(~"malformed source json: " + src.name +
- ~" (non-dict pkg)");
- }
- }
- }
- }
- Ok(_) => {
- warn(~"malformed packages.json: " + src.name +
- ~"(packages is not a list)");
- }
- Err(e) => {
- warn(fmt!("%s:%s", src.name, e.to_str()));
- }
- };
-}
-
-pub fn build_cargo_options(argv: ~[~str]) -> Options {
- let matches = &match getopts::getopts(argv, opts()) {
- result::Ok(m) => m,
- result::Err(f) => {
- fail!(fmt!("%s", getopts::fail_str(f)));
- }
- };
-
- let test = opt_present(matches, ~"test");
- let G = opt_present(matches, ~"G");
- let g = opt_present(matches, ~"g");
- let help = opt_present(matches, ~"h") || opt_present(matches, ~"help");
- let len = vec::len(matches.free);
-
- let is_install = len > 1u && matches.free[1] == ~"install";
- let is_uninstall = len > 1u && matches.free[1] == ~"uninstall";
-
- if G && g { fail!(~"-G and -g both provided"); }
-
- if !is_install && !is_uninstall && (g || G) {
- fail!(~"-g and -G are only valid for `install` and `uninstall|rm`");
- }
-
- let mode =
- if (!is_install && !is_uninstall) || g { UserMode }
- else if G { SystemMode }
- else { LocalMode };
-
- Options {test: test, mode: mode, free: matches.free, help: help}
-}
-
-pub fn configure(opts: Options) -> Cargo {
- let home = match get_cargo_root() {
- Ok(home) => home,
- Err(_err) => get_cargo_sysroot().get()
- };
-
- let get_cargo_dir = match opts.mode {
- SystemMode => get_cargo_sysroot,
- UserMode => get_cargo_root,
- LocalMode => get_cargo_root_nearest
- };
-
- let p = get_cargo_dir().get();
-
- let sources = HashMap();
- try_parse_sources(&home.push("sources.json"), sources);
- try_parse_sources(&home.push("local-sources.json"), sources);
-
- let dep_cache = HashMap();
-
- let mut c = Cargo {
- pgp: pgp::supported(),
- root: home,
- installdir: p,
- bindir: p.push("bin"),
- libdir: p.push("lib"),
- workdir: p.push("work"),
- sourcedir: home.push("sources"),
- sources: sources,
- mut current_install: ~"",
- dep_cache: dep_cache,
- opts: opts
- };
-
- need_dir(&c.root);
- need_dir(&c.installdir);
- need_dir(&c.sourcedir);
- need_dir(&c.workdir);
- need_dir(&c.libdir);
- need_dir(&c.bindir);
-
- for sources.each_key |&k| {
- let mut s = sources.get(&k);
- load_source_packages(&c, s);
- sources.insert(k, s);
- }
-
- if c.pgp {
- pgp::init(&c.root);
- } else {
- warn(~"command `gpg` was not found");
- warn(~"you have to install gpg from source " +
- ~" or package manager to get it to work correctly");
- }
-
- c
-}
-
-pub fn for_each_package(c: &Cargo, b: fn(s: @Source, p: &Package)) {
- for c.sources.each_value |&v| {
- for v.packages.each |p| {
- b(v, p);
- }
- }
-}
-
-// Runs all programs in directory <buildpath>
-pub fn run_programs(buildpath: &Path) {
- let newv = os::list_dir_path(buildpath);
- for newv.each |ct| {
- run::run_program(ct.to_str(), ~[]);
- }
-}
-
-// Runs rustc in <path + subdir> with the given flags
-// and returns <patho + subdir>
-pub fn run_in_buildpath(what: &str, path: &Path, subdir: &Path, cf: &Path,
- extra_flags: ~[~str]) -> Option<Path> {
- let buildpath = path.push_rel(subdir);
- need_dir(&buildpath);
- debug!("%s: %s -> %s", what, cf.to_str(), buildpath.to_str());
- let p = run::program_output(rustc_sysroot(),
- ~[~"--out-dir",
- buildpath.to_str(),
- cf.to_str()] + extra_flags);
- if p.status != 0 {
- error(fmt!("rustc failed: %d\n%s\n%s", p.status, p.err, p.out));
- return None;
- }
- Some(buildpath)
-}
-
-pub fn test_one_crate(_c: &Cargo, path: &Path, cf: &Path) {
- let buildpath = match run_in_buildpath(~"testing", path,
- &Path("test"),
- cf,
- ~[ ~"--test"]) {
- None => return,
- Some(bp) => bp
- };
- run_programs(&buildpath);
-}
-
-pub fn install_one_crate(c: &Cargo, path: &Path, cf: &Path) {
- let buildpath = match run_in_buildpath(~"installing", path,
- &Path("build"),
- cf, ~[]) {
- None => return,
- Some(bp) => bp
- };
- let newv = os::list_dir_path(&buildpath);
- let exec_suffix = str::from_slice(os::EXE_SUFFIX);
- for newv.each |ct| {
- if (exec_suffix != ~"" && str::ends_with(ct.to_str(),
- exec_suffix)) ||
- (exec_suffix == ~"" &&
- !str::starts_with(ct.filename().get(),
- ~"lib")) {
- debug!(" bin: %s", ct.to_str());
- install_to_dir(*ct, &c.bindir);
- if c.opts.mode == SystemMode {
- // FIXME (#2662): Put this file in PATH / symlink it so it can
- // be used as a generic executable
- // `cargo install -G rustray` and `rustray file.obj`
- }
- } else {
- debug!(" lib: %s", ct.to_str());
- install_to_dir(*ct, &c.libdir);
- }
- }
-}
-
-
-pub fn rustc_sysroot() -> ~str {
- match os::self_exe_path() {
- Some(path) => {
- let rustc = path.push_many([~"..", ~"bin", ~"rustc"]);
- debug!(" rustc: %s", rustc.to_str());
- rustc.to_str()
- }
- None => ~"rustc"
- }
-}
-
-pub fn install_source(c: &mut Cargo, path: &Path) {
- debug!("source: %s", path.to_str());
- os::change_dir(path);
-
- let mut cratefiles = ~[];
- for os::walk_dir(&Path(".")) |p| {
- if p.filetype() == Some(~".rc") {
- cratefiles.push(*p);
- }
- }
-
- if vec::is_empty(cratefiles) {
- fail!(~"this doesn't look like a rust package (no .rc files)");
- }
-
- for cratefiles.each |cf| {
- match load_crate(cf) {
- None => loop,
- Some(crate) => {
- for crate.deps.each |query| {
- // FIXME (#1356): handle cyclic dependencies
- // (n.b. #1356 says "Cyclic dependency is an error
- // condition")
-
- let wd = get_temp_workdir(c);
- install_query(c, &wd, *query);
- }
-
- os::change_dir(path);
-
- if c.opts.test {
- test_one_crate(c, path, cf);
- }
- install_one_crate(c, path, cf);
- }
- }
- }
-}
-
-pub fn install_git(c: &mut Cargo, wd: &Path, url: ~str,
- reference: Option<~str>) {
- run::program_output(~"git", ~[~"clone", url, wd.to_str()]);
- if reference.is_some() {
- let r = reference.get();
- os::change_dir(wd);
- run::run_program(~"git", ~[~"checkout", r]);
- }
-
- install_source(c, wd);
-}
-
-pub fn install_curl(c: &mut Cargo, wd: &Path, url: ~str) {
- let tarpath = wd.push("pkg.tar");
- let p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o",
- tarpath.to_str(), url]);
- if p.status != 0 {
- fail!(fmt!("fetch of %s failed: %s", url, p.err));
- }
- run::run_program(~"tar", ~[~"-x", ~"--strip-components=1",
- ~"-C", wd.to_str(),
- ~"-f", tarpath.to_str()]);
- install_source(c, wd);
-}
-
-pub fn install_file(c: &mut Cargo, wd: &Path, path: &Path) {
- run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
- ~"-C", wd.to_str(),
- ~"-f", path.to_str()]);
- install_source(c, wd);
-}
-
-pub fn install_package(c: &mut Cargo, src: ~str, wd: &Path, pkg: Package) {
- let url = copy pkg.url;
- let method = match pkg.method {
- ~"git" => ~"git",
- ~"file" => ~"file",
- _ => ~"curl"
- };
-
- info(fmt!("installing %s/%s via %s...", src, pkg.name, method));
-
- match method {
- ~"git" => install_git(c, wd, url, copy pkg.reference),
- ~"file" => install_file(c, wd, &Path(url)),
- ~"curl" => install_curl(c, wd, url),
- _ => ()
- }
-}
-
-pub fn cargo_suggestion(c: &Cargo, fallback: fn()) {
- if c.sources.is_empty() {
- error(~"no sources defined - you may wish to run " +
- ~"`cargo init`");
- return;
- }
- fallback();
-}
-
-pub fn install_uuid(c: &mut Cargo, wd: &Path, uuid: ~str) {
- let mut ps = ~[];
- for_each_package(c, |s, p| {
- if p.uuid == uuid {
- vec::push(&mut ps, (s.name, copy *p));
- }
- });
- if vec::len(ps) == 1u {
- let (sname, p) = copy ps[0];
- install_package(c, sname, wd, p);
- return;
- } else if vec::len(ps) == 0u {
- cargo_suggestion(c, || {
- error(~"can't find package: " + uuid);
- });
- return;
- }
- error(~"found multiple packages:");
- for ps.each |elt| {
- let (sname,p) = copy *elt;
- info(~" " + sname + ~"/" + p.uuid + ~" (" + p.name + ~")");
- }
-}
-
-pub fn install_named(c: &mut Cargo, wd: &Path, name: ~str) {
- let mut ps = ~[];
- for_each_package(c, |s, p| {
- if p.name == name {
- vec::push(&mut ps, (s.name, copy *p));
- }
- });
- if vec::len(ps) == 1u {
- let (sname, p) = copy ps[0];
- install_package(c, sname, wd, p);
- return;
- } else if vec::len(ps) == 0u {
- cargo_suggestion(c, || {
- error(~"can't find package: " + name);
- });
- return;
- }
- error(~"found multiple packages:");
- for ps.each |elt| {
- let (sname,p) = copy *elt;
- info(~" " + sname + ~"/" + p.uuid + ~" (" + p.name + ~")");
- }
-}
-
-pub fn install_uuid_specific(c: &mut Cargo, wd: &Path, src: ~str,
- uuid: ~str) {
- match c.sources.find(&src) {
- Some(s) => {
- for s.packages.each |p| {
- if p.uuid == uuid {
- install_package(c, src, wd, *p);
- return;
- }
- }
- }
- _ => ()
- }
- error(~"can't find package: " + src + ~"/" + uuid);
-}
-
-pub fn install_named_specific(c: &mut Cargo, wd: &Path, src: ~str,
- name: ~str) {
- match c.sources.find(&src) {
- Some(s) => {
- for s.packages.each |p| {
- if p.name == name {
- install_package(c, src, wd, *p);
- return;
- }
- }
- }
- _ => ()
- }
- error(~"can't find package: " + src + ~"/" + name);
-}
-
-pub fn cmd_uninstall(c: &Cargo) {
- if vec::len(c.opts.free) < 3u {
- cmd_usage();
- return;
- }
-
- let lib = &c.libdir;
- let bin = &c.bindir;
- let target = c.opts.free[2u];
-
- // FIXME (#2662): needs stronger pattern matching
- // FIXME (#2662): needs to uninstall from a specified location in a
- // cache instead of looking for it (binaries can be uninstalled by
- // name only)
-
- fn try_uninstall(p: &Path) -> bool {
- if os::remove_file(p) {
- info(~"uninstalled: '" + p.to_str() + ~"'");
- true
- } else {
- error(~"could not uninstall: '" +
- p.to_str() + ~"'");
- false
- }
- }
-
- if is_uuid(target) {
- for os::list_dir(lib).each |file| {
- match str::find_str(*file, ~"-" + target + ~"-") {
- Some(_) => if !try_uninstall(&lib.push(*file)) { return },
- None => ()
- }
- }
- error(~"can't find package with uuid: " + target);
- } else {
- for os::list_dir(lib).each |file| {
- match str::find_str(*file, ~"lib" + target + ~"-") {
- Some(_) => if !try_uninstall(&lib.push(*file)) { return },
- None => ()
- }
- }
- for os::list_dir(bin).each |file| {
- match str::find_str(*file, target) {
- Some(_) => if !try_uninstall(&lib.push(*file)) { return },
- None => ()
- }
- }
-
- error(~"can't find package with name: " + target);
- }
-}
-
-pub fn install_query(c: &mut Cargo, wd: &Path, target: ~str) {
- match c.dep_cache.find(&target) {
- Some(inst) => {
- if inst {
- return;
- }
- }
- None => ()
- }
-
- c.dep_cache.insert(target, true);
-
- if is_archive_path(target) {
- install_file(c, wd, &Path(target));
- return;
- } else if is_git_url(target) {
- let reference = if c.opts.free.len() >= 4u {
- Some(c.opts.free[3u])
- } else {
- None
- };
- install_git(c, wd, target, reference);
- } else if !valid_pkg_name(target) && has_archive_extension(target) {
- install_curl(c, wd, target);
- return;
- } else {
- let mut ps = copy target;
-
- match str::find_char(ps, '/') {
- option::Some(idx) => {
- let source = str::slice(ps, 0u, idx);
- ps = str::slice(ps, idx + 1u, str::len(ps));
- if is_uuid(ps) {
- install_uuid_specific(c, wd, source, ps);
- } else {
- install_named_specific(c, wd, source, ps);
- }
- }
- option::None => {
- if is_uuid(ps) {
- install_uuid(c, wd, ps);
- } else {
- install_named(c, wd, ps);
- }
- }
- }
- }
-
- // FIXME (#2662): This whole dep_cache and current_install thing is
- // a bit of a hack. It should be cleaned up in the future.
-
- if target == c.current_install {
- c.dep_cache.clear();
- c.current_install = ~"";
- }
-}
-
-pub fn get_temp_workdir(c: &Cargo) -> Path {
- match tempfile::mkdtemp(&c.workdir, "cargo") {
- Some(wd) => wd,
- None => fail!(fmt!("needed temp dir: %s",
- c.workdir.to_str()))
- }
-}
-
-pub fn cmd_install(c: &mut Cargo) {
- unsafe {
- let wd = get_temp_workdir(c);
-
- if vec::len(c.opts.free) == 2u {
- let cwd = os::getcwd();
- let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(),
- wd.to_str()]);
-
- if status != 0 {
- fail!(fmt!("could not copy directory: %s", cwd.to_str()));
- }
-
- install_source(c, &wd);
- return;
- }
-
- sync(c);
-
- let query = c.opts.free[2];
- c.current_install = query.to_str();
-
- install_query(c, &wd, query);
- }
-}
-
-pub fn sync(c: &Cargo) {
- for c.sources.each_key |&k| {
- let mut s = c.sources.get(&k);
- sync_one(c, s);
- c.sources.insert(k, s);
- }
-}
-
-pub fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool {
- let name = src.name;
- let srcfile = dir.push("source.json.new");
- let destsrcfile = dir.push("source.json");
- let pkgfile = dir.push("packages.json.new");
- let destpkgfile = dir.push("packages.json");
- let keyfile = dir.push("key.gpg");
- let srcsigfile = dir.push("source.json.sig");
- let sigfile = dir.push("packages.json.sig");
- let url = Path(src.url);
- let mut has_src_file = false;
-
- if !os::copy_file(&url.push("packages.json"), &pkgfile) {
- error(fmt!("fetch for source %s (url %s) failed",
- name, url.to_str()));
- return false;
- }
-
- if os::copy_file(&url.push("source.json"), &srcfile) {
- has_src_file = false;
- }
-
- os::copy_file(&url.push("source.json.sig"), &srcsigfile);
- os::copy_file(&url.push("packages.json.sig"), &sigfile);
-
- match copy src.key {
- Some(u) => {
- let p = run::program_output(~"curl",
- ~[~"-f", ~"-s",
- ~"-o", keyfile.to_str(), u]);
- if p.status != 0 {
- error(fmt!("fetch for source %s (key %s) failed", name, u));
- return false;
- }
- pgp::add(&c.root, &keyfile);
- }
- _ => ()
- }
- match (src.key, src.keyfp) {
- (Some(_), Some(f)) => {
- let r = pgp::verify(&c.root, &pkgfile, &sigfile);
-
- if !r {
- error(fmt!("signature verification failed for source %s with \
- key %s", name, f));
- return false;
- }
-
- if has_src_file {
- let e = pgp::verify(&c.root, &srcfile, &srcsigfile);
-
- if !e {
- error(fmt!("signature verification failed for source %s \
- with key %s", name, f));
- return false;
- }
- }
- }
- _ => ()
- }
-
- copy_warn(&pkgfile, &destpkgfile);
-
- if has_src_file {
- copy_warn(&srcfile, &destsrcfile);
- }
-
- os::remove_file(&keyfile);
- os::remove_file(&srcfile);
- os::remove_file(&srcsigfile);
- os::remove_file(&pkgfile);
- os::remove_file(&sigfile);
-
- info(fmt!("synced source: %s", name));
-
- return true;
-}
-
-pub fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool {
- let name = src.name;
- let srcfile = dir.push("source.json");
- let pkgfile = dir.push("packages.json");
- let keyfile = dir.push("key.gpg");
- let srcsigfile = dir.push("source.json.sig");
- let sigfile = dir.push("packages.json.sig");
- let url = src.url;
-
- fn rollback(name: ~str, dir: &Path, insecure: bool) {
- fn msg(name: ~str, insecure: bool) {
- error(fmt!("could not rollback source: %s", name));
-
- if insecure {
- warn(~"a past security check failed on source " +
- name + ~" and rolling back the source failed -"
- + ~" this source may be compromised");
- }
- }
-
- if !os::change_dir(dir) {
- msg(name, insecure);
- }
- else {
- let p = run::program_output(~"git", ~[~"reset", ~"--hard",
- ~"HEAD@{1}"]);
-
- if p.status != 0 {
- msg(name, insecure);
- }
- }
- }
-
- if !os::path_exists(&dir.push(".git")) {
- let p = run::program_output(~"git", ~[~"clone", url, dir.to_str()]);
-
- if p.status != 0 {
- error(fmt!("fetch for source %s (url %s) failed", name, url));
- return false;
- }
- }
- else {
- if !os::change_dir(dir) {
- error(fmt!("fetch for source %s (url %s) failed", name, url));
- return false;
- }
-
- let p = run::program_output(~"git", ~[~"pull"]);
-
- if p.status != 0 {
- error(fmt!("fetch for source %s (url %s) failed", name, url));
- return false;
- }
- }
-
- let has_src_file = os::path_exists(&srcfile);
-
- match copy src.key {
- Some(u) => {
- let p = run::program_output(~"curl",
- ~[~"-f", ~"-s",
- ~"-o", keyfile.to_str(), u]);
- if p.status != 0 {
- error(fmt!("fetch for source %s (key %s) failed", name, u));
- rollback(name, dir, false);
- return false;
- }
- pgp::add(&c.root, &keyfile);
- }
- _ => ()
- }
- match (src.key, src.keyfp) {
- (Some(_), Some(f)) => {
- let r = pgp::verify(&c.root, &pkgfile, &sigfile);
-
- if !r {
- error(fmt!("signature verification failed for source %s with \
- key %s", name, f));
- rollback(name, dir, false);
- return false;
- }
-
- if has_src_file {
- let e = pgp::verify(&c.root, &srcfile, &srcsigfile);
-
- if !e {
- error(fmt!("signature verification failed for source %s \
- with key %s", name, f));
- rollback(name, dir, false);
- return false;
- }
- }
- }
- _ => ()
- }
-
- os::remove_file(&keyfile);
-
- info(fmt!("synced source: %s", name));
-
- return true;
-}
-
-pub fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool {
- let name = src.name;
- let srcfile = dir.push("source.json.new");
- let destsrcfile = dir.push("source.json");
- let pkgfile = dir.push("packages.json.new");
- let destpkgfile = dir.push("packages.json");
- let keyfile = dir.push("key.gpg");
- let srcsigfile = dir.push("source.json.sig");
- let sigfile = dir.push("packages.json.sig");
- let mut url = src.url;
- let smart = !str::ends_with(src.url, ~"packages.json");
- let mut has_src_file = false;
-
- if smart {
- url += ~"/packages.json";
- }
-
- let p = run::program_output(~"curl",
- ~[~"-f", ~"-s",
- ~"-o", pkgfile.to_str(), url]);
-
- if p.status != 0 {
- error(fmt!("fetch for source %s (url %s) failed", name, url));
- return false;
- }
- if smart {
- url = src.url + ~"/source.json";
- let p =
- run::program_output(~"curl",
- ~[~"-f", ~"-s",
- ~"-o", srcfile.to_str(), url]);
-
- if p.status == 0 {
- has_src_file = true;
- }
- }
-
- match copy src.key {
- Some(u) => {
- let p = run::program_output(~"curl",
- ~[~"-f", ~"-s",
- ~"-o", keyfile.to_str(), u]);
- if p.status != 0 {
- error(fmt!("fetch for source %s (key %s) failed", name, u));
- return false;
- }
- pgp::add(&c.root, &keyfile);
- }
- _ => ()
- }
- match (src.key, src.keyfp) {
- (Some(_), Some(f)) => {
- if smart {
- url = src.url + ~"/packages.json.sig";
- }
- else {
- url = src.url + ~".sig";
- }
-
- let mut p = run::program_output(~"curl",
- ~[~"-f", ~"-s", ~"-o",
- sigfile.to_str(), url]);
- if p.status != 0 {
- error(fmt!("fetch for source %s (sig %s) failed", name, url));
- return false;
- }
-
- let r = pgp::verify(&c.root, &pkgfile, &sigfile);
-
- if !r {
- error(fmt!("signature verification failed for source %s with \
- key %s", name, f));
- return false;
- }
-
- if smart && has_src_file {
- url = src.url + ~"/source.json.sig";
-
- p = run::program_output(~"curl",
- ~[~"-f", ~"-s", ~"-o",
- srcsigfile.to_str(), url]);
- if p.status != 0 {
- error(fmt!("fetch for source %s (sig %s) failed",
- name, url));
- return false;
- }
-
- let e = pgp::verify(&c.root, &srcfile, &srcsigfile);
-
- if !e {
- error(~"signature verification failed for " +
- ~"source " + name + ~" with key " + f);
- return false;
- }
- }
- }
- _ => ()
- }
-
- copy_warn(&pkgfile, &destpkgfile);
-
- if smart && has_src_file {
- copy_warn(&srcfile, &destsrcfile);
- }
-
- os::remove_file(&keyfile);
- os::remove_file(&srcfile);
- os::remove_file(&srcsigfile);
- os::remove_file(&pkgfile);
- os::remove_file(&sigfile);
-
- info(fmt!("synced source: %s", name));
-
- return true;
-}
-
-pub fn sync_one(c: &Cargo, src: @Source) {
- let name = src.name;
- let dir = c.sourcedir.push(name);
-
- info(fmt!("syncing source: %s...", name));
-
- need_dir(&dir);
-
- let result = match src.method {
- ~"git" => sync_one_git(c, &dir, src),
- ~"file" => sync_one_file(c, &dir, src),
- _ => sync_one_curl(c, &dir, src)
- };
-
- if result {
- load_source_info(c, src);
- load_source_packages(c, src);
- }
-}
-
-pub fn cmd_init(c: &Cargo) {
- let srcurl = ~"http://www.rust-lang.org/cargo/sources.json";
- let sigurl = ~"http://www.rust-lang.org/cargo/sources.json.sig";
-
- let srcfile = c.root.push("sources.json.new");
- let sigfile = c.root.push("sources.json.sig");
- let destsrcfile = c.root.push("sources.json");
-
- let p =
- run::program_output(~"curl", ~[~"-f", ~"-s",
- ~"-o", srcfile.to_str(), srcurl]);
- if p.status != 0 {
- error(fmt!("fetch of sources.json failed: %s", p.out));
- return;
- }
-
- let p =
- run::program_output(~"curl", ~[~"-f", ~"-s",
- ~"-o", sigfile.to_str(), sigurl]);
- if p.status != 0 {
- error(fmt!("fetch of sources.json.sig failed: %s", p.out));
- return;
- }
-
- let r = pgp::verify(&c.root, &srcfile, &sigfile);
- if !r {
- error(fmt!("signature verification failed for '%s'",
- srcfile.to_str()));
- return;
- }
-
- copy_warn(&srcfile, &destsrcfile);
- os::remove_file(&srcfile);
- os::remove_file(&sigfile);
-
- info(fmt!("initialized .cargo in %s", c.root.to_str()));
-}
-
-pub fn print_pkg(s: @Source, p: &Package) {
- let mut m = s.name + ~"/" + p.name + ~" (" + p.uuid + ~")";
- if vec::len(p.tags) > 0u {
- m = m + ~" [" + str::connect(p.tags, ~", ") + ~"]";
- }
- info(m);
- if p.description != ~"" {
- print(~" >> " + p.description + ~"\n")
- }
-}
-
-pub fn print_source(s: @Source) {
- info(s.name + ~" (" + s.url + ~")");
-
- let pks = sort::merge_sort(s.packages.get(), sys::shape_lt);
- let l = vec::len(pks);
-
- print(io::with_str_writer(|writer| {
- let mut list = ~" >> ";
-
- for vec::eachi(pks) |i, pk| {
- if str::len(list) > 78u {
- writer.write_line(list);
- list = ~" >> ";
- }
- list += pk.name + (if l - 1u == i { ~"" } else { ~", " });
- }
-
- writer.write_line(list);
- }));
-}
-
-pub fn cmd_list(c: &Cargo) {
- sync(c);
-
- if vec::len(c.opts.free) >= 3u {
- let v = vec::slice(c.opts.free, 2u, vec::len(c.opts.free));
- for vec::each(v) |name| {
- if !valid_pkg_name(*name) {
- error(fmt!("'%s' is an invalid source name", *name));
- } else {
- match c.sources.find(name) {
- Some(source) => {
- print_source(source);
- }
- None => {
- error(fmt!("no such source: %s", *name));
- }
- }
- }
- }
- } else {
- for c.sources.each_value |&v| {
- print_source(v);
- }
- }
-}
-
-pub fn cmd_search(c: &Cargo) {
- if vec::len(c.opts.free) < 3u {
- cmd_usage();
- return;
- }
-
- sync(c);
-
- let mut n = 0;
- let name = c.opts.free[2];
- let tags = vec::slice(c.opts.free, 3u, vec::len(c.opts.free));
- for_each_package(c, |s, p| {
- if (str::contains(p.name, name) || name == ~"*") &&
- vec::all(tags, |t| vec::contains(p.tags, t) ) {
- print_pkg(s, p);
- n += 1;
- }
- });
- info(fmt!("found %d packages", n));
-}
-
-pub fn install_to_dir(srcfile: &Path, destdir: &Path) {
- let newfile = destdir.push(srcfile.filename().get());
-
- let status = run::run_program(~"cp", ~[~"-r", srcfile.to_str(),
- newfile.to_str()]);
- if status == 0 {
- info(fmt!("installed: '%s'", newfile.to_str()));
- } else {
- error(fmt!("could not install: '%s'", newfile.to_str()));
- }
-}
-
-pub fn dump_cache(c: &Cargo) {
- need_dir(&c.root);
-
- let out = c.root.push("cache.json");
- let _root = json::Object(~LinearMap::new());
-
- if os::path_exists(&out) {
- copy_warn(&out, &c.root.push("cache.json.old"));
- }
-}
-
-pub fn dump_sources(c: &Cargo) {
- if c.sources.is_empty() {
- return;
- }
-
- need_dir(&c.root);
-
- let out = c.root.push("sources.json");
-
- if os::path_exists(&out) {
- copy_warn(&out, &c.root.push("sources.json.old"));
- }
-
- match io::buffered_file_writer(&out) {
- result::Ok(writer) => {
- let mut hash = ~LinearMap::new();
-
- for c.sources.each |&k, &v| {
- let mut chash = ~LinearMap::new();
-
- chash.insert(~"url", json::String(v.url));
- chash.insert(~"method", json::String(v.method));
-
- match copy v.key {
- Some(key) => {
- chash.insert(~"key", json::String(copy key));
- }
- _ => ()
- }
- match copy v.keyfp {
- Some(keyfp) => {
- chash.insert(~"keyfp", json::String(copy keyfp));
- }
- _ => ()
- }
-
- hash.insert(copy k, json::Object(chash));
- }
-
- json::to_writer(writer, &json::Object(hash))
- }
- result::Err(e) => {
- error(fmt!("could not dump sources: %s", e));
- }
- }
-}
-
-pub fn copy_warn(srcfile: &Path, destfile: &Path) {
- if !os::copy_file(srcfile, destfile) {
- warn(fmt!("copying %s to %s failed",
- srcfile.to_str(), destfile.to_str()));
- }
-}
-
-pub fn cmd_sources(c: &Cargo) {
- if vec::len(c.opts.free) < 3u {
- for c.sources.each_value |&v| {
- info(fmt!("%s (%s) via %s",
- v.name, v.url, v.method));
- }
- return;
- }
-
- let action = c.opts.free[2u];
-
- match action {
- ~"clear" => {
- for c.sources.each_key |&k| {
- c.sources.remove(&k);
- }
-
- info(~"cleared sources");
- }
- ~"add" => {
- if vec::len(c.opts.free) < 5u {
- cmd_usage();
- return;
- }
-
- let name = c.opts.free[3u];
- let url = c.opts.free[4u];
-
- if !valid_pkg_name(name) {
- error(fmt!("'%s' is an invalid source name", name));
- return;
- }
-
- if c.sources.contains_key(&name) {
- error(fmt!("source already exists: %s", name));
- } else {
- c.sources.insert(name, @Source {
- name: name,
- mut url: url,
- mut method: assume_source_method(url),
- mut key: None,
- mut keyfp: None,
- packages: DVec()
- });
- info(fmt!("added source: %s", name));
- }
- }
- ~"remove" => {
- if vec::len(c.opts.free) < 4u {
- cmd_usage();
- return;
- }
-
- let name = c.opts.free[3u];
-
- if !valid_pkg_name(name) {
- error(fmt!("'%s' is an invalid source name", name));
- return;
- }
-
- if c.sources.contains_key(&name) {
- c.sources.remove(&name);
- info(fmt!("removed source: %s", name));
- } else {
- error(fmt!("no such source: %s", name));
- }
- }
- ~"set-url" => {
- if vec::len(c.opts.free) < 5u {
- cmd_usage();
- return;
- }
-
- let name = c.opts.free[3u];
- let url = c.opts.free[4u];
-
- if !valid_pkg_name(name) {
- error(fmt!("'%s' is an invalid source name", name));
- return;
- }
-
- match c.sources.find(&name) {
- Some(source) => {
- let old = copy source.url;
- let method = assume_source_method(url);
-
- source.url = url;
- source.method = method;
-
- c.sources.insert(name, source);
-
- info(fmt!("changed source url: '%s' to '%s'", old, url));
- }
- None => {
- error(fmt!("no such source: %s", name));
- }
- }
- }
- ~"set-method" => {
- if vec::len(c.opts.free) < 5u {
- cmd_usage();
- return;
- }
-
- let name = c.opts.free[3u];
- let method = c.opts.free[4u];
-
- if !valid_pkg_name(name) {
- error(fmt!("'%s' is an invalid source name", name));
- return;
- }
-
- match c.sources.find(&name) {
- Some(source) => {
- let old = copy source.method;
-
- source.method = match method {
- ~"git" => ~"git",
- ~"file" => ~"file",
- _ => ~"curl"
- };
-
- c.sources.insert(name, source);
-
- info(fmt!("changed source method: '%s' to '%s'", old,
- method));
- }
- None => {
- error(fmt!("no such source: %s", name));
- }
- }
- }
- ~"rename" => {
- if vec::len(c.opts.free) < 5u {
- cmd_usage();
- return;
- }
-
- let name = c.opts.free[3u];
- let newn = c.opts.free[4u];
-
- if !valid_pkg_name(name) {
- error(fmt!("'%s' is an invalid source name", name));
- return;
- }
- if !valid_pkg_name(newn) {
- error(fmt!("'%s' is an invalid source name", newn));
- return;
- }
-
- match c.sources.find(&name) {
- Some(source) => {
- c.sources.remove(&name);
- c.sources.insert(newn, source);
- info(fmt!("renamed source: %s to %s", name, newn));
- }
- None => {
- error(fmt!("no such source: %s", name));
- }
- }
- }
- _ => cmd_usage()
- }
-}
-
-pub fn cmd_usage() {
- print(~"Usage: cargo <cmd> [options] [args..]
-e.g. cargo install <name>
-
-Where <cmd> is one of:
- init, install, list, search, sources,
- uninstall, usage
-
-Options:
-
- -h, --help Display this message
- <cmd> -h, <cmd> --help Display help for <cmd>
-");
-}
-
-pub fn cmd_usage_init() {
- print(~"cargo init
-
-Re-initialize cargo in ~/.cargo. Clears all sources and then adds the
-default sources from <www.rust-lang.org/sources.json>.");
-}
-
-pub fn cmd_usage_install() {
- print(~"cargo install
-cargo install [source/]<name>[@version]
-cargo install [source/]<uuid>[@version]
-cargo install <git url> [ref]
-cargo install <tarball url>
-cargo install <tarball file>
-
-Options:
- --test Run crate tests before installing
- -g Install to the user level (~/.cargo/bin/ instead of
- locally in ./.cargo/bin/ by default)
- -G Install to the system level (/usr/local/lib/cargo/bin/)
-
-Install a crate. If no arguments are supplied, it installs from
-the current working directory. If a source is provided, only install
-from that source, otherwise it installs from any source.");
-}
-
-pub fn cmd_usage_uninstall() {
- print(~"cargo uninstall [source/]<name>[@version]
-cargo uninstall [source/]<uuid>[@version]
-cargo uninstall <meta-name>[@version]
-cargo uninstall <meta-uuid>[@version]
-
-Options:
- -g Remove from the user level (~/.cargo/bin/ instead of
- locally in ./.cargo/bin/ by default)
- -G Remove from the system level (/usr/local/lib/cargo/bin/)
-
-Remove a crate. If a source is provided, only remove
-from that source, otherwise it removes from any source.
-If a crate was installed directly (git, tarball, etc.), you can remove
-it by metadata.");
-}
-
-pub fn cmd_usage_list() {
- print(~"cargo list [sources..]
-
-If no arguments are provided, list all sources and their packages.
-If source names are provided, list those sources and their packages.
-");
-}
-
-pub fn cmd_usage_search() {
- print(~"cargo search <query | '*'> [tags..]
-
-Search packages.");
-}
-
-pub fn cmd_usage_sources() {
- print(~"cargo sources
-cargo sources add <name> <url>
-cargo sources remove <name>
-cargo sources rename <name> <new>
-cargo sources set-url <name> <url>
-cargo sources set-method <name> <method>
-
-If no arguments are supplied, list all sources (but not their packages).
-
-Commands:
- add Add a source. The source method will be guessed
- from the URL.
- remove Remove a source.
- rename Rename a source.
- set-url Change the URL for a source.
- set-method Change the method for a source.");
-}
-
-pub fn main() {
- let argv = os::args();
- let o = build_cargo_options(argv);
-
- if vec::len(o.free) < 2u {
- cmd_usage();
- return;
- }
- if o.help {
- match o.free[1] {
- ~"init" => cmd_usage_init(),
- ~"install" => cmd_usage_install(),
- ~"uninstall" => cmd_usage_uninstall(),
- ~"list" => cmd_usage_list(),
- ~"search" => cmd_usage_search(),
- ~"sources" => cmd_usage_sources(),
- _ => cmd_usage()
- }
- return;
- }
- if o.free[1] == ~"usage" {
- cmd_usage();
- return;
- }
-
- let mut c = configure(o);
- let home = c.root;
- let first_time = os::path_exists(&home.push("sources.json"));
-
- if !first_time && o.free[1] != ~"init" {
- cmd_init(&c);
-
- // FIXME (#2662): shouldn't need to reconfigure
- c = configure(o);
- }
-
- match o.free[1] {
- ~"init" => cmd_init(&c),
- ~"install" => cmd_install(&mut c),
- ~"uninstall" => cmd_uninstall(&c),
- ~"list" => cmd_list(&c),
- ~"search" => cmd_search(&c),
- ~"sources" => cmd_sources(&c),
- _ => cmd_usage()
- }
-
- dump_cache(&c);
- dump_sources(&c);
-}
-