diff --git a/src/bin/bench.rs b/src/bin/bench.rs index 3db26741f4e..c7cf6b69332 100644 --- a/src/bin/bench.rs +++ b/src/bin/bench.rs @@ -20,6 +20,8 @@ pub struct Options { flag_example: Vec, flag_test: Vec, flag_bench: Vec, + flag_frozen: bool, + flag_locked: bool, arg_args: Vec, } @@ -46,6 +48,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date All of the trailing arguments are passed to the benchmark binaries generated for filtering benchmarks and generally providing options configuring how they @@ -64,9 +68,11 @@ Compilation can be customized with the `bench` profile in the manifest. pub fn execute(options: Options, config: &Config) -> CliResult> { let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let ops = ops::TestOptions { no_run: options.flag_no_run, diff --git a/src/bin/build.rs b/src/bin/build.rs index 3fc0fe32e6c..601344adf7c 100644 --- a/src/bin/build.rs +++ b/src/bin/build.rs @@ -23,6 +23,8 @@ pub struct Options { flag_example: Vec, flag_test: Vec, flag_bench: Vec, + flag_locked: bool, + flag_frozen: bool, } pub const USAGE: &'static str = " @@ -48,6 +50,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date If the --package argument is given, then SPEC is a package id specification which indicates which package should be built. If it is not given, then the @@ -62,9 +66,11 @@ the --release flag will use the `release` profile instead. pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-build; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index cdd110f3cab..d29a3cbb06f 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -28,6 +28,8 @@ pub struct Flags { flag_explain: Option, arg_command: String, arg_args: Vec, + flag_locked: bool, + flag_frozen: bool, } const USAGE: &'static str = " @@ -45,6 +47,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date Some common cargo commands are (see all commands with --list): build Compile the current project @@ -68,6 +72,16 @@ fn main() { execute_main_without_stdin(execute, true, USAGE) } +macro_rules! configure_shell { + ($config:expr, $options:expr) => ( + try!($config.configure($options.flag_verbose, + $options.flag_quiet, + &$options.flag_color, + $options.flag_frozen, + $options.flag_locked)); + ) +} + macro_rules! each_subcommand{ ($mac:ident) => { $mac!(bench); @@ -113,9 +127,11 @@ each_subcommand!(declare_mod); on this top-level information. */ fn execute(flags: Flags, config: &Config) -> CliResult> { - try!(config.configure_shell(flags.flag_verbose, - flags.flag_quiet, - &flags.flag_color)); + try!(config.configure(flags.flag_verbose, + flags.flag_quiet, + &flags.flag_color, + flags.flag_frozen, + flags.flag_locked)); init_git_transports(config); cargo::util::job::setup(); diff --git a/src/bin/clean.rs b/src/bin/clean.rs index 36ec7db1771..c259e83c6f3 100644 --- a/src/bin/clean.rs +++ b/src/bin/clean.rs @@ -14,6 +14,8 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_release: bool, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -31,6 +33,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date If the --package argument is given, then SPEC is a package id specification which indicates which package's artifacts should be cleaned out. If it is not @@ -40,9 +44,11 @@ and its format, see the `cargo help pkgid` command. pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-clean; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let opts = ops::CleanOptions { diff --git a/src/bin/doc.rs b/src/bin/doc.rs index 1c420def853..7f4fc2878e5 100644 --- a/src/bin/doc.rs +++ b/src/bin/doc.rs @@ -19,6 +19,8 @@ pub struct Options { flag_package: Vec, flag_lib: bool, flag_bin: Vec, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -43,6 +45,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date By default the documentation for the local package and all dependencies is built. The output is all placed in `target/doc` in rustdoc's usual format. @@ -54,9 +58,11 @@ the `cargo help pkgid` command. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); diff --git a/src/bin/fetch.rs b/src/bin/fetch.rs index 2870dc63a88..1a970b71f05 100644 --- a/src/bin/fetch.rs +++ b/src/bin/fetch.rs @@ -9,6 +9,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -23,6 +25,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date If a lockfile is available, this command will ensure that all of the git dependencies and/or registries dependencies are downloaded and locally @@ -35,9 +39,11 @@ all updated. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let ws = try!(Workspace::new(&root, config)); try!(ops::fetch(&ws)); diff --git a/src/bin/generate_lockfile.rs b/src/bin/generate_lockfile.rs index a49930fd9ab..36057c1bb6e 100644 --- a/src/bin/generate_lockfile.rs +++ b/src/bin/generate_lockfile.rs @@ -11,6 +11,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -25,13 +27,17 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-generate-lockfile; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let ws = try!(Workspace::new(&root, config)); diff --git a/src/bin/git_checkout.rs b/src/bin/git_checkout.rs index d3f49db6cde..e67844cce57 100644 --- a/src/bin/git_checkout.rs +++ b/src/bin/git_checkout.rs @@ -9,6 +9,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -23,12 +25,16 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let Options { flag_url: url, flag_reference: reference, .. } = options; let url = try!(url.to_url().map_err(|e| { diff --git a/src/bin/init.rs b/src/bin/init.rs index 3f02f057f3a..a779ec7e148 100644 --- a/src/bin/init.rs +++ b/src/bin/init.rs @@ -12,6 +12,8 @@ pub struct Options { arg_path: Option, flag_name: Option, flag_vcs: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -31,13 +33,17 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-init; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let Options { flag_bin, arg_path, flag_name, flag_vcs, .. } = options; diff --git a/src/bin/install.rs b/src/bin/install.rs index 7f9ed95195b..78d8f58fd59 100644 --- a/src/bin/install.rs +++ b/src/bin/install.rs @@ -16,6 +16,8 @@ pub struct Options { flag_root: Option, flag_list: bool, flag_force: bool, + flag_frozen: bool, + flag_locked: bool, arg_crate: Option, flag_vers: Option, @@ -56,6 +58,8 @@ Build and install options: -v, --verbose ... Use verbose output -q, --quiet Less output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date This command manages Cargo's local set of installed binary crates. Only packages which have [[bin]] targets can be installed, and all binaries are installed into @@ -89,9 +93,11 @@ The `--list` option will list all installed packages (and their versions). "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let compile_opts = ops::CompileOptions { config: config, diff --git a/src/bin/login.rs b/src/bin/login.rs index 50d8249be7f..635321c578d 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -13,6 +13,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -27,13 +29,17 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let token = match options.arg_token.clone() { Some(token) => token, None => { diff --git a/src/bin/metadata.rs b/src/bin/metadata.rs index d8a9f1fe5db..d5c2d09056e 100644 --- a/src/bin/metadata.rs +++ b/src/bin/metadata.rs @@ -13,6 +13,8 @@ pub struct Options { flag_no_deps: bool, flag_quiet: Option, flag_verbose: u32, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -34,12 +36,16 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let manifest = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let options = OutputMetadataOptions { diff --git a/src/bin/new.rs b/src/bin/new.rs index 70f9018e497..e90194f1d66 100644 --- a/src/bin/new.rs +++ b/src/bin/new.rs @@ -12,6 +12,8 @@ pub struct Options { arg_path: String, flag_name: Option, flag_vcs: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -31,13 +33,17 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-new; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let Options { flag_bin, arg_path, flag_name, flag_vcs, .. } = options; diff --git a/src/bin/owner.rs b/src/bin/owner.rs index 1eb02429576..9b666adfe87 100644 --- a/src/bin/owner.rs +++ b/src/bin/owner.rs @@ -12,6 +12,8 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_list: bool, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -30,6 +32,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date This command will modify the owners for a package on the specified registry (or default). Note that owners of a package can upload new versions, yank old @@ -41,9 +45,11 @@ and troubleshooting. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let opts = ops::OwnersOptions { krate: options.arg_crate, token: options.flag_token, diff --git a/src/bin/package.rs b/src/bin/package.rs index 4a454085409..40eb7bac778 100644 --- a/src/bin/package.rs +++ b/src/bin/package.rs @@ -14,6 +14,8 @@ pub struct Options { flag_list: bool, flag_allow_dirty: bool, flag_jobs: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -33,12 +35,16 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let ws = try!(Workspace::new(&root, config)); try!(ops::package(&ws, &ops::PackageOpts { diff --git a/src/bin/pkgid.rs b/src/bin/pkgid.rs index 963caf11f04..13aedf257a7 100644 --- a/src/bin/pkgid.rs +++ b/src/bin/pkgid.rs @@ -9,6 +9,8 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_manifest_path: Option, + flag_frozen: bool, + flag_locked: bool, arg_spec: Option, } @@ -24,6 +26,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date Given a argument, print out the fully qualified package id specifier. This command will generate an error if is ambiguous as to which package @@ -48,9 +52,11 @@ Example Package IDs pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path.clone(), config.cwd())); let ws = try!(Workspace::new(&root, config)); diff --git a/src/bin/publish.rs b/src/bin/publish.rs index f5a9d827767..7c277046006 100644 --- a/src/bin/publish.rs +++ b/src/bin/publish.rs @@ -15,6 +15,8 @@ pub struct Options { flag_allow_dirty: bool, flag_jobs: Option, flag_dry_run: bool, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -35,13 +37,17 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let Options { flag_token: token, flag_host: host, diff --git a/src/bin/run.rs b/src/bin/run.rs index 378e3dc2400..b889087d665 100644 --- a/src/bin/run.rs +++ b/src/bin/run.rs @@ -16,6 +16,8 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_release: bool, + flag_frozen: bool, + flag_locked: bool, arg_args: Vec, } @@ -38,6 +40,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date If neither `--bin` nor `--example` are given, then if the project only has one bin target it will be run. Otherwise `--bin` specifies the bin target to run, @@ -50,9 +54,11 @@ the ones before go to Cargo. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); diff --git a/src/bin/rustc.rs b/src/bin/rustc.rs index cce7a12d869..10fd9fc9130 100644 --- a/src/bin/rustc.rs +++ b/src/bin/rustc.rs @@ -25,6 +25,8 @@ pub struct Options { flag_test: Vec, flag_bench: Vec, flag_profile: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -51,6 +53,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date The specified target for the current package (or package specified by SPEC if provided) will be compiled along with all of its dependencies. The specified @@ -69,9 +73,11 @@ processes spawned by Cargo, use the $RUSTFLAGS environment variable or the pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-rustc; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); diff --git a/src/bin/rustdoc.rs b/src/bin/rustdoc.rs index c5710a184c3..010b003c58d 100644 --- a/src/bin/rustdoc.rs +++ b/src/bin/rustdoc.rs @@ -22,6 +22,8 @@ pub struct Options { flag_example: Vec, flag_test: Vec, flag_bench: Vec, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -48,6 +50,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date The specified target for the current package (or package specified by SPEC if provided) will be documented with the specified ... being passed to the @@ -63,9 +67,11 @@ the `cargo help pkgid` command. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); diff --git a/src/bin/search.rs b/src/bin/search.rs index 4d1f1ea3bf1..829039aaa0e 100644 --- a/src/bin/search.rs +++ b/src/bin/search.rs @@ -10,7 +10,9 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_limit: Option, - arg_query: Vec + flag_frozen: bool, + flag_locked: bool, + arg_query: Vec, } pub const USAGE: &'static str = " @@ -27,12 +29,16 @@ Options: -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never --limit LIMIT Limit the number of results (default: 10, max: 100) + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let Options { flag_host: host, flag_limit: limit, diff --git a/src/bin/test.rs b/src/bin/test.rs index f7f53bc4bfd..cd823a59172 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -24,6 +24,8 @@ pub struct Options { flag_color: Option, flag_release: bool, flag_no_fail_fast: bool, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -52,6 +54,8 @@ Options: -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never --no-fail-fast Run all tests regardless of failure + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date All of the trailing arguments are passed to the test binaries generated for filtering tests and generally providing options configuring how they run. For @@ -81,9 +85,11 @@ To get the list of all options available for the test binaries use this: "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let empty = Vec::new(); diff --git a/src/bin/uninstall.rs b/src/bin/uninstall.rs index 046997a44fb..001abde41ef 100644 --- a/src/bin/uninstall.rs +++ b/src/bin/uninstall.rs @@ -8,6 +8,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, arg_spec: String, } @@ -26,6 +28,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet Less output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date The argument SPEC is a package id specification (see `cargo help pkgid`) to specify which crate should be uninstalled. By default all binaries are @@ -34,9 +38,11 @@ only uninstall particular binaries. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = options.flag_root.as_ref().map(|s| &s[..]); try!(ops::uninstall(root, &options.arg_spec, &options.flag_bin, config)); diff --git a/src/bin/update.rs b/src/bin/update.rs index 8c72dd1118d..6d1d7935b9c 100644 --- a/src/bin/update.rs +++ b/src/bin/update.rs @@ -14,6 +14,8 @@ pub struct Options { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -31,6 +33,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date This command requires that a `Cargo.lock` already exists as generated by `cargo build` or related commands. @@ -55,9 +59,11 @@ For more information about package id specifications, see `cargo help pkgid`. pub fn execute(options: Options, config: &Config) -> CliResult> { debug!("executing; cmd=cargo-update; args={:?}", env::args().collect::>()); - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); let root = try!(find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())); let update_opts = ops::UpdateOptions { diff --git a/src/bin/verify_project.rs b/src/bin/verify_project.rs index 0ce407e08c4..27424f7a681 100644 --- a/src/bin/verify_project.rs +++ b/src/bin/verify_project.rs @@ -16,6 +16,8 @@ pub struct Flags { flag_verbose: u32, flag_quiet: Option, flag_color: Option, + flag_frozen: bool, + flag_locked: bool, } pub const USAGE: &'static str = " @@ -31,12 +33,16 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date "; pub fn execute(args: Flags, config: &Config) -> CliResult> { - try!(config.configure_shell(args.flag_verbose, - args.flag_quiet, - &args.flag_color)); + try!(config.configure(args.flag_verbose, + args.flag_quiet, + &args.flag_color, + args.flag_frozen, + args.flag_locked)); let mut contents = String::new(); let filename = args.flag_manifest_path.unwrap_or("Cargo.toml".into()); diff --git a/src/bin/yank.rs b/src/bin/yank.rs index a869f36fffc..7971efbb37e 100644 --- a/src/bin/yank.rs +++ b/src/bin/yank.rs @@ -11,6 +11,8 @@ pub struct Options { flag_quiet: Option, flag_color: Option, flag_undo: bool, + flag_frozen: bool, + flag_locked: bool, } pub static USAGE: &'static str = " @@ -28,6 +30,8 @@ Options: -v, --verbose ... Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never + --frozen Require Cargo.lock and cache are up to date + --locked Require Cargo.lock is up to date The yank command removes a previously pushed crate's version from the server's index. This command does not delete any data, and the crate will still be @@ -39,9 +43,11 @@ crates to be locked to any yanked version. "; pub fn execute(options: Options, config: &Config) -> CliResult> { - try!(config.configure_shell(options.flag_verbose, - options.flag_quiet, - &options.flag_color)); + try!(config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + options.flag_frozen, + options.flag_locked)); try!(ops::yank(config, options.arg_crate, options.flag_vers, diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 1ecf4406d44..ccfe87cabee 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -269,7 +269,10 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { let ret = if overrides.is_empty() { // Ensure the requested source_id is loaded - try!(self.ensure_loaded(dep.source_id(), Kind::Normal)); + try!(self.ensure_loaded(dep.source_id(), Kind::Normal).chain_error(|| { + human(format!("failed to load source for a dependency \ + on `{}`", dep.name())) + })); match self.sources.get_mut(dep.source_id()) { Some(src) => try!(src.query(&dep)), diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index f0a1f72c312..91a2bf2d7a0 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -86,6 +86,12 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> } } + if !ws.config().lock_update_allowed() { + let flag = if ws.config().network_allowed() {"--frozen"} else {"--locked"}; + bail!("the lock file needs to be updated but {} was passed to \ + prevent this", flag); + } + // Ok, if that didn't work just write it out root.open_rw("Cargo.lock", ws.config(), "Cargo.lock file").and_then(|mut f| { try!(f.file().set_len(0)); diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index ac831b3576a..e0d4fd5d6e6 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -182,6 +182,11 @@ pub fn registry(config: &Config, /// Create a new HTTP handle with appropriate global configuration for cargo. pub fn http_handle(config: &Config) -> CargoResult { + if !config.network_allowed() { + bail!("attempting to make an HTTP request, but --frozen was \ + specified") + } + // The timeout option for libcurl by default times out the entire transfer, // but we probably don't want this. Instead we only set timeouts for the // connect phase as well as a "low speed" timeout so if we don't receive diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 7ffdddade84..1149bfffd02 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -560,19 +560,26 @@ fn with_authentication(url: &str, cfg: &git2::Config, mut f: F) }) } -pub fn fetch(repo: &git2::Repository, url: &str, - refspec: &str, cargo_config: &Config) -> CargoResult<()> { - // Create a local anonymous remote in the repository to fetch the url +pub fn fetch(repo: &git2::Repository, + url: &str, + refspec: &str, + config: &Config) -> CargoResult<()> { + if !config.network_allowed() { + bail!("attempting to update a git repository, but --frozen \ + was specified") + } with_authentication(url, &try!(repo.config()), |f| { let mut cb = git2::RemoteCallbacks::new(); cb.credentials(f); + + // Create a local anonymous remote in the repository to fetch the url let mut remote = try!(repo.remote_anonymous(&url)); let mut opts = git2::FetchOptions::new(); opts.remote_callbacks(cb) .download_tags(git2::AutotagOption::All); - try!(network::with_retry(cargo_config, ||{ + try!(network::with_retry(config, ||{ remote.fetch(&[refspec], Some(&mut opts), None) })); Ok(()) diff --git a/src/cargo/sources/registry.rs b/src/cargo/sources/registry.rs index 06e6344bb96..f89f6bae794 100644 --- a/src/cargo/sources/registry.rs +++ b/src/cargo/sources/registry.rs @@ -177,6 +177,7 @@ use core::dependency::{Dependency, DependencyInner, Kind}; use sources::{PathSource, git}; use util::{CargoResult, Config, internal, ChainError, ToUrl, human}; use util::{hex, Sha256, paths, Filesystem, FileLock}; +use util::network; use ops; const DEFAULT: &'static str = "https://github.com/rust-lang/crates.io-index"; @@ -315,7 +316,9 @@ impl<'cfg> RegistrySource<'cfg> { body.extend_from_slice(buf); Ok(buf.len()) })); - try!(handle.perform()); + try!(network::with_retry(self.config, || { + handle.perform() + })) } let code = try!(handle.response_code()); if code != 200 && code != 0 { @@ -495,7 +498,7 @@ impl<'cfg> RegistrySource<'cfg> { let refspec = "refs/heads/*:refs/remotes/origin/*"; try!(git::fetch(&repo, &url, refspec, &self.config).chain_error(|| { - internal(format!("failed to fetch `{}`", url)) + human(format!("failed to fetch `{}`", url)) })); // git reset --hard origin/master diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 37bdf035736..d1b299e5f46 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -32,6 +32,8 @@ pub struct Config { rustdoc: PathBuf, target_dir: RefCell>, extra_verbose: Cell, + frozen: Cell, + locked: Cell, } impl Config { @@ -49,6 +51,8 @@ impl Config { rustdoc: PathBuf::from("rustdoc"), target_dir: RefCell::new(None), extra_verbose: Cell::new(false), + frozen: Cell::new(false), + locked: Cell::new(false), }; try!(cfg.scrape_tool_config()); @@ -292,10 +296,12 @@ impl Config { }) } - pub fn configure_shell(&self, - verbose: u32, - quiet: Option, - color: &Option) -> CargoResult<()> { + pub fn configure(&self, + verbose: u32, + quiet: Option, + color: &Option, + frozen: bool, + locked: bool) -> CargoResult<()> { let extra_verbose = verbose >= 2; let verbose = if verbose == 0 {None} else {Some(true)}; let cfg_verbose = try!(self.get_bool("term.verbose")).map(|v| v.val); @@ -329,6 +335,8 @@ impl Config { self.shell().set_verbosity(verbosity); try!(self.shell().set_color_config(color.map(|s| &s[..]))); self.extra_verbose.set(extra_verbose); + self.frozen.set(frozen); + self.locked.set(locked); Ok(()) } @@ -337,6 +345,14 @@ impl Config { self.extra_verbose.get() } + pub fn network_allowed(&self) -> bool { + !self.frozen.get() + } + + pub fn lock_update_allowed(&self) -> bool { + !self.frozen.get() && !self.locked.get() + } + fn load_values(&self) -> CargoResult<()> { let mut cfg = CV::Table(HashMap::new(), PathBuf::from(".")); diff --git a/src/doc/faq.md b/src/doc/faq.md index ae7e9bcaa26..7782247ce79 100644 --- a/src/doc/faq.md +++ b/src/doc/faq.md @@ -155,3 +155,37 @@ many possible names has historically led to confusion where one case was handled but others were accidentally forgotten. [crates.io]: https://crates.io/ + +# How can Cargo work offline? + +Cargo is often used in situations with limited or no network access such as +airplanes, CI environments, or embedded in large production deployments. Users +are often surprised when Cargo attempts to fetch resources from the network, and +hence the request for Cargo to work offline comes up frequently. + +Cargo, at its heart, will not attempt to access the network unless told to do +so. That is, if no crates comes from crates.io, a git repository, or some other +network location, Cargo will never attempt to make a network connection. As a +result, if Cargo attempts to touch the network, then it's because it needs to +fetch a required resource. + +Cargo is also quite aggressive about caching information to minimize the amount +of network activity. It will guarantee, for example, that if `cargo build` (or +an equivalent) is run to completion then the next `cargo build` is guaranteed to +not touch the network so long as `Cargo.toml` has not been modified in the +meantime. This avoidance of the network boils down to a `Cargo.lock` existing +and a populated cache of the crates reflected in the lock file. If either of +these components are missing, then they're required for the build to succeed and +must be fetched remotely. + +As of Rust 1.11.0 (to be released 2016-09-29) Cargo understands a new flag, +`--frozen`, which is an assertion that it shouldn't touch the network. When +passed, Cargo will immediately return an error if it would otherwise attempt a +network request. The error should include contextual information about why the +network request is being made in the first place to help debug as well. Note +that this flag *does not change the behavior of Cargo*, it simply asserts that +Cargo shouldn't touch the network as a previous command has been run to ensure +that network activity shouldn't be necessary. + +Note that Cargo does not yet support vendoring in a first-class fashion, but +this is a hotly desired feature and coming soon! diff --git a/tests/bad-config.rs b/tests/bad-config.rs index 880ba85ba32..3b806ef463a 100644 --- a/tests/bad-config.rs +++ b/tests/bad-config.rs @@ -73,9 +73,10 @@ fn bad3() { [http] proxy = true "#); + Package::new("foo", "1.0.0").publish(); assert_that(foo.cargo_process("publish").arg("-v"), execs().with_status(101).with_stderr("\ -[UPDATING] registry `https://[..]` +[UPDATING] registry `[..]` [ERROR] invalid configuration for key `http.proxy` expected a string, but found a boolean in [..]config ")); @@ -246,7 +247,10 @@ fn bad_git_dependency() { assert_that(foo.cargo_process("build").arg("-v"), execs().with_status(101).with_stderr("\ [UPDATING] git repository `file:///` -[ERROR] Unable to update file:/// +[ERROR] failed to load source for a dependency on `foo` + +Caused by: + Unable to update file:/// Caused by: failed to clone into: [..] diff --git a/tests/build-auth.rs b/tests/build-auth.rs index 6ac2107df7c..8784329a9d6 100644 --- a/tests/build-auth.rs +++ b/tests/build-auth.rs @@ -102,7 +102,10 @@ fn http_auth_offered() { assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr(&format!("\ [UPDATING] git repository `http://{addr}/foo/bar` -[ERROR] Unable to update http://{addr}/foo/bar +[ERROR] failed to load source for a dependency on `bar` + +Caused by: + Unable to update http://{addr}/foo/bar Caused by: failed to clone into: [..] diff --git a/tests/overrides.rs b/tests/overrides.rs index 46f118a4457..7157bb5f183 100644 --- a/tests/overrides.rs +++ b/tests/overrides.rs @@ -467,7 +467,10 @@ fn override_with_nothing() { execs().with_status(101).with_stderr("\ [UPDATING] registry [..] [UPDATING] git repository [..] -error: Unable to update file://[..] +[ERROR] failed to load source for a dependency on `foo` + +Caused by: + Unable to update file://[..] Caused by: Could not find Cargo.toml in `[..]` diff --git a/tests/path.rs b/tests/path.rs index 574851e9387..0e8aa25c910 100644 --- a/tests/path.rs +++ b/tests/path.rs @@ -524,7 +524,10 @@ fn error_message_for_missing_manifest() { assert_that(p.cargo_process("build"), execs().with_status(101) .with_stderr("\ -[ERROR] Unable to update file://[..] +[ERROR] failed to load source for a dependency on `bar` + +Caused by: + Unable to update file://[..] Caused by: failed to read `[..]bar[..]Cargo.toml` diff --git a/tests/registry.rs b/tests/registry.rs index 7f600fb1786..1a2371bfdb6 100644 --- a/tests/registry.rs +++ b/tests/registry.rs @@ -1070,3 +1070,34 @@ fn upstream_warnings_on_extra_verbose() { [..]warning: function is never used[..] ")); } + +#[test] +fn disallow_network() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "bar" + version = "0.5.0" + authors = [] + + [dependencies] + foo = "*" + "#) + .file("src/main.rs", "fn main() {}"); + p.build(); + + assert_that(p.cargo("build").arg("--frozen"), + execs().with_status(101).with_stderr("\ +[UPDATING] registry `[..]` +error: failed to load source for a dependency on `foo` + +Caused by: + Unable to update registry [..] + +Caused by: + failed to fetch `[..]` + +Caused by: + attempting to update a git repository, but --frozen was specified +")); +}