interested in the inner workings of Cargo.
The purpose of Cargo is to formalize a canonical Rust workflow, by automating
-the standard tasks associated with distributing software. Cargo simplifies
+the standard tasks associated with distributing software. Cargo simplifies
structuring a new project, adding dependencies, writing and running unit tests,
and more.
`Resolve` is the representation of a directed acyclic graph of package
dependencies, which uses `PackageId`s for nodes. This is the data
-structure that is saved to the lock file. If there is no lockfile,
+structure that is saved to the lock file. If there is no lock file,
Cargo constructs a resolve by finding a graph of packages which
matches declared dependency specification according to semver.
Cargo uses [`env_logger`](https://docs.rs/env_logger/*/env_logger/), so you can set
`RUST_LOG` environment variable to get the logs. This is useful both for diagnosing
-bugs in stable Cargo and for local development. Cargo also has internal hierarchical
-profiling infrastructure, which is activated via `CARGO_PROFILE` variable
+bugs in stable Cargo and for local development. Cargo also has internal hierarchical
+profiling infrastructure, which is activated via `CARGO_PROFILE` variable
```
-# Outputs all logs with levels debug and higher
+# Outputs all logs with levels debug and higher
$ RUST_LOG=debug cargo generate-lockfile
-# Don't forget that you can filter by module as well
+# Don't forget that you can filter by module as well
$ RUST_LOG=cargo::core::resolver=trace cargo generate-lockfile
# Output first three levels of profiling info
* Include tests that cover all non-trivial code. The existing tests
in `test/` provide templates on how to test Cargo's behavior in a
sandbox-environment. The internal module `testsuite/support` provides a vast amount
-of helpers to minimize boilerplate. See [`testsuite/support/mod.rs`] for an
+of helpers to minimize boilerplate. See [`testsuite/support/mod.rs`] for an
introduction to writing tests.
* Make sure `cargo test` passes. If you do not have the cross-compilers
installed locally, install them using the instructions returned by
A merge of Cargo's master-branch and your changes is immediately queued
to be tested after the pull request is made. In case unforeseen
-problems are discovered during this step (e.g. a failure on a platform you
+problems are discovered during this step (e.g., a failure on a platform you
originally did not develop on), you may ask for guidance. Push additional
commits to your branch to tackle these problems.
))
.after_help(
"\
-The benchmark filtering argument `BENCHNAME` and all the arguments following the
+The benchmark filtering argument BENCHNAME and all the arguments following the
two dashes (`--`) are passed to the benchmark binaries and thus to libtest
-(rustc's built in unit-test and micro-benchmarking framework). If you're
+(rustc's built in unit-test and micro-benchmarking framework). If you're
passing arguments to both Cargo and the binary, the ones after `--` go to the
-binary, the ones before go to Cargo. For details about libtest's arguments see
+binary, the ones before go to Cargo. For details about libtest's arguments see
the output of `cargo bench -- --help`.
-If the --package argument is given, then SPEC is a package id specification
+If the `--package` argument is given, then SPEC is a package ID specification
which indicates which package should be benchmarked. If it is not given, then
the current package is benchmarked. For more information on SPEC and its format,
see the `cargo help pkgid` command.
`--all` flag is automatically assumed for a virtual manifest.
Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-The --jobs argument affects the building of the benchmark executable but does
+The `--jobs` argument affects the building of the benchmark executable but does
not affect how many jobs are used when running the benchmarks.
Compilation can be customized with the `bench` profile in the manifest.
.arg_message_format()
.after_help(
"\
-If the --package argument is given, then SPEC is a package id specification
+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
current package is built. For more information on SPEC and its format, see the
`cargo help pkgid` command.
Compilation can be configured via the use of profiles which are configured in
the manifest. The default profile for this command is `dev`, but passing
-the --release flag will use the `release` profile instead.
+the `--release` flag will use the `release` profile instead.
The `--profile test` flag can be used to check unit tests with the
`#[cfg(test)]` attribute.
.arg_doc("Whether or not to clean just the documentation directory")
.after_help(
"\
-If the --package argument is given, then SPEC is a package id specification
+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
given, then all packages' artifacts are removed. For more information on SPEC
and its format, see the `cargo help pkgid` command.
`--all` flag is automatically assumed for a virtual manifest.
Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-If the --package argument is given, then SPEC is a package id specification
+If the `--package` argument is given, then SPEC is a package ID specification
which indicates which package should be documented. If it is not given, then the
current package is documented. For more information on SPEC and its format, see
the `cargo help pkgid` command.
.arg_target_triple("Fetch dependencies for the target triple")
.after_help(
"\
-If a lockfile is available, this command will ensure that all of the git
+If a lock file is available, this command will ensure that all of the Git
dependencies and/or registries dependencies are downloaded and locally
available. The network is never touched after a `cargo fetch` unless
-the lockfile changes.
+the lock file changes.
-If the lockfile is not available, then this is the equivalent of
-`cargo generate-lockfile`. A lockfile is generated and dependencies are also
+If the lock file is not available, then this is the equivalent of
+`cargo generate-lockfile`. A lock file is generated and dependencies are also
all updated.
",
)
Omitting the <crate> specification entirely will
install the crate in the current directory. That is, `install` is equivalent to
-the more explicit `install --path .`. This behaviour is deprecated, and no
+the more explicit `install --path .`. This behaviour is deprecated, and no
longer supported as of the Rust 2018 edition.
If the source is crates.io or `--git` then by default the crate will be built
-in a temporary target directory. To avoid this, the target directory can be
+in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
-path. In particular, this can be useful for caching build artifacts on
+path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
)
}
subcommand("pkgid")
.about("Print a fully qualified package specification")
.arg(Arg::with_name("spec"))
- .arg_package("Argument to get the package id specifier for")
+ .arg_package("Argument to get the package ID specifier for")
.arg_manifest_path()
.after_help(
"\
-Given a <spec> argument, print out the fully qualified package id specifier.
+Given a <spec> argument, print out the fully qualified package ID specifier.
This command will generate an error if <spec> is ambiguous as to which package
it refers to in the dependency graph. If no <spec> is given, then the pkgid for
the local package is printed.
-use crate::command_prelude::*;
-
use cargo::ops::{self, DocOptions};
+use crate::command_prelude::*;
+
pub fn cli() -> App {
subcommand("rustdoc")
.setting(AppSettings::TrailingVarArg)
.after_help(
"\
The specified target for the current package (or package specified by SPEC if
-provided) will be documented with the specified <opts>... being passed to the
+provided) will be documented with the specified `<opts>...` being passed to the
final rustdoc invocation. Dependencies will not be documented as part of this
-command. Note that rustdoc will still unconditionally receive arguments such
-as -L, --extern, and --crate-type, and the specified <opts>... will simply be
-added to the rustdoc invocation.
+command. Note that rustdoc will still unconditionally receive arguments such
+as `-L`, `--extern`, and `--crate-type`, and the specified `<opts>...` will
+simply be added to the rustdoc invocation.
-If the --package argument is given, then SPEC is a package id specification
+If the `--package` argument is given, then SPEC is a package ID specification
which indicates which package should be documented. If it is not given, then the
current package is documented. For more information on SPEC and its format, see
the `cargo help pkgid` command.
-use crate::command_prelude::*;
-
use cargo::ops::{self, CompileFilter};
+use crate::command_prelude::*;
+
pub fn cli() -> App {
subcommand("test")
- // subcommand aliases are handled in aliased_command()
+ // Subcommand aliases are handled in `aliased_command()`.
// .alias("t")
.setting(AppSettings::TrailingVarArg)
.about("Execute all unit and integration tests and build examples of a local package")
.arg_message_format()
.after_help(
"\
-The test filtering argument `TESTNAME` and all the arguments following the
+The test filtering argument TESTNAME and all the arguments following the
two dashes (`--`) are passed to the test binaries and thus to libtest
-(rustc's built in unit-test and micro-benchmarking framework). If you're
+(rustc's built in unit-test and micro-benchmarking framework). If you're
passing arguments to both Cargo and the binary, the ones after `--` go to the
-binary, the ones before go to Cargo. For details about libtest's arguments see
-the output of `cargo test -- --help`. As an example, this will run all
+binary, the ones before go to Cargo. For details about libtest's arguments see
+the output of `cargo test -- --help`. As an example, this will run all
tests with `foo` in their name on 3 threads in parallel:
cargo test foo -- --test-threads 3
-If the --package argument is given, then SPEC is a package id specification
+If the `--package` argument is given, then SPEC is a package ID specification
which indicates which package should be tested. If it is not given, then the
current package is tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.
`--all` flag is automatically assumed for a virtual manifest.
Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-The --jobs argument affects the building of the test executable but does
+The `--jobs` argument affects the building of the test executable but does
not affect how many jobs are used when running the tests. The default value
-for the --jobs argument is the number of CPUs. If you want to control the
+for the `--jobs` argument is the number of CPUs. If you want to control the
number of simultaneous running test cases, pass the `--test-threads` option
to the test binaries:
Compilation can be configured via the `test` profile in the manifest.
By default the rust test harness hides output from test execution to
-keep results readable. Test output can be recovered (e.g. for debugging)
+keep results readable. Test output can be recovered (e.g., for debugging)
by passing `--nocapture` to the test binaries:
cargo test -- --nocapture
compile_opts,
};
- // TESTNAME is actually an argument of the test binary, but it's
- // important so we explicitly mention it and reconfigure
+ // `TESTNAME` is actually an argument of the test binary, but it's
+ // important, so we explicitly mention it and reconfigure.
let mut test_args = vec![];
test_args.extend(args.value_of("TESTNAME").into_iter().map(|s| s.to_string()));
test_args.extend(
.arg(opt("root", "Directory to uninstall packages from").value_name("DIR"))
.after_help(
"\
-The argument SPEC is a package id specification (see `cargo help pkgid`) to
+The argument SPEC is a package ID specification (see `cargo help pkgid`) to
specify which crate should be uninstalled. By default all binaries are
uninstalled for a crate but the `--bin` and `--example` flags can be used to
only uninstall particular binaries.
If SPEC is given, then a conservative update of the lockfile will be
performed. This means that only the dependency specified by SPEC will be
updated. Its transitive dependencies will be updated only if SPEC cannot be
-updated without updating dependencies. All other dependencies will remain
+updated without updating dependencies. All other dependencies will remain
locked at their currently recorded versions.
-If PRECISE is specified, then --aggressive must not also be specified. The
+If PRECISE is specified, then `--aggressive` must not also be specified. The
argument PRECISE is a string representing a precise revision that the package
being updated should be updated to. For example, if the package comes from a git
repository, then PRECISE would be the exact revision that the repository should
If SPEC is not given, then all dependencies will be re-resolved and
updated.
-For more information about package id specifications, see `cargo help pkgid`.
+For more information about package ID specifications, see `cargo help pkgid`.
",
)
}
/// Configuration information for a rustc build.
#[derive(Debug)]
pub struct BuildConfig {
- /// The target arch triple, defaults to host arch
+ /// The target arch triple.
+ /// Default: host arch.
pub requested_target: Option<String>,
- /// How many rustc jobs to run in parallel
+ /// Number of rustc jobs to run in parallel.
pub jobs: u32,
- /// Whether we are building for release
+ /// `true` if we are building for release.
pub release: bool,
- /// In what mode we are compiling
+ /// The mode we are compiling in.
pub mode: CompileMode,
- /// Whether to print std output in json format (for machine reading)
+ /// `true` to print stdout in JSON format (for machine reading).
pub message_format: MessageFormat,
- /// Force cargo to do a full rebuild and treat each target as changed.
+ /// Force Cargo to do a full rebuild and treat each target as changed.
pub force_rebuild: bool,
/// Output a build plan to stdout instead of actually compiling.
pub build_plan: bool,
- /// Use Cargo itself as the wrapper around rustc, only used for `cargo fix`
+ /// Use Cargo itself as the wrapper around rustc, only used for `cargo fix`.
pub cargo_as_rustc_wrapper: bool,
- /// Extra env vars to inject into rustc commands
+ /// Extra env vars to inject into rustc commands.
pub extra_rustc_env: Vec<(String, String)>,
- /// Extra args to inject into rustc commands
+ /// Extra args to inject into rustc commands.
pub extra_rustc_args: Vec<String>,
pub rustfix_diagnostic_server: RefCell<Option<RustfixDiagnosticServer>>,
}
impl BuildConfig {
- /// Parse all config files to learn about build configuration. Currently
+ /// Parses all config files to learn about build configuration. Currently
/// configured options are:
///
- /// * build.jobs
- /// * build.target
- /// * target.$target.ar
- /// * target.$target.linker
- /// * target.$target.libfoo.metadata
+ /// * `build.jobs`
+ /// * `build.target`
+ /// * `target.$target.ar`
+ /// * `target.$target.linker`
+ /// * `target.$target.libfoo.metadata`
pub fn new(
config: &Config,
jobs: Option<u32>,
Short,
}
-/// The general "mode" of what to do.
-/// This is used for two purposes. The commands themselves pass this in to
-/// `compile_ws` to tell it the general execution strategy. This influences
-/// the default targets selected. The other use is in the `Unit` struct
+/// The general "mode" for what to do.
+/// This is used for two purposes. The commands themselves pass this in to
+/// `compile_ws` to tell it the general execution strategy. This influences
+/// the default targets selected. The other use is in the `Unit` struct
/// to indicate what is being done with a specific target.
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
pub enum CompileMode {
/// `test` is true, then it is also compiled with `--test` to check it like
/// a test.
Check { test: bool },
- /// Used to indicate benchmarks should be built. This is not used in
- /// `Target` because it is essentially the same as `Test` (indicating
+ /// Used to indicate benchmarks should be built. This is not used in
+ /// `Target`, because it is essentially the same as `Test` (indicating
/// `--test` should be passed to rustc) and by using `Test` instead it
/// allows some de-duping of Units to occur.
Bench,
Doc { deps: bool },
/// A target that will be tested with `rustdoc`.
Doctest,
- /// A marker for Units that represent the execution of a `build.rs`
- /// script.
+ /// A marker for Units that represent the execution of a `build.rs` script.
RunCustomBuild,
}
}
impl CompileMode {
- /// Returns true if the unit is being checked.
+ /// Returns `true` if the unit is being checked.
pub fn is_check(self) -> bool {
match self {
CompileMode::Check { .. } => true,
}
}
- /// Returns true if this is a doc or doctest. Be careful using this.
+ /// Returns `true` if this is a doc or doc test. Be careful using this.
/// Although both run rustdoc, the dependencies for those two modes are
/// very different.
pub fn is_doc(self) -> bool {
}
}
- /// Returns true if this is any type of test (test, benchmark, doctest, or
- /// check-test).
+ /// Returns `true` if this is any type of test (test, benchmark, doc test, or
+ /// check test).
pub fn is_any_test(self) -> bool {
match self {
CompileMode::Test
}
}
- /// Returns true if this is the *execution* of a `build.rs` script.
+ /// Returns `true` if this is the *execution* of a `build.rs` script.
pub fn is_run_custom_build(self) -> bool {
self == CompileMode::RunCustomBuild
}
mod target_info;
pub use self::target_info::{FileFlavor, TargetInfo};
-/// The build context, containing all information about a build task
+/// The build context, containing all information about a build task.
pub struct BuildContext<'a, 'cfg: 'a> {
- /// The workspace the build is for
+ /// The workspace the build is for.
pub ws: &'a Workspace<'cfg>,
- /// The cargo configuration
+ /// The cargo configuration.
pub config: &'cfg Config,
- /// The dependency graph for our build
+ /// The dependency graph for our build.
pub resolve: &'a Resolve,
pub profiles: &'a Profiles,
pub build_config: &'a BuildConfig,
pub extra_compiler_args: HashMap<Unit<'a>, Vec<String>>,
pub packages: &'a PackageSet<'cfg>,
- /// Information about the compiler
+ /// Information about the compiler.
pub rustc: Rustc,
- /// Build information for the host arch
+ /// Build information for the host arch.
pub host_config: TargetConfig,
- /// Build information for the target
+ /// Build information for the target.
pub target_config: TargetConfig,
pub target_info: TargetInfo,
pub host_info: TargetInfo,
platform.matches(name, info.cfg())
}
- /// Get the user-specified linker for a particular host or target
+ /// Gets the user-specified linker for a particular host or target.
pub fn linker(&self, kind: Kind) -> Option<&Path> {
self.target_config(kind).linker.as_ref().map(|s| s.as_ref())
}
- /// Get the user-specified `ar` program for a particular host or target
+ /// Gets the user-specified `ar` program for a particular host or target.
pub fn ar(&self, kind: Kind) -> Option<&Path> {
self.target_config(kind).ar.as_ref().map(|s| s.as_ref())
}
- /// Get the list of cfg printed out from the compiler for the specified kind
+ /// Gets the list of `cfg`s printed out from the compiler for the specified kind.
pub fn cfg(&self, kind: Kind) -> &[Cfg] {
let info = match kind {
Kind::Host => &self.host_info,
info.cfg().unwrap_or(&[])
}
- /// The host arch triple
+ /// Gets the host architecture triple.
///
- /// e.g. x86_64-unknown-linux-gnu, would be
- /// - machine: x86_64
- /// - hardware-platform: unknown
- /// - operating system: linux-gnu
+ /// For example, x86_64-unknown-linux-gnu, would be
+ /// - machine: x86_64,
+ /// - hardware-platform: unknown,
+ /// - operating system: linux-gnu.
pub fn host_triple(&self) -> &str {
&self.rustc.host
}
.unwrap_or_else(|| self.host_triple())
}
- /// Get the target configuration for a particular host or target
+ /// Gets the target configuration for a particular host or target.
fn target_config(&self, kind: Kind) -> &TargetConfig {
match kind {
Kind::Host => &self.host_config,
}
}
- /// Number of jobs specified for this build
+ /// Gets the number of jobs specified for this build.
pub fn jobs(&self) -> u32 {
self.build_config.jobs
}
}
}
-/// Information required to build for a target
+/// Information required to build for a target.
#[derive(Clone, Default)]
pub struct TargetConfig {
/// The path of archiver (lib builder) for this target.
pub ar: Option<PathBuf>,
/// The path of the linker for this target.
pub linker: Option<PathBuf>,
- /// Special build options for any necessary input files (filename -> options)
+ /// Special build options for any necessary input files (filename -> options).
pub overrides: HashMap<String, BuildOutput>,
}
// to compilation units with the Target kind, which indicates
// it was chosen by the --target flag.
//
- // This means that, e.g. even if the specified --target is the
+ // This means that, e.g., even if the specified --target is the
// same as the host, build scripts in plugins won't get
// RUSTFLAGS.
let compiling_with_target = requested_target.is_some();
return Ok(rustflags);
}
- // Then the build.rustflags value
+ // Then the `build.rustflags` value.
let key = format!("build.{}", name);
if let Some(args) = config.get_list_or_split_string(&key)? {
let args = args.val.into_iter();
pub enum FileFlavor {
/// Not a special file type.
Normal,
- /// It is something you can link against (e.g. a library)
+ /// Something you can link against (e.g., a library).
Linkable,
- /// It is a piece of external debug information (e.g. *.dSYM and *.pdb)
+ /// Piece of external debug information (e.g., `.dSYM`/`.pdb` file).
DebugInfo,
}
pub flavor: FileFlavor,
suffix: String,
prefix: String,
- // wasm bin target will generate two files in deps such as
+ // Wasm bin target will generate two files in deps such as
// "web-stuff.js" and "web_stuff.wasm". Note the different usages of
// "-" and "_". should_replace_hyphens is a flag to indicate that
// we need to convert the stem "web-stuff" to "web_stuff", so we
should_replace_hyphens: false,
}];
- // rust-lang/cargo#4500
+ // See rust-lang/cargo#4500.
if target_triple.ends_with("pc-windows-msvc")
&& crate_type.ends_with("dylib")
&& suffix == ".dll"
})
}
- // rust-lang/cargo#4535
+ // See rust-lang/cargo#4535.
if target_triple.starts_with("wasm32-") && crate_type == "bin" && suffix == ".js" {
ret.push(FileType {
suffix: ".wasm".to_string(),
})
}
- // rust-lang/cargo#4490, rust-lang/cargo#4960
- // - only uplift debuginfo for binaries.
- // tests are run directly from target/debug/deps/
- // and examples are inside target/debug/examples/ which already have symbols next to them
+ // See rust-lang/cargo#4490, rust-lang/cargo#4960.
+ // - Only uplift debuginfo for binaries.
+ // Tests are run directly from `target/debug/deps/`
+ // and examples are inside target/debug/examples/ which already have symbols next to them,
// so no need to do anything.
if *kind == TargetKind::Bin {
if target_triple.contains("-apple-") {
}
/// Takes rustc output (using specialized command line args), and calculates the file prefix and
-/// suffix for the given crate type, or returns None if the type is not supported. (e.g. for a
-/// rust library like libcargo.rlib, prefix = "lib", suffix = "rlib").
+/// suffix for the given crate type, or returns `None` if the type is not supported. (e.g., for a
+/// Rust library like `libcargo.rlib`, we have prefix "lib" and suffix "rlib").
///
/// The caller needs to ensure that the lines object is at the correct line for the given crate
/// type: this is not checked.
-// This function can not handle more than 1 file per type (with wasm32-unknown-emscripten, there
-// are 2 files for bin (.wasm and .js))
+//
+// This function can not handle more than one file per type (with wasm32-unknown-emscripten, there
+// are two files for bin (`.wasm` and `.js`)).
fn parse_crate_type(
crate_type: &str,
error: &str,
use crate::util::{self, join_paths, process, CargoResult, CfgExpr, Config, ProcessBuilder};
pub struct Doctest {
- /// The package being doctested.
+ /// The package being doc-tested.
pub package: Package,
/// The target being tested (currently always the package's lib).
pub target: Target,
server.configure(&mut rustc);
}
Ok(Compilation {
- native_dirs: BTreeSet::new(), // TODO: deprecated, remove
+ // TODO: deprecated; remove.
+ native_dirs: BTreeSet::new(),
root_output: PathBuf::from("/"),
deps_output: PathBuf::from("/"),
host_deps_output: PathBuf::from("/"),
}
pub struct CompilationFiles<'a, 'cfg: 'a> {
- /// The target directory layout for the host (and target if it is the same as host)
+ /// The target directory layout for the host (and target if it is the same as host).
pub(super) host: Layout,
- /// The target directory layout for the target (if different from then host)
+ /// The target directory layout for the target (if different from then host).
pub(super) target: Option<Layout>,
/// Additional directory to include a copy of the outputs.
export_dir: Option<PathBuf>,
/// Absolute path to the file that will be produced by the build process.
pub path: PathBuf,
/// If it should be linked into `target`, and what it should be called
- /// (e.g. without metadata).
+ /// (e.g., without metadata).
pub hardlink: Option<PathBuf>,
/// If `--out-dir` is specified, the absolute path to the exported file.
pub export_path: Option<PathBuf>,
}
impl OutputFile {
- /// Gets the hardlink if present. Otherwise returns the path.
+ /// Gets the hard link if present; otherwise, returns the path.
pub fn bin_dst(&self) -> &PathBuf {
match self.hardlink {
Some(ref link_dst) => link_dst,
}
}
- /// Get the metadata for a target in a specific profile
- /// We build to the path: "{filename}-{target_metadata}"
+ /// Gets the metadata for a target in a specific profile.
+ /// We build to the path `"{filename}-{target_metadata}"`.
/// We use a linking step to link/copy to a predictable filename
/// like `target/debug/libfoo.{a,so,rlib}` and such.
pub fn metadata(&self, unit: &Unit<'a>) -> Option<Metadata> {
self.metas[unit].clone()
}
- /// Get the short hash based only on the PackageId
- /// Used for the metadata when target_metadata returns None
+ /// Gets the short hash based only on the `PackageId`.
+ /// Used for the metadata when `target_metadata` returns `None`.
pub fn target_short_hash(&self, unit: &Unit<'_>) -> String {
let hashable = unit.pkg.package_id().stable_hash(self.ws.root());
util::short_hash(&hashable)
}
}
- /// Return the root of the build output tree
+ /// Returns the root of the build output tree.
pub fn target_root(&self) -> &Path {
self.host.dest()
}
self.layout(unit.kind).build().join(dir).join("out")
}
- /// Returns the file stem for a given target/profile combo (with metadata)
+ /// Returns the file stem for a given target/profile combo (with metadata).
pub fn file_stem(&self, unit: &Unit<'a>) -> String {
match self.metas[unit] {
Some(ref metadata) => format!("{}-{}", unit.target.crate_name(), metadata),
.map(Arc::clone)
}
- /// Returns the bin stem for a given target (without metadata)
+ /// Returns the bin stem for a given target (without metadata).
fn bin_stem(&self, unit: &Unit<'_>) -> String {
if unit.target.allows_underscores() {
unit.target.name().to_string()
/// our target to be copied to. Eg, file_stem may be out_dir/deps/foo-abcdef
/// and link_stem would be out_dir/foo
/// This function returns it in two parts so the caller can add prefix/suffix
- /// to filename separately
+ /// to filename separately.
///
- /// Returns an Option because in some cases we don't want to link
- /// (eg a dependent lib)
+ /// Returns an `Option` because in some cases we don't want to link
+ /// (eg a dependent lib).
fn link_stem(&self, unit: &Unit<'a>) -> Option<(PathBuf, String)> {
let out_dir = self.out_dir(unit);
let bin_stem = self.bin_stem(unit);
// it was compiled into something like `example/` or `doc/` then
// we don't want to link it up.
if out_dir.ends_with("deps") {
- // Don't lift up library dependencies
+ // Don't lift up library dependencies.
if unit.target.is_bin() || self.roots.contains(unit) {
Some((
out_dir.parent().unwrap().to_owned(),
});
}
}
- // not supported, don't worry about it
+ // Not supported; don't worry about it.
None => {
unsupported.push(crate_type.to_string());
}
}
Ok(())
};
- //info!("{:?}", unit);
+ // info!("{:?}", unit);
match *unit.target.kind() {
TargetKind::Bin
| TargetKind::CustomBuild
cx: &Context<'a, 'cfg>,
metas: &mut HashMap<Unit<'a>, Option<Metadata>>,
) -> Option<Metadata> {
- // No metadata for dylibs because of a couple issues
- // - OSX encodes the dylib name in the executable
- // - Windows rustc multiple files of which we can't easily link all of them
+ // No metadata for dylibs because of a couple issues:
+ // - macOS encodes the dylib name in the executable,
+ // - Windows rustc multiple files of which we can't easily link all of them.
//
- // No metadata for bin because of an issue
- // - wasm32 rustc/emcc encodes the .wasm name in the .js (rust-lang/cargo#4535)
+ // No metadata for bin because of an issue:
+ // - wasm32 rustc/emcc encodes the `.wasm` name in the `.js` (rust-lang/cargo#4535).
//
- // Two exceptions
- // 1) Upstream dependencies (we aren't exporting + need to resolve name conflict)
- // 2) __CARGO_DEFAULT_LIB_METADATA env var
+ // Two exceptions:
+ // 1) Upstream dependencies (we aren't exporting + need to resolve name conflict),
+ // 2) `__CARGO_DEFAULT_LIB_METADATA` env var.
//
- // Note, though, that the compiler's build system at least wants
+ // Note, however, that the compiler's build system at least wants
// path dependencies (eg libstd) to have hashes in filenames. To account for
// that we have an extra hack here which reads the
// `__CARGO_DEFAULT_LIB_METADATA` environment variable and creates a
1.hash(&mut hasher);
// Unique metadata per (name, source, version) triple. This'll allow us
- // to pull crates from anywhere w/o worrying about conflicts
+ // to pull crates from anywhere without worrying about conflicts.
unit.pkg
.package_id()
.stable_hash(bcx.ws.root())
.hash(&mut hasher);
// Add package properties which map to environment variables
- // exposed by Cargo
+ // exposed by Cargo.
let manifest_metadata = unit.pkg.manifest().metadata();
manifest_metadata.authors.hash(&mut hasher);
manifest_metadata.description.hash(&mut hasher);
.features_sorted(unit.pkg.package_id())
.hash(&mut hasher);
- // Mix in the target-metadata of all the dependencies of this target
+ // Mix in the target-metadata of all the dependencies of this target.
{
let mut deps_metadata = cx
.dep_targets(unit)
}
// Throw in the profile we're compiling with. This helps caching
- // panic=abort and panic=unwind artifacts, additionally with various
+ // `panic=abort` and `panic=unwind` artifacts, additionally with various
// settings like debuginfo and whatnot.
unit.profile.hash(&mut hasher);
unit.mode.hash(&mut hasher);
bcx.rustc.verbose_version.hash(&mut hasher);
- // Seed the contents of __CARGO_DEFAULT_LIB_METADATA to the hasher if present.
+ // Seed the contents of `__CARGO_DEFAULT_LIB_METADATA` to the hasher if present.
// This should be the release channel, to get a different hash for each channel.
if let Ok(ref channel) = __cargo_default_lib_metadata {
channel.hash(&mut hasher);
use self::compilation_files::CompilationFiles;
pub use self::compilation_files::{Metadata, OutputFile};
-/// All information needed to define a Unit.
+/// All information needed to define a unit.
///
/// A unit is an object that has enough information so that cargo knows how to build it.
/// For example, if your package has dependencies, then every dependency will be built as a library
/// the host architecture so the host rustc can use it (when compiling to the target
/// architecture).
pub kind: Kind,
- /// The "mode" this unit is being compiled for. See `CompileMode` for
- /// more details.
+ /// The "mode" this unit is being compiled for. See [`CompileMode`] for more details.
pub mode: CompileMode,
}
}
if unit.mode == CompileMode::Doctest {
- // Note that we can *only* doctest rlib outputs here. A
+ // Note that we can *only* doc-test rlib outputs here. A
// staticlib output cannot be linked by the compiler (it just
// doesn't do that). A dylib output, however, can be linked by
// the compiler, but will always fail. Currently all dylibs are
self.files.as_mut().unwrap()
}
- /// Return the filenames that the given unit will generate.
+ /// Returns the filenames that the given unit will generate.
pub fn outputs(&self, unit: &Unit<'a>) -> CargoResult<Arc<Vec<OutputFile>>> {
self.files.as_ref().unwrap().outputs(unit, self.bcx)
}
/// For a package, return all targets which are registered as dependencies
/// for that package.
- // TODO: this ideally should be `-> &[Unit<'a>]`
+ //
+ // TODO: this ideally should be `-> &[Unit<'a>]`.
pub fn dep_targets(&self, unit: &Unit<'a>) -> Vec<Unit<'a>> {
// If this build script's execution has been overridden then we don't
// actually depend on anything, we've reached the end of the dependency
self.primary_packages.contains(&unit.pkg.package_id())
}
- /// Gets a package for the given package id.
+ /// Gets a package for the given package ID.
pub fn get_package(&self, id: PackageId) -> CargoResult<&'a Package> {
self.package_cache
.get(&id)
.ok_or_else(|| failure::format_err!("failed to find {}", id))
}
- /// Return the list of filenames read by cargo to generate the BuildContext
- /// (all Cargo.toml, etc).
+ /// Returns the list of filenames read by cargo to generate the `BuildContext`
+ /// (all `Cargo.toml`, etc.).
pub fn build_plan_inputs(&self) -> CargoResult<Vec<PathBuf>> {
let mut inputs = Vec::new();
// Note that we're using the `package_cache`, which should have been
// populated by `build_unit_dependencies`, and only those packages are
// considered as all the inputs.
//
- // (notably we skip dev-deps here if they aren't present)
+ // (Notably, we skip dev-deps here if they aren't present.)
for pkg in self.package_cache.values() {
inputs.push(pkg.manifest_path().to_path_buf());
}
)
};
let suggestion = "Consider changing their names to be unique or compiling them separately.\n\
- This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313";
+ This may become a hard error in the future; see \
+ <https://github.com/rust-lang/cargo/issues/6313>.";
let report_collision = |unit: &Unit<'_>,
other_unit: &Unit<'_>,
path: &PathBuf|
// We check the global test mode to see if we are running in `cargo
// test` in which case we ensure all dependencies have `panic`
// cleared, and avoid building the lib thrice (once with `panic`, once
- // without, once for --test). In particular, the lib included for
- // doctests and examples are `Build` mode here.
+ // without, once for `--test`). In particular, the lib included for
+ // Doc tests and examples are `Build` mode here.
let unit_for = if unit.mode.is_any_test() || bcx.build_config.test() {
UnitFor::new_test()
} else if unit.target.is_custom_build() {
// generates all units.
UnitFor::new_build()
} else if unit.target.for_host() {
- // proc-macro/plugin should never have panic set.
+ // Proc macro / plugin should never have panic set.
UnitFor::new_compiler()
} else {
UnitFor::new_normal()
state: &mut State<'a, 'cfg, 'tmp>,
unit_for: UnitFor,
) -> CargoResult<()> {
- // Currently the `deps` map does not include `unit_for`. This should
- // be safe for now. `TestDependency` only exists to clear the `panic`
+ // Currently the `deps` map does not include `unit_for`. This should
+ // be safe for now. `TestDependency` only exists to clear the `panic`
// flag, and you'll never ask for a `unit` with `panic` set as a
- // `TestDependency`. `CustomBuild` should also be fine since if the
+ // `TestDependency`. `CustomBuild` should also be fine since if the
// requested unit's settings are the same as `Any`, `CustomBuild` can't
// affect anything else in the hierarchy.
if !state.deps.contains_key(unit) {
Ok(())
}
-/// For a package, return all targets which are registered as dependencies
+/// For a package, returns all targets that are registered as dependencies
/// for that package.
-/// This returns a vec of `(Unit, UnitFor)` pairs. The `UnitFor`
+/// This returns a `Vec` of `(Unit, UnitFor)` pairs. The `UnitFor`
/// is the profile type that should be used for dependencies of the unit.
fn compute_deps<'a, 'cfg, 'tmp>(
unit: &Unit<'a>,
if unit.mode.is_run_custom_build() {
return compute_deps_custom_build(unit, state.bcx);
} else if unit.mode.is_doc() && !unit.mode.is_any_test() {
- // Note: This does not include Doctest.
+ // Note: this does not include doc test.
return compute_deps_doc(unit, state);
}
return false;
}
- // If this dependency is *not* a transitive dependency, then it
- // only applies to test/example targets
+ // If this dependency is **not** a transitive dependency, then it
+ // only applies to test/example targets.
if !dep.is_transitive()
&& !unit.target.is_test()
&& !unit.target.is_example()
) -> CargoResult<Vec<(Unit<'a>, UnitFor)>> {
// When not overridden, then the dependencies to run a build script are:
//
- // 1. Compiling the build script itself
+ // 1. Compiling the build script itself.
// 2. For each immediate dependency of our package which has a `links`
// key, the execution of that build script.
//
unit.pkg,
unit.target,
UnitFor::new_build(),
- Kind::Host, // build scripts always compiled for the host
+ // Build scripts always compiled for the host.
+ Kind::Host,
CompileMode::Build,
);
// All dependencies of this unit should use profiles for custom
Ok(vec![(unit, UnitFor::new_build())])
}
-/// Returns the dependencies necessary to document a package
+/// Returns the dependencies necessary to document a package.
fn compute_deps_doc<'a, 'cfg, 'tmp>(
unit: &Unit<'a>,
state: &mut State<'a, 'cfg, 'tmp>,
Some(lib) => lib,
None => continue,
};
- // rustdoc only needs rmeta files for regular dependencies.
- // However, for plugins/proc-macros, deps should be built like normal.
+ // Rustdoc only needs rmeta files for regular dependencies.
+ // However, for plugins/proc macros, deps should be built like normal.
let mode = check_or_build_mode(unit.mode, lib);
let dep_unit_for = UnitFor::new_normal().with_for_host(lib.for_host());
let lib_unit = new_unit(bcx, dep, lib, dep_unit_for, unit.kind.for_target(lib), mode);
}
}
- // Be sure to build/run the build script for documented libraries as
+ // Be sure to build/run the build script for documented libraries.
ret.extend(dep_build_script(unit, bcx));
- // If we document a binary, we need the library available
+ // If we document a binary, we need the library available.
if unit.target.is_bin() {
ret.extend(maybe_lib(unit, bcx, UnitFor::new_normal()));
}
match mode {
CompileMode::Check { .. } | CompileMode::Doc { .. } => {
if target.for_host() {
- // Plugin and proc-macro targets should be compiled like
+ // Plugin and proc macro targets should be compiled like
// normal.
CompileMode::Build
} else {
}
}
- // And next we take a look at all build scripts executions listed in the
+ // Next, we take a look at all build scripts executions listed in the
// dependency map. Our job here is to take everything that depends on
// this build script (from our reverse map above) and look at the other
// package dependencies of these parents.
/// Contains the parsed output of a custom build script.
#[derive(Clone, Debug, Hash)]
pub struct BuildOutput {
- /// Paths to pass to rustc with the `-L` flag
+ /// Paths to pass to rustc with the `-L` flag.
pub library_paths: Vec<PathBuf>,
- /// Names and link kinds of libraries, suitable for the `-l` flag
+ /// Names and link kinds of libraries, suitable for the `-l` flag.
pub library_links: Vec<String>,
- /// Various `--cfg` flags to pass to the compiler
+ /// Various `--cfg` flags to pass to the compiler.
pub cfgs: Vec<String>,
/// Additional environment variables to run the compiler with.
pub env: Vec<(String, String)>,
- /// Metadata to pass to the immediate dependencies
+ /// Metadata to pass to the immediate dependencies.
pub metadata: Vec<(String, String)>,
/// Paths to trigger a rerun of this build script.
/// May be absolute or relative paths (relative to package root).
pub rerun_if_changed: Vec<PathBuf>,
/// Environment variables which, when changed, will cause a rebuild.
pub rerun_if_env_changed: Vec<String>,
- /// Warnings generated by this build,
+ /// Warnings generated by this build.
pub warnings: Vec<String>,
}
-/// Map of packages to build info
+/// Map of packages to build info.
pub type BuildMap = HashMap<(PackageId, Kind), BuildOutput>;
-/// Build info and overrides
+/// Build info and overrides.
pub struct BuildState {
pub outputs: Mutex<BuildMap>,
overrides: HashMap<(String, Kind), BuildOutput>,
#[derive(Default)]
pub struct BuildScripts {
- // Cargo will use this `to_link` vector to add -L flags to compiles as we
+ // Cargo will use this `to_link` vector to add `-L` flags to compiles as we
// propagate them upwards towards the final build. Note, however, that we
// need to preserve the ordering of `to_link` to be topologically sorted.
// This will ensure that build scripts which print their paths properly will
// this as we're building interactively below to ensure that the memory
// usage here doesn't blow up too much.
//
- // For more information, see #2354
+ // For more information, see #2354.
pub to_link: Vec<(PackageId, Kind)>,
seen_to_link: HashSet<(PackageId, Kind)>,
pub plugins: BTreeSet<PackageId>,
// environment variables. Note that the profile-related environment
// variables are not set with this the build script's profile but rather the
// package's library profile.
- // NOTE: If you add any profile flags, be sure to update
+ // NOTE: if you add any profile flags, be sure to update
// `Profiles::get_profile_run_custom_build` so that those flags get
// carried over.
let to_exec = to_exec.into_os_string();
let json_messages = bcx.build_config.json_messages();
let extra_verbose = bcx.config.extra_verbose();
- // Check to see if the build script has already run, and if it has keep
- // track of whether it has told us about some explicit dependencies
+ // Check to see if the build script has already run, and if it has, keep
+ // track of whether it has told us about some explicit dependencies.
let prev_script_out_dir = paths::read_bytes(&root_output_file)
.and_then(|bytes| util::bytes2path(&bytes))
.unwrap_or_else(|_| script_out_dir.clone());
let value = iter.next();
let (key, value) = match (key, value) {
(Some(a), Some(b)) => (a, b.trim_end()),
- // line started with `cargo:` but didn't match `key=value`
+ // Line started with `cargo:` but didn't match `key=value`.
_ => failure::bail!("Wrong output in {}: `{}`", whence, line),
};
}
}
-/// Compute the `build_scripts` map in the `Context` which tracks what build
+/// Computes the `build_scripts` map in the `Context` which tracks what build
/// scripts each package depends on.
///
/// The global `build_scripts` map lists for all (package, kind) tuples what set
}
// When adding an entry to 'to_link' we only actually push it on if the
- // script hasn't seen it yet (e.g. we don't push on duplicates).
+ // script hasn't seen it yet (e.g., we don't push on duplicates).
fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, kind: Kind) {
if scripts.seen_to_link.insert((pkg, kind)) {
scripts.to_link.push((pkg, kind));
let compare = compare_old_fingerprint(&loc, &*fingerprint, mtime_on_use);
log_compare(unit, &compare);
- // If our comparison failed (e.g. we're going to trigger a rebuild of this
+ // If our comparison failed (e.g., we're going to trigger a rebuild of this
// crate), then we also ensure the source of the crate passes all
// verification checks before we build it.
//
}
/// A compilation unit dependency has a fingerprint that is comprised of:
-/// * its package id
+/// * its package ID
/// * its extern crate name
/// * its calculated fingerprint for the dependency
struct DepFingerprint {
/// * Any dependency changes
/// * The compiler changes
/// * The set of features a package is built with changes
-/// * The profile a target is compiled with changes (e.g. opt-level changes)
+/// * The profile a target is compiled with changes (e.g., opt-level changes)
///
/// Information like file modification time is only calculated for path
/// dependencies and is calculated in `calculate_target_fresh`.
}
};
- // TODO: fix #5918
+ // TODO: fix #5918.
// Note that equal mtimes should be considered "stale". For filesystems with
// not much timestamp precision like 1s this is would be a conservative approximation
// to handle the case where a file is modified within the same second after
}
impl Job {
- /// Create a new job representing a unit of work.
+ /// Creates a new job representing a unit of work.
pub fn new(dirty: Work, fresh: Work) -> Job {
Job { dirty, fresh }
}
use crate::util::{internal, profile, CargoResult, CargoResultExt, ProcessBuilder};
use crate::util::{Config, DependencyQueue, Dirty, Fresh, Freshness};
use crate::util::{Progress, ProgressStyle};
-
use super::context::OutputFile;
use super::job::Job;
use super::{BuildContext, BuildPlan, CompileMode, Context, Kind, Unit};
/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
- /// Number of jobs currently active
+ /// The number of jobs currently active.
amt: usize,
- /// Current freshness state of this package. Any dirty target within a
+ /// The current freshness state of this package. Any dirty target within a
/// package will cause the entire package to become dirty.
fresh: Freshness,
}
Ok(())
}
- /// Execute all jobs necessary to build the dependency graph.
+ /// Executes all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
/// necessary dependencies, in order. Freshness is propagated as far as
// loop starts out by scheduling as much work as possible (up to the
// maximum number of parallel jobs we have tokens for). A local queue
// is maintained separately from the main dependency queue as one
- // dequeue may actually dequeue quite a bit of work (e.g. 10 binaries
+ // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries
// in one package).
//
// After a job has finished we update our internal state if it was
Message::Finish(key, result) => {
info!("end: {:?}", key);
- // self.active.remove_item(&key); // <- switch to this when stabilized.
+ // FIXME: switch to this when stabilized.
+ // self.active.remove_item(&key);
let pos = self
.active
.iter()
self.progress.clear();
let build_type = if self.is_release { "release" } else { "dev" };
- // NOTE: This may be a bit inaccurate, since this may not display the
- // profile for what was actually built. Profile overrides can change
+ // NOTE: this may be a bit inaccurate, since this may not display the
+ // profile for what was actually built. Profile overrides can change
// these settings, and in some cases different targets are built with
- // different profiles. To be accurate, it would need to collect a
+ // different profiles. To be accurate, it would need to collect a
// list of Units built, and maybe display a list of the different
- // profiles used. However, to keep it simple and compatible with old
+ // profiles used. However, to keep it simple and compatible with old
// behavior, we just display what the base profile is.
let profile = cx.bcx.profiles.base_profile(self.is_release);
let mut opt_type = String::from(if profile.opt_level.as_str() == "0" {
};
if !build_plan {
- // Print out some nice progress information
+ // Print out some nice progress information.
self.note_working_on(config, &key, fresh)?;
}
match fresh {
// Any dirty stage which runs at least one command gets printed as
- // being a compiled package
+ // being a compiled package.
Dirty => {
if key.mode.is_doc() {
- // Skip Doctest
+ // Skip doc test.
if !key.mode.is_any_test() {
self.documented.insert(key.pkg);
config.shell().status("Documenting", key.pkg)?;
}
}
Fresh => {
- // If doctest is last, only print "Fresh" if nothing has been printed.
+ // If doc test are last, only print "Fresh" if nothing has been printed.
if self.counts[&key.pkg] == 0
&& !(key.mode == CompileMode::Doctest && self.compiled.contains(&key.pkg))
{
incremental: PathBuf,
fingerprint: PathBuf,
examples: PathBuf,
- /// The lockfile for a build, will be unlocked when this struct is `drop`ped.
+ /// The lock file for a build, will be unlocked when this struct is `drop`ped.
_lock: FileLock,
}
// doesn't prevent Cargo from working
}
- /// Make sure all directories stored in the Layout exist on the filesystem.
+ /// Makes sure all directories stored in the Layout exist on the filesystem.
pub fn prepare(&mut self) -> io::Result<()> {
if fs::metadata(&self.root).is_err() {
fs::create_dir_all(&self.root)?;
+mod build_config;
+mod build_context;
+mod build_plan;
+mod compilation;
+mod context;
+mod custom_build;
+mod fingerprint;
+mod job;
+mod job_queue;
+mod layout;
+mod output_depinfo;
+
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use crate::util::paths;
use crate::util::{self, machine_message, process, Freshness, ProcessBuilder};
use crate::util::{internal, join_paths, profile};
-
-use self::build_plan::BuildPlan;
-use self::job::{Job, Work};
-use self::job_queue::JobQueue;
-
-use self::output_depinfo::output_depinfo;
-
pub use self::build_config::{BuildConfig, CompileMode, MessageFormat};
pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo};
+use self::build_plan::BuildPlan;
pub use self::compilation::{Compilation, Doctest};
pub use self::context::{Context, Unit};
pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts};
+use self::job::{Job, Work};
+use self::job_queue::JobQueue;
pub use self::layout::is_bad_artifact_name;
+use self::output_depinfo::output_depinfo;
-mod build_config;
-mod build_context;
-mod build_plan;
-mod compilation;
-mod context;
-mod custom_build;
-mod fingerprint;
-mod job;
-mod job_queue;
-mod layout;
-mod output_depinfo;
-
-/// Whether an object is for the host arch, or the target arch.
+/// Indicates whether an object is for the host architcture or the target architecture.
///
/// These will be the same unless cross-compiling.
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
}
/// A glorified callback for executing calls to rustc. Rather than calling rustc
-/// directly, we'll use an Executor, giving clients an opportunity to intercept
+/// directly, we'll use an `Executor`, giving clients an opportunity to intercept
/// the build calls.
pub trait Executor: Send + Sync + 'static {
/// Called after a rustc process invocation is prepared up-front for a given
mode: CompileMode,
_state: &job_queue::JobState<'_>,
) -> CargoResult<()> {
- // we forward to exec() to keep RLS working.
+ // We forward to `exec()` to keep RLS working.
self.exec(cmd, id, target, mode)
}
let (dirty, fresh, freshness) = if unit.mode.is_run_custom_build() {
custom_build::prepare(cx, unit)?
} else if unit.mode == CompileMode::Doctest {
- // we run these targets later, so this is just a noop for now
+ // We run these targets later, so this is just a no-op for now.
(Work::noop(), Work::noop(), Freshness::Fresh)
} else if build_plan {
(
} else {
rustc(cx, unit, exec)?
};
- // Need to link targets on both the dirty and fresh
+ // Need to link targets on both the dirty and fresh.
let dirty = work.then(link_targets(cx, unit, false)?).then(dirty);
let fresh = link_targets(cx, unit, true)?.then(fresh);
let root = cx.files().out_dir(unit);
let kind = unit.kind;
- // Prepare the native lib state (extra -L and -l flags)
+ // Prepare the native lib state (extra `-L` and `-l` flags).
let build_state = cx.build_state.clone();
let current_id = unit.pkg.package_id();
let build_deps = load_build_deps(cx, unit);
let real_name = unit.target.name().to_string();
let crate_name = unit.target.crate_name();
- // XXX(Rely on target_filenames iterator as source of truth rather than rederiving filestem)
+ // Rely on `target_filenames` iterator as source of truth rather than rederiving filestem.
let rustc_dep_info_loc = if do_rename && cx.files().metadata(unit).is_none() {
root.join(&crate_name)
} else {
}
fn internal_if_simple_exit_code(err: Error) -> Error {
- // If a signal on unix (code == None) or an abnormal termination
- // on Windows (codes like 0xC0000409), don't hide the error details.
+ // If a signal on unix (`code == None`) or an abnormal termination
+ // on Windows (codes like `0xC0000409`), don't hide the error details.
match err
.downcast_ref::<ProcessError>()
.as_ref()
Ok(())
}));
- // Add all relevant -L and -l flags from dependencies (now calculated and
- // present in `state`) to the command provided
+ // Add all relevant `-L` and `-l` flags from dependencies (now calculated and
+ // present in `state`) to the command provided.
fn add_native_deps(
rustc: &mut ProcessBuilder,
build_state: &BuildMap,
}
/// Link the compiled target (often of form `foo-{metadata_hash}`) to the
-/// final target. This must happen during both "Fresh" and "Compile"
+/// final target. This must happen during both "Fresh" and "Compile".
fn link_targets<'a, 'cfg>(
cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>,
}
Ok(Work::new(move |_| {
- // If we're a "root crate", e.g. the target of this compilation, then we
+ // If we're a "root crate", e.g., the target of this compilation, then we
// hard link our outputs out of the `deps` directory into the directory
// above. This means that `cargo build` will produce binaries in
// `target/debug` which one probably expects.
// Determine paths to add to the dynamic search path from -L entries
//
// Strip off prefixes like "native=" or "framework=" and filter out directories
-// *not* inside our output directory since they are likely spurious and can cause
+// **not** inside our output directory since they are likely spurious and can cause
// clashes with system shared libraries (issue #3366).
fn filter_dynamic_search_path<'a, I>(paths: I, root_output: &PathBuf) -> Vec<PathBuf>
where
cmd.args(args);
}
- // -C overflow-checks is implied by the setting of -C debug-assertions,
- // so we only need to provide -C overflow-checks if it differs from
- // the value of -C debug-assertions we would provide.
+ // `-C overflow-checks` is implied by the setting of `-C debug-assertions`,
+ // so we only need to provide `-C overflow-checks` if it differs from
+ // the value of `-C debug-assertions` we would provide.
if opt_level.as_str() != "0" {
if debug_assertions {
cmd.args(&["-C", "debug-assertions=on"]);
deps
});
- // Be sure that the host path is also listed. This'll ensure that proc-macro
+ // Be sure that the host path is also listed. This'll ensure that proc macro
// dependencies are correctly found (for reexported macros).
if let Kind::Target = unit.kind {
cmd.arg("-L").arg(&{
// If there is not one linkable target but should, rustc fails later
// on if there is an `extern crate` for it. This may turn into a hard
- // error in the future, see PR #4797
+ // error in the future (see PR #4797).
if !dep_targets
.iter()
.any(|u| !u.mode.is_doc() && u.target.linkable())
fn for_target(self, target: &Target) -> Kind {
// Once we start compiling for the `Host` kind we continue doing so, but
// if we are a `Target` kind and then we start compiling for a target
- // that needs to be on the host we lift ourselves up to `Host`
+ // that needs to be on the host we lift ourselves up to `Host`.
match self {
Kind::Host => Kind::Host,
Kind::Target if target.for_host() => Kind::Host,
}
fn json_stderr(line: &str, package_id: PackageId, target: &Target) -> CargoResult<()> {
- // stderr from rustc/rustdoc can have a mix of JSON and non-JSON output
+ // Stderr from rustc/rustdoc can have a mix of JSON and non-JSON output.
if line.starts_with('{') {
- // Handle JSON lines
+ // Handle JSON lines.
let compiler_message = serde_json::from_str(line)
.map_err(|_| internal(&format!("compiler produced invalid json: `{}`", line)))?;
message: compiler_message,
});
} else {
- // Forward non-JSON to stderr
+ // Forward non-JSON to stderr.
writeln!(io::stderr(), "{}", line)?;
}
Ok(())
inner: Rc<Inner>,
}
-/// The data underlying a Dependency.
+/// The data underlying a `Dependency`.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
struct Inner {
name: InternedString,
/// This is the name of this `Dependency` as listed in `Cargo.toml`.
///
/// Or in other words, this is what shows up in the `[dependencies]` section
- /// on the left hand side. This is **not** the name of the package that's
+ /// on the left hand side. This is *not* the name of the package that's
/// being depended on as the dependency can be renamed. For that use
/// `package_name` below.
///
self
}
- /// Set the source id for this dependency
+ /// Sets the source ID for this dependency.
pub fn set_source_id(&mut self, id: SourceId) -> &mut Dependency {
Rc::make_mut(&mut self.inner).source_id = id;
self
}
- /// Set the version requirement for this dependency
+ /// Sets the version requirement for this dependency.
pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
Rc::make_mut(&mut self.inner).req = req;
self
self
}
- /// Lock this dependency to depending on the specified package id
+ /// Locks this dependency to depending on the specified package ID.
pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency {
assert_eq!(self.inner.source_id, id.source_id());
assert!(self.inner.req.matches(id.version()));
.set_source_id(id.source_id())
}
- /// Returns whether this is a "locked" dependency, basically whether it has
+ /// Returns `true` if this is a "locked" dependency, basically whether it has
/// an exact version req.
pub fn is_locked(&self) -> bool {
// Kind of a hack to figure this out, but it works!
self.inner.req.to_string().starts_with('=')
}
- /// Returns false if the dependency is only used to build the local package.
+ /// Returns `false` if the dependency is only used to build the local package.
pub fn is_transitive(&self) -> bool {
match self.inner.kind {
Kind::Normal | Kind::Build => true,
self.inner.optional
}
- /// Returns true if the default features of the dependency are requested.
+ /// Returns `true` if the default features of the dependency are requested.
pub fn uses_default_features(&self) -> bool {
self.inner.default_features
}
&self.inner.features
}
- /// Returns true if the package (`sum`) can fulfill this dependency request.
+ /// Returns `true` if the package (`sum`) can fulfill this dependency request.
pub fn matches(&self, sum: &Summary) -> bool {
self.matches_id(sum.package_id())
}
- /// Returns true if the package (`sum`) can fulfill this dependency request.
+ /// Returns `true` if the package (`sum`) can fulfill this dependency request.
pub fn matches_ignoring_source(&self, id: PackageId) -> bool {
self.package_name() == id.name() && self.version_req().matches(id.version())
}
- /// Returns true if the package (`id`) can fulfill this dependency request.
+ /// Returns `true` if the package (`id`) can fulfill this dependency request.
pub fn matches_id(&self, id: PackageId) -> bool {
self.inner.name == id.name()
&& (self.inner.only_match_name
-//! Support for nightly features in Cargo itself
+//! Support for nightly features in Cargo itself.
//!
//! This file is the version of `feature_gate.rs` in upstream Rust for Cargo
//! itself and is intended to be the avenue for which new features in Cargo are
//!
//! 4. Update the unstable documentation at
//! `src/doc/src/reference/unstable.md` to include a short description of
-//! how to use your new feature. When the feature is stabilized, be sure
+//! how to use your new feature. When the feature is stabilized, be sure
//! that the Cargo Guide or Reference is updated to fully document the
//! feature and remove the entry from the Unstable section.
//!
}
impl Hash for InternedString {
- // NB: we can't implement this as `identity(self).hash(state)`,
+ // N.B., we can't implement this as `identity(self).hash(state)`,
// because we use this for on-disk fingerprints and so need
// stability across Cargo invocations.
fn hash<H: Hasher>(&self, state: &mut H) {
}
impl Borrow<str> for InternedString {
- // if we implement Hash as `identity(self).hash(state)`,
+ // If we implement Hash as `identity(self).hash(state)`,
// then this will nead to be removed.
fn borrow(&self) -> &str {
self.as_str()
Virtual(VirtualManifest),
}
-/// Contains all the information about a package, as loaded from a Cargo.toml.
+/// Contains all the information about a package, as loaded from a `Cargo.toml`.
#[derive(Clone, Debug)]
pub struct Manifest {
summary: Summary,
pub categories: Vec<String>,
pub license: Option<String>,
pub license_file: Option<String>,
- pub description: Option<String>, // not markdown
- pub readme: Option<String>, // file, not contents
- pub homepage: Option<String>, // url
- pub repository: Option<String>, // url
- pub documentation: Option<String>, // url
+ pub description: Option<String>, // Not in Markdown
+ pub readme: Option<String>, // File, not contents
+ pub homepage: Option<String>, // URL
+ pub repository: Option<String>, // URL
+ pub documentation: Option<String>, // URL
pub badges: BTreeMap<String, BTreeMap<String, String>>,
pub links: Option<String>,
}
/// Information about a package that is available somewhere in the file system.
///
/// A package is a `Cargo.toml` file plus all the files that are part of it.
-// TODO: Is manifest_path a relic?
+//
+// TODO: is `manifest_path` a relic?
#[derive(Clone)]
pub struct Package {
- /// The package's manifest
+ /// The package's manifest.
manifest: Manifest,
- /// The root of the package
+ /// The root of the package.
manifest_path: PathBuf,
}
}
impl Package {
- /// Create a package from a manifest and its location
+ /// Creates a package from a manifest and its location.
pub fn new(manifest: Manifest, manifest_path: &Path) -> Package {
Package {
manifest,
}
}
- /// Get the manifest dependencies
+ /// Gets the manifest dependencies.
pub fn dependencies(&self) -> &[Dependency] {
self.manifest.dependencies()
}
- /// Get the manifest
+ /// Gets the manifest.
pub fn manifest(&self) -> &Manifest {
&self.manifest
}
- /// Get the path to the manifest
+ /// Gets the path to the manifest.
pub fn manifest_path(&self) -> &Path {
&self.manifest_path
}
- /// Get the name of the package
+ /// Gets the name of the package.
pub fn name(&self) -> InternedString {
self.package_id().name()
}
- /// Get the PackageId object for the package (fully defines a package)
+ /// Gets the `PackageId` object for the package (fully defines a package).
pub fn package_id(&self) -> PackageId {
self.manifest.package_id()
}
- /// Get the root folder of the package
+ /// Gets the root folder of the package.
pub fn root(&self) -> &Path {
self.manifest_path.parent().unwrap()
}
- /// Get the summary for the package
+ /// Gets the summary for the package.
pub fn summary(&self) -> &Summary {
self.manifest.summary()
}
- /// Get the targets specified in the manifest
+ /// Gets the targets specified in the manifest.
pub fn targets(&self) -> &[Target] {
self.manifest.targets()
}
- /// Get the current package version
+ /// Gets the current package version.
pub fn version(&self) -> &Version {
self.package_id().version()
}
- /// Get the package authors
+ /// Gets the package authors.
pub fn authors(&self) -> &Vec<String> {
&self.manifest.metadata().authors
}
- /// Whether the package is set to publish
+ /// Returns `true` if the package is set to publish.
pub fn publish(&self) -> &Option<Vec<String>> {
self.manifest.publish()
}
- /// Whether the package uses a custom build script for any target
+ /// Returns `true` if the package uses a custom build script for any target.
pub fn has_custom_build(&self) -> bool {
self.targets().iter().any(|t| t.is_custom_build())
}
# When uploading crates to the registry Cargo will automatically\n\
# \"normalize\" Cargo.toml files for maximal compatibility\n\
# with all versions of Cargo and also rewrite `path` dependencies\n\
- # to registry (e.g. crates.io) dependencies\n\
+ # to registry (e.g., crates.io) dependencies\n\
#\n\
# If you believe there's an error in this file please file an\n\
# issue against the rust-lang/cargo repository. If you're\n\
///
/// Note that timeout management is done manually here instead of in libcurl
/// because we want to apply timeouts to an entire batch of operations, not
- /// any one particular single operatino
- timeout: ops::HttpTimeout, // timeout configuration
+ /// any one particular single operation.
+ timeout: ops::HttpTimeout, // timeout configuration
updated_at: Cell<Instant>, // last time we received bytes
next_speed_check: Cell<Instant>, // if threshold isn't 0 by this time, error
next_speed_check_bytes_threshold: Cell<u64>, // decremented when we receive bytes
}
struct Download<'cfg> {
- /// Token for this download, used as the key of the `Downloads::pending` map
+ /// The token for this download, used as the key of the `Downloads::pending` map
/// and stored in `EasyHandle` as well.
token: usize,
- /// Package that we're downloading
+ /// The package that we're downloading.
id: PackageId,
- /// Actual downloaded data, updated throughout the lifetime of this download
+ /// Actual downloaded data, updated throughout the lifetime of this download.
data: RefCell<Vec<u8>>,
/// The URL that we're downloading from, cached here for error messages and
/// reenqueuing.
url: String,
- /// A descriptive string to print when we've finished downloading this crate
+ /// A descriptive string to print when we've finished downloading this crate.
descriptor: String,
- /// Statistics updated from the progress callback in libcurl
+ /// Statistics updated from the progress callback in libcurl.
total: Cell<u64>,
current: Cell<u64>,
- /// The moment we started this transfer at
+ /// The moment we started this transfer at.
start: Instant,
timed_out: Cell<Option<String>>,
Ok(None)
}
- /// Returns the number of crates that are still downloading
+ /// Returns the number of crates that are still downloading.
pub fn remaining(&self) -> usize {
self.pending.len()
}
// a few anyway.
//
// Here we start off by asking the `multi` handle to do some work via
- // the `perform` method. This will actually do I/O work (nonblocking)
+ // the `perform` method. This will actually do I/O work (non-blocking)
// and attempt to make progress. Afterwards we ask about the `messages`
// contained in the handle which will inform us if anything has finished
// transferring.
if !progress.is_enabled() {
return;
}
- // If we didn't download anything, no need for a summary
+ // If we didn't download anything, no need for a summary.
if self.downloads_finished == 0 {
return;
}
- // If an error happened, let's not clutter up the output
+ // If an error happened, let's not clutter up the output.
if !self.success {
return;
}
/// 2. the package version (a `Version`, optional)
/// 3. the package source (a `Url`, optional)
///
-/// If any of the optional fields are omitted, then the package id may be ambiguous, there may be
+/// If any of the optional fields are omitted, then the package ID may be ambiguous, there may be
/// more than one package/version/url combo that will match. However, often just the name is
-/// sufficient to uniquely define a package id.
+/// sufficient to uniquely define a package ID.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct PackageIdSpec {
name: String,
I: IntoIterator<Item = PackageId>,
{
let spec = PackageIdSpec::parse(spec)
- .chain_err(|| failure::format_err!("invalid package id specification: `{}`", spec))?;
+ .chain_err(|| failure::format_err!("invalid package ID specification: `{}`", spec))?;
spec.query(i)
}
let ret = match ids.next() {
Some(id) => id,
None => failure::bail!(
- "package id specification `{}` \
+ "package ID specification `{}` \
matched no packages",
self
),
})
}
- /// Retrieve the profile for a target.
+ /// Retrieves the profile for a target.
/// `is_member` is whether or not this package is a member of the
/// workspace.
pub fn get_profile(
| CompileMode::Check { .. }
| CompileMode::Doctest
| CompileMode::RunCustomBuild => {
- // Note: RunCustomBuild doesn't normally use this code path.
+ // Note: `RunCustomBuild` doesn't normally use this code path.
// `build_unit_profiles` normally ensures that it selects the
- // ancestor's profile. However `cargo clean -p` can hit this
+ // ancestor's profile. However, `cargo clean -p` can hit this
// path.
if release {
&self.release
CompileMode::Doc { .. } => &self.doc,
};
let mut profile = maker.get_profile(Some(pkg_id), is_member, unit_for);
- // `panic` should not be set for tests/benches, or any of their
- // dependencies.
+ // `panic` should not be set for tests/benches, or any of their dependencies.
if !unit_for.is_panic_ok() || mode.is_any_test() {
profile.panic = None;
}
}
/// The profile for *running* a `build.rs` script is only used for setting
- /// a few environment variables. To ensure proper de-duplication of the
+ /// a few environment variables. To ensure proper de-duplication of the
/// running `Unit`, this uses a stripped-down profile (so that unrelated
/// profile flags don't cause `build.rs` to needlessly run multiple
/// times).
}
/// This returns a generic base profile. This is currently used for the
- /// `[Finished]` line. It is not entirely accurate, since it doesn't
+ /// `[Finished]` line. It is not entirely accurate, since it doesn't
/// select for the package that was actually built.
pub fn base_profile(&self, release: bool) -> Profile {
if release {
/// An object used for handling the profile override hierarchy.
///
/// The precedence of profiles are (first one wins):
-/// - Profiles in .cargo/config files (using same order as below).
-/// - [profile.dev.overrides.name] - A named package.
-/// - [profile.dev.overrides."*"] - This cannot apply to workspace members.
-/// - [profile.dev.build-override] - This can only apply to `build.rs` scripts
+/// - Profiles in `.cargo/config` files (using same order as below).
+/// - [profile.dev.overrides.name] -- a named package.
+/// - [profile.dev.overrides."*"] -- this cannot apply to workspace members.
+/// - [profile.dev.build-override] -- this can only apply to `build.rs` scripts
/// and their dependencies.
/// - [profile.dev]
/// - Default (hard-coded) values.
pub name: &'static str,
pub opt_level: InternedString,
pub lto: Lto,
- // None = use rustc default
+ // `None` means use rustc default.
pub codegen_units: Option<u32>,
pub debuginfo: Option<u32>,
pub debug_assertions: bool,
}
}
- /// Compare all fields except `name`, which doesn't affect compilation.
+ /// Compares all fields except `name`, which doesn't affect compilation.
/// This is necessary for `Unit` deduplication for things like "test" and
/// "dev" which are essentially the same.
fn comparable(
/// to ensure the target's dependencies have the correct settings.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct UnitFor {
- /// A target for `build.rs` or any of its dependencies. This enables
+ /// A target for `build.rs` or any of its dependencies. This enables
/// `build-override` profiles for these targets.
custom_build: bool,
/// This is true if it is *allowed* to set the `panic` flag. Currently
/// this is false for test/bench targets and all their dependencies, and
- /// "for_host" units such as proc-macro and custom build scripts and their
+ /// "for_host" units such as proc macro and custom build scripts and their
/// dependencies.
panic_ok: bool,
}
impl UnitFor {
- /// A unit for a normal target/dependency (i.e. not custom build,
- /// proc-macro/plugin, or test/bench).
+ /// A unit for a normal target/dependency (i.e., not custom build,
+ /// proc macro/plugin, or test/bench).
pub fn new_normal() -> UnitFor {
UnitFor {
custom_build: false,
}
}
- /// A unit for a proc-macro or compiler plugin or their dependencies.
+ /// A unit for a proc macro or compiler plugin or their dependencies.
pub fn new_compiler() -> UnitFor {
UnitFor {
custom_build: false,
}
}
- /// Create a variant based on `for_host` setting.
+ /// Creates a variant based on `for_host` setting.
///
/// When `for_host` is true, this clears `panic_ok` in a sticky fashion so
/// that all its dependencies also have `panic_ok=false`.
}
}
- /// Returns true if this unit is for a custom build script or one of its
+ /// Returns `true` if this unit is for a custom build script or one of its
/// dependencies.
pub fn is_custom_build(self) -> bool {
self.custom_build
}
- /// Returns true if this unit is allowed to set the `panic` compiler flag.
+ /// Returns `true` if this unit is allowed to set the `panic` compiler flag.
pub fn is_panic_ok(self) -> bool {
self.panic_ok
}
}
}
-/// Profiles loaded from .cargo/config files.
+/// Profiles loaded from `.cargo/config` files.
#[derive(Clone, Debug, Deserialize, Default)]
pub struct ConfigProfiles {
dev: Option<TomlProfile>,
///
/// The resolution phase of Cargo uses this to drive knowledge about new
/// packages as well as querying for lists of new packages. It is here that
-/// sources are updated (e.g. network operations) and overrides are
+/// sources are updated (e.g., network operations) and overrides are
/// handled.
///
/// The general idea behind this registry is that it is centered around the
///
/// Here the `deps` will be resolved to a precise version and stored
/// internally for future calls to `query` below. It's expected that `deps`
- /// have had `lock_to` call already, if applicable. (e.g. if a lock file was
+ /// have had `lock_to` call already, if applicable. (e.g., if a lock file was
/// already present).
///
/// Note that the patch list specified here *will not* be available to
}
/// This function is used to transform a summary to another locked summary
- /// if possible. This is where the concept of a lockfile comes into play.
+ /// if possible. This is where the concept of a lock file comes into play.
///
- /// If a summary points at a package id which was previously locked, then we
- /// override the summary's id itself, as well as all dependencies, to be
+ /// If a summary points at a package ID which was previously locked, then we
+ /// override the summary's ID itself, as well as all dependencies, to be
/// rewritten to the locked versions. This will transform the summary's
/// source to a precise source (listed in the locked version) as well as
/// transforming all of the dependencies from range requirements on
/// imprecise sources to exact requirements on precise sources.
///
- /// If a summary does not point at a package id which was previously locked,
+ /// If a summary does not point at a package ID which was previously locked,
/// or if any dependencies were added and don't have a previously listed
/// version, we still want to avoid updating as many dependencies as
/// possible to keep the graph stable. In this case we map all of the
trace!("locking summary of {}", summary.package_id());
- // Lock the summary's id if possible
+ // Lock the summary's ID if possible
let summary = match pair {
Some(&(ref precise, _)) => summary.override_id(precise.clone()),
None => summary,
//
// 1. We have a lock entry for this dependency from the same
// source as it's listed as coming from. In this case we make
- // sure to lock to precisely the given package id.
+ // sure to lock to precisely the given package ID.
//
// 2. We have a lock entry for this dependency, but it's from a
// different source than what's listed, or the version
use crate::core::resolver::Context;
use crate::core::{Dependency, PackageId};
-/// This is a Trie for storing a large number of Sets designed to
-/// efficiently see if any of the stored Sets are a subset of a search Set.
+/// This is a trie for storing a large number of sets designed to
+/// efficiently see if any of the stored sets are a subset of a search set.
enum ConflictStoreTrie {
- /// a Leaf is one of the stored Sets.
+ /// One of the stored sets.
Leaf(BTreeMap<PackageId, ConflictReason>),
- /// a Node is a map from an element to a subTrie where
- /// all the Sets in the subTrie contains that element.
+ /// A map from an element to a subtrie where
+ /// all the sets in the subtrie contains that element.
Node(BTreeMap<PackageId, ConflictStoreTrie>),
}
match self {
ConflictStoreTrie::Leaf(c) => {
if must_contain.is_none() {
- // is_conflicting checks that all the elements are active,
+ // `is_conflicting` checks that all the elements are active,
// but we have checked each one by the recursion of this function.
debug_assert!(cx.is_conflicting(None, c));
Some(c)
} else {
- // we did not find `must_contain` so we need to keep looking.
+ // We did not find `must_contain`, so we need to keep looking.
None
}
}
.map(|f| m.range(..=f))
.unwrap_or_else(|| m.range(..))
{
- // if the key is active then we need to check all of the corresponding subTrie.
+ // If the key is active, then we need to check all of the corresponding subtrie.
if cx.is_active(pid) {
if let Some(o) =
store.find_conflicting(cx, must_contain.filter(|&f| f != pid))
{
return Some(o);
}
- } // else, if it is not active then there is no way any of the corresponding
- // subTrie will be conflicting.
+ }
+ // Else, if it is not active then there is no way any of the corresponding
+ // subtrie will be conflicting.
}
None
}
p.entry(pid)
.or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new()))
.insert(iter, con);
- } // else, We already have a subset of this in the ConflictStore
+ }
+ // Else, we already have a subset of this in the `ConflictStore`.
} else {
- // we are at the end of the set we are adding, there are 3 cases for what to do next:
- // 1. self is a empty dummy Node inserted by `or_insert_with`
+ // We are at the end of the set we are adding, there are three cases for what to do
+ // next:
+ // 1. `self` is a empty dummy Node inserted by `or_insert_with`
// in witch case we should replace it with `Leaf(con)`.
- // 2. self is a Node because we previously inserted a superset of
+ // 2. `self` is a `Node` because we previously inserted a superset of
// the thing we are working on (I don't know if this happens in practice)
// but the subset that we are working on will
// always match any time the larger set would have
// in witch case we can replace it with `Leaf(con)`.
- // 3. self is a Leaf that is in the same spot in the structure as
+ // 3. `self` is a `Leaf` that is in the same spot in the structure as
// the thing we are working on. So it is equivalent.
// We can replace it with `Leaf(con)`.
if cfg!(debug_assertions) {
// look up which entries are still active without
// linearly scanning through the full list.
//
- // Also, as a final note, this map is *not* ever removed from. This remains
+ // Also, as a final note, this map is **not** ever removed from. This remains
// as a global cache which we never delete from. Any entry in this map is
// unconditionally true regardless of our resolution history of how we got
// here.
self.find_conflicting(cx, dep, None)
}
- /// Add to the cache a conflict of the form:
+ /// Adds to the cache a conflict of the form:
/// `dep` is known to be unresolvable if
- /// all the `PackageId` entries are activated
+ /// all the `PackageId` entries are activated.
pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap<PackageId, ConflictReason>) {
self.con_from_dep
.entry(dep.clone())
use std::collections::{BTreeMap, HashMap, HashSet};
use std::rc::Rc;
-#[allow(unused_imports)] // "ensure" seems to require "bail" be in scope (macro hygiene issue?)
+// "ensure" seems to require "bail" be in scope (macro hygiene issue?).
+#[allow(unused_imports)]
use failure::{bail, ensure};
use log::debug;
/// Activate this summary by inserting it into our list of known activations.
///
- /// Returns true if this summary with the given method is already activated.
+ /// Returns `true` if this summary with the given method is already activated.
pub fn flag_activated(&mut self, summary: &Summary, method: &Method<'_>) -> CargoResult<bool> {
let id = summary.package_id();
let prev = self
.collect::<CargoResult<Vec<DepInfo>>>()?;
// Attempt to resolve dependencies with fewer candidates before trying
- // dependencies with more candidates. This way if the dependency with
+ // dependencies with more candidates. This way if the dependency with
// only one candidate can't be resolved we don't have to do a bunch of
// work before we figure that out.
deps.sort_by_key(|&(_, ref a, _)| a.len());
.unwrap_or(false)
}
- /// checks whether all of `parent` and the keys of `conflicting activations`
- /// are still active
+ /// Checks whether all of `parent` and the keys of `conflicting activations`
+ /// are still active.
pub fn is_conflicting(
&self,
parent: Option<PackageId>,
.all(|&id| self.is_active(id))
}
- /// Return all dependencies and the features we want from them.
+ /// Returns all dependencies and the features we want from them.
fn resolve_features<'b>(
&mut self,
parent: Option<&Summary>,
Method::Required { dev_deps, .. } => dev_deps,
};
- // First, filter by dev-dependencies
+ // First, filter by dev-dependencies.
let deps = s.dependencies();
let deps = deps.iter().filter(|d| d.is_transitive() || dev_deps);
}
}
-/// Takes requested features for a single package from the input Method and
+/// Takes requested features for a single package from the input `Method` and
/// recurses to find all requested features, dependencies and requested
-/// dependency features in a Requirements object, returning it to the resolver.
+/// dependency features in a `Requirements` object, returning it to the resolver.
fn build_requirements<'a, 'b: 'a>(
s: &'a Summary,
method: &'b Method<'_>,
{
match *fv {
FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => failure::bail!(
- "Cyclic feature dependency: feature `{}` depends on itself",
+ "cyclic feature dependency: feature `{}` depends on itself",
feat
),
_ => {}
};
// `PackageId`s in the lock file don't include the `source` part
- // for workspace members, so we reconstruct proper ids.
+ // for workspace members, so we reconstruct proper IDs.
let live_pkgs = {
let mut live_pkgs = HashMap::new();
let mut all_pkgs = HashSet::new();
}
fn build_path_deps(ws: &Workspace<'_>) -> HashMap<String, SourceId> {
- // If a crate is *not* a path source, then we're probably in a situation
+ // If a crate is **not** a path source, then we're probably in a situation
// such as `cargo install` with a lock file from a remote dependency. In
// that case we don't need to fixup any path dependencies (as they're not
// actually path dependencies any more), so we ignore them.
-//! Resolution of the entire dependency graph for a crate
+//! Resolution of the entire dependency graph for a crate.
//!
//! This module implements the core logic in taking the world of crates and
//! constraints and creating a resolved graph with locked versions for all
//!
//! 1. Each crate can have any number of dependencies. Each dependency can
//! declare a version range that it is compatible with.
-//! 2. Crates can be activated with multiple version (e.g. show up in the
+//! 2. Crates can be activated with multiple version (e.g., show up in the
//! dependency graph twice) so long as each pairwise instance have
//! semver-incompatible versions.
//!
//! that has the same links attribute as something else
//! activated.
//! * Always try to activate the highest version crate first. The default
-//! dependency in Cargo (e.g. when you write `foo = "0.1.2"`) is
+//! dependency in Cargo (e.g., when you write `foo = "0.1.2"`) is
//! semver-compatible, so selecting the highest version possible will allow us
//! to hopefully satisfy as many dependencies at once.
//!
//!
//! Note that this is a relatively performance-critical portion of Cargo. The
//! data that we're processing is proportional to the size of the dependency
-//! graph, which can often be quite large (e.g. take a look at Servo). To make
+//! graph, which can often be quite large (e.g., take a look at Servo). To make
//! matters worse the DFS algorithm we're implemented is inherently quite
//! inefficient. When we add the requirement of backtracking on top it means
//! that we're implementing something that probably shouldn't be allocating all
/// for the same query every time). Typically this is an instance of a
/// `PackageRegistry`.
///
-/// * `try_to_use` - this is a list of package ids which were previously found
+/// * `try_to_use` - this is a list of package IDs which were previously found
/// in the lock file. We heuristically prefer the ids listed in `try_to_use`
/// when sorting candidates to activate, but otherwise this isn't used
/// anywhere else.
// backtracking to find a place to restart. It is also the list of
// things to explain in the error message if we fail to resolve.
//
- // This is a map of package id to a reason why that packaged caused a
+ // This is a map of package ID to a reason why that packaged caused a
// conflict for us.
let mut conflicting_activations = BTreeMap::new();
// When backtracking we don't fully update `conflicting_activations`
// especially for the cases that we didn't make a backtrack frame in the
- // first place. This `backtracked` var stores whether we are continuing
+ // first place. This `backtracked` var stores whether we are continuing
// from a restored backtrack frame so that we can skip caching
// `conflicting_activations` in `past_conflicting_activations`
let mut backtracked = false;
/// we've reached the end of iteration.
///
/// If we've reached the end of the iterator here then `Err` will be
- /// returned. The error will contain a map of package id to conflict reason,
- /// where each package id caused a candidate to be filtered out from the
+ /// returned. The error will contain a map of package ID to conflict reason,
+ /// where each package ID caused a candidate to be filtered out from the
/// original list for the reason listed.
fn next(
&mut self,
}
}
-/// Checks that packages are unique when written to lockfile.
+/// Checks that packages are unique when written to lock file.
///
-/// When writing package id's to lockfile, we apply lossy encoding. In
+/// When writing package ID's to lock file, we apply lossy encoding. In
/// particular, we don't store paths of path dependencies. That means that
-/// *different* packages may collide in the lockfile, hence this check.
+/// *different* packages may collide in the lock file, hence this check.
fn check_duplicate_pkgs_in_lockfile(resolve: &Resolve) -> CargoResult<()> {
let mut unique_pkg_ids = HashMap::new();
for pkg_id in resolve.iter() {
use super::encode::Metadata;
-/// Represents a fully resolved package dependency graph. Each node in the graph
+/// Represents a fully-resolved package dependency graph. Each node in the graph
/// is a package and edges represent dependencies between packages.
///
/// Each instance of `Resolve` also understands the full set of features used
#[derive(PartialEq)]
pub struct Resolve {
/// A graph, whose vertices are packages and edges are dependency specifications
- /// from Cargo.toml. We need a `Vec` here because the same package
+ /// from `Cargo.toml`. We need a `Vec` here because the same package
/// might be present in both `[dependencies]` and `[build-dependencies]`.
graph: Graph<PackageId, Vec<Dependency>>,
replacements: HashMap<PackageId, PackageId>,
pub fn merge_from(&mut self, previous: &Resolve) -> CargoResult<()> {
// Given a previous instance of resolve, it should be forbidden to ever
- // have a checksums which *differ*. If the same package id has differing
+ // have a checksums which *differ*. If the same package ID has differing
// checksums, then something has gone wrong such as:
//
// * Something got seriously corrupted
this could be indicative of a few possible errors:
* the lock file is corrupt
- * a replacement source in use (e.g. a mirror) returned a different checksum
+ * a replacement source in use (e.g., a mirror) returned a different checksum
* the source itself may be corrupt in one way or another
unable to verify that `{0}` is the same as when the lockfile was generated
use crate::util::errors::CargoResult;
-/// The requested verbosity of output
+/// The requested verbosity of output.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
Verbose,
}
impl Shell {
- /// Create a new shell (color choice and verbosity), defaulting to 'auto' color and verbose
+ /// Creates a new shell (color choice and verbosity), defaulting to 'auto' color and verbose
/// output.
pub fn new() -> Shell {
Shell {
}
}
- /// Create a shell from a plain writable object, with no color, and max verbosity.
+ /// Creates a shell from a plain writable object, with no color, and max verbosity.
pub fn from_write(out: Box<dyn Write>) -> Shell {
Shell {
err: ShellOut::Write(out),
}
}
- /// Print a message, where the status will have `color` color, and can be justified. The
+ /// Prints a message, where the status will have `color` color, and can be justified. The
/// messages follows without color.
fn print(
&mut self,
}
}
- /// Set whether or not the next print should clear the current line.
+ /// Sets whether the next print should clear the current line.
pub fn set_needs_clear(&mut self, needs_clear: bool) {
self.needs_clear = needs_clear;
}
- /// True if the `needs_clear` flag is not set.
+ /// Returns `true` if the `needs_clear` flag is unset.
pub fn is_cleared(&self) -> bool {
!self.needs_clear
}
- /// Returns the width of the terminal in spaces, if any
+ /// Returns the width of the terminal in spaces, if any.
pub fn err_width(&self) -> Option<usize> {
match self.err {
ShellOut::Stream { tty: true, .. } => imp::stderr_width(),
}
}
- /// Returns whether stderr is a tty
+ /// Returns `true` if stderr is a tty.
pub fn is_err_tty(&self) -> bool {
match self.err {
ShellOut::Stream { tty, .. } => tty,
}
}
- /// Get a reference to the underlying writer
+ /// Gets a reference to the underlying writer.
pub fn err(&mut self) -> &mut dyn Write {
if self.needs_clear {
self.err_erase_line();
self.print(&status, Some(&message), color, true)
}
- /// Run the callback only if we are in verbose mode
+ /// Runs the callback only if we are in verbose mode.
pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
where
F: FnMut(&mut Shell) -> CargoResult<()>,
}
}
- /// Run the callback if we are not in verbose mode.
+ /// Runs the callback if we are not in verbose mode.
pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
where
F: FnMut(&mut Shell) -> CargoResult<()>,
}
}
- /// Print a red 'error' message
+ /// Prints a red 'error' message.
pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
self.print(&"error:", Some(&message), Red, false)
}
- /// Print an amber 'warning' message
+ /// Prints an amber 'warning' message.
pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
match self.verbosity {
Verbosity::Quiet => Ok(()),
}
}
- /// Update the verbosity of the shell
+ /// Updates the verbosity of the shell.
pub fn set_verbosity(&mut self, verbosity: Verbosity) {
self.verbosity = verbosity;
}
- /// Get the verbosity of the shell
+ /// Gets the verbosity of the shell.
pub fn verbosity(&self) -> Verbosity {
self.verbosity
}
- /// Update the color choice (always, never, or auto) from a string.
+ /// Updates the color choice (always, never, or auto) from a string..
pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
if let ShellOut::Stream {
ref mut stream,
Ok(())
}
- /// Get the current color choice
+ /// Gets the current color choice.
///
- /// If we are not using a color stream, this will always return Never, even if the color choice
- /// has been set to something else.
+ /// If we are not using a color stream, this will always return `Never`, even if the color
+ /// choice has been set to something else.
pub fn color_choice(&self) -> ColorChoice {
match self.err {
ShellOut::Stream { color_choice, .. } => color_choice,
}
impl ShellOut {
- /// Print out a message with a status. The status comes first and is bold + the given color.
- /// The status can be justified, in which case the max width that will right align is 12 chars.
+ /// Prints out a message with a status. The status comes first, and is bold plus the given
+ /// color. The status can be justified, in which case the max width that will right align is
+ /// 12 chars.
fn print(
&mut self,
status: &dyn fmt::Display,
Ok(())
}
- /// Get this object as a `io::Write`.
+ /// Gets this object as a `io::Write`.
fn as_write(&mut self) -> &mut dyn Write {
match *self {
ShellOut::Stream { ref mut stream, .. } => stream,
}
impl ColorChoice {
- /// Convert our color choice to termcolor's version
+ /// Converts our color choice to termcolor's version.
fn to_termcolor_color_choice(self) -> termcolor::ColorChoice {
match self {
ColorChoice::Always => termcolor::ColorChoice::Always,
pub use self::source_id::{GitReference, SourceId};
-/// A Source finds and downloads remote packages based on names and
-/// versions.
+/// Something that finds and downloads remote packages based on names and versions.
pub trait Source {
- /// Returns the `SourceId` corresponding to this source
+ /// Returns the `SourceId` corresponding to this source.
fn source_id(&self) -> SourceId;
- /// Returns the replaced `SourceId` corresponding to this source
+ /// Returns the replaced `SourceId` corresponding to this source.
fn replaced_source_id(&self) -> SourceId {
self.source_id()
}
/// the `precise` field in the source id listed.
fn requires_precise(&self) -> bool;
- /// Attempt to find the packages that match a dependency request.
+ /// Attempts to find the packages that match a dependency request.
fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()>;
- /// Attempt to find the packages that are close to a dependency request.
+ /// Attempts to find the packages that are close to a dependency request.
/// Each source gets to define what `close` means for it.
- /// path/git sources may return all dependencies that are at that uri.
- /// where as an Index source may return dependencies that have the same canonicalization.
+ /// Path/Git sources may return all dependencies that are at that URI,
+ /// whereas an `Index` source may return dependencies that have the same canonicalization.
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()>;
fn query_vec(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
Ok(ret)
}
- /// The update method performs any network operations required to
- /// get the entire list of all names, versions and dependencies of
- /// packages managed by the Source.
+ /// Performs any network operations required to get the entire list of all names,
+ /// versions and dependencies of packages managed by the `Source`.
fn update(&mut self) -> CargoResult<()>;
- /// The download method fetches the full package for each name and
- /// version specified.
+ /// Fetches the full package for each name and version specified.
fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
fn download_now(self: Box<Self>, package: PackageId, config: &Config) -> CargoResult<Package>
/// resolver error messages currently.
fn describe(&self) -> String;
- /// Returns whether a source is being replaced by another here
+ /// Returns whether a source is being replaced by another here.
fn is_replaced(&self) -> bool {
false
}
}
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
- /// Forwards to `Source::source_id`
+ /// Forwards to `Source::source_id`.
fn source_id(&self) -> SourceId {
(**self).source_id()
}
- /// Forwards to `Source::replaced_source_id`
+ /// Forwards to `Source::replaced_source_id`.
fn replaced_source_id(&self) -> SourceId {
(**self).replaced_source_id()
}
- /// Forwards to `Source::supports_checksums`
+ /// Forwards to `Source::supports_checksums`.
fn supports_checksums(&self) -> bool {
(**self).supports_checksums()
}
- /// Forwards to `Source::requires_precise`
+ /// Forwards to `Source::requires_precise`.
fn requires_precise(&self) -> bool {
(**self).requires_precise()
}
- /// Forwards to `Source::query`
+ /// Forwards to `Source::query`.
fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
(**self).query(dep, f)
}
- /// Forwards to `Source::query`
+ /// Forwards to `Source::query`.
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
(**self).fuzzy_query(dep, f)
}
- /// Forwards to `Source::update`
+ /// Forwards to `Source::update`.
fn update(&mut self) -> CargoResult<()> {
(**self).update()
}
- /// Forwards to `Source::download`
+ /// Forwards to `Source::download`.
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
(**self).download(id)
}
(**self).finish_download(id, data)
}
- /// Forwards to `Source::fingerprint`
+ /// Forwards to `Source::fingerprint`.
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
(**self).fingerprint(pkg)
}
- /// Forwards to `Source::verify`
+ /// Forwards to `Source::verify`.
fn verify(&self, pkg: PackageId) -> CargoResult<()> {
(**self).verify(pkg)
}
}
}
-/// A `HashMap` of `SourceId` -> `Box<Source>`
+/// A `HashMap` of `SourceId` -> `Box<Source>`.
#[derive(Default)]
pub struct SourceMap<'src> {
map: HashMap<SourceId, Box<dyn Source + 'src>>,
}
-// impl debug on source requires specialization, if even desirable at all
+// `impl Debug` on source requires specialization, if even desirable at all.
impl<'src> fmt::Debug for SourceMap<'src> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SourceMap ")?;
}
impl<'src> SourceMap<'src> {
- /// Create an empty map
+ /// Creates an empty map.
pub fn new() -> SourceMap<'src> {
SourceMap {
map: HashMap::new(),
}
}
- /// Like `HashMap::contains_key`
+ /// Like `HashMap::contains_key`.
pub fn contains(&self, id: SourceId) -> bool {
self.map.contains_key(&id)
}
- /// Like `HashMap::get`
+ /// Like `HashMap::get`.
pub fn get(&self, id: SourceId) -> Option<&(dyn Source + 'src)> {
let source = self.map.get(&id);
})
}
- /// Like `HashMap::get_mut`
+ /// Like `HashMap::get_mut`.
pub fn get_mut(&mut self, id: SourceId) -> Option<&mut (dyn Source + 'src)> {
self.map.get_mut(&id).map(|s| {
let s: &mut (dyn Source + 'src) = &mut **s;
})
}
- /// Like `HashMap::get`, but first calculates the `SourceId` from a
- /// `PackageId`
+ /// Like `HashMap::get`, but first calculates the `SourceId` from a `PackageId`.
pub fn get_by_package_id(&self, pkg_id: PackageId) -> Option<&(dyn Source + 'src)> {
self.get(pkg_id.source_id())
}
- /// Like `HashMap::insert`, but derives the SourceId key from the Source
+ /// Like `HashMap::insert`, but derives the `SourceId` key from the `Source`.
pub fn insert(&mut self, source: Box<dyn Source + 'src>) {
let id = source.source_id();
self.map.insert(id, source);
}
- /// Like `HashMap::is_empty`
+ /// Like `HashMap::is_empty`.
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
- /// Like `HashMap::len`
+ /// Like `HashMap::len`.
pub fn len(&self) -> usize {
self.map.len()
}
- /// Like `HashMap::values`
+ /// Like `HashMap::values`.
pub fn sources<'a>(&'a self) -> impl Iterator<Item = &'a Box<dyn Source + 'src>> {
self.map.values()
}
- /// Like `HashMap::iter_mut`
+ /// Like `HashMap::iter_mut`.
pub fn sources_mut<'a>(
&'a mut self,
) -> impl Iterator<Item = (&'a SourceId, &'a mut (dyn Source + 'src))> {
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
struct SourceIdInner {
- /// The source URL
+ /// The source URL.
url: Url,
- /// `git::canonicalize_url(url)` for the url field
+ /// The result of `git::canonicalize_url()` on `url` field.
canonical_url: Url,
- /// The source kind
+ /// The source kind.
kind: Kind,
- // e.g. the exact git revision of the specified branch for a Git Source
+ /// For example, the exact Git revision of the specified branch for a Git Source.
precise: Option<String>,
/// Name of the registry source for alternative registries
- /// WARNING: This is not always set for alt-registries when the name is
+ /// WARNING: this is not always set for alt-registries when the name is
/// not known.
name: Option<String>,
}
-/// The possible kinds of code source. Along with SourceIdInner this fully defines the
-/// source
+/// The possible kinds of code source. Along with `SourceIdInner`, this fully defines the
+/// source.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Kind {
- /// Kind::Git(<git reference>) represents a git repository
+ /// A git repository.
Git(GitReference),
- /// represents a local path
+ /// A local path..
Path,
- /// represents a remote registry
+ /// A remote registry.
Registry,
- /// represents a local filesystem-based registry
+ /// A local filesystem-based registry.
LocalRegistry,
- /// represents a directory-based registry
+ /// A directory-based registry.
Directory,
}
-/// Information to find a specific commit in a git repository
+/// Information to find a specific commit in a Git repository.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum GitReference {
- /// from a tag
+ /// From a tag.
Tag(String),
- /// from the HEAD of a branch
+ /// From the HEAD of a branch.
Branch(String),
- /// from a specific revision
+ /// From a specific revision.
Rev(String),
}
impl SourceId {
- /// Create a SourceId object from the kind and url.
+ /// Creates a `SourceId` object from the kind and URL.
///
/// The canonical url will be calculated, but the precise field will not
fn new(kind: Kind, url: Url) -> CargoResult<SourceId> {
let mut reference = GitReference::Branch("master".to_string());
for (k, v) in url.query_pairs() {
match &k[..] {
- // map older 'ref' to branch
+ // Map older 'ref' to branch.
"branch" | "ref" => reference = GitReference::Branch(v.into_owned()),
"rev" => reference = GitReference::Rev(v.into_owned()),
}
}
- /// A view of the `SourceId` that can be `Display`ed as a URL
+ /// A view of the `SourceId` that can be `Display`ed as a URL.
pub fn to_url(&self) -> SourceIdToUrl<'_> {
SourceIdToUrl {
inner: &*self.inner,
}
}
- /// Create a SourceId from a filesystem path.
+ /// Creates a `SourceId` from a filesystem path.
///
- /// Pass absolute path
+ /// `path`: an absolute path.
pub fn for_path(path: &Path) -> CargoResult<SourceId> {
let url = path.to_url()?;
SourceId::new(Kind::Path, url)
}
- /// Crate a SourceId from a git reference
+ /// Creates a `SourceId` from a Git reference.
pub fn for_git(url: &Url, reference: GitReference) -> CargoResult<SourceId> {
SourceId::new(Kind::Git(reference), url.clone())
}
- /// Create a SourceId from a registry url
+ /// Creates a SourceId from a registry URL.
pub fn for_registry(url: &Url) -> CargoResult<SourceId> {
SourceId::new(Kind::Registry, url.clone())
}
- /// Create a SourceId from a local registry path
+ /// Creates a SourceId from a local registry path.
pub fn for_local_registry(path: &Path) -> CargoResult<SourceId> {
let url = path.to_url()?;
SourceId::new(Kind::LocalRegistry, url)
}
- /// Create a SourceId from a directory path
+ /// Creates a `SourceId` from a directory path.
pub fn for_directory(path: &Path) -> CargoResult<SourceId> {
let url = path.to_url()?;
SourceId::new(Kind::Directory, url)
}))
}
- /// Get this source URL
+ /// Gets this source URL.
pub fn url(&self) -> &Url {
&self.inner.url
}
}
}
- /// Is this source from a filesystem path
+ /// Returns `true` if this source is from a filesystem path.
pub fn is_path(self) -> bool {
self.inner.kind == Kind::Path
}
- /// Is this source from a registry (either local or not)
+ /// Returns `true` if this source is from a registry (either local or not).
pub fn is_registry(self) -> bool {
match self.inner.kind {
Kind::Registry | Kind::LocalRegistry => true,
}
}
- /// Is this source from a git repository
+ /// Returns `true` if this source from a Git repository.
pub fn is_git(self) -> bool {
match self.inner.kind {
Kind::Git(_) => true,
}
}
- /// Get the value of the precise field
+ /// Gets the value of the precise field.
pub fn precise(self) -> Option<&'static str> {
self.inner.precise.as_ref().map(|s| &s[..])
}
- /// Get the git reference if this is a git source, otherwise None.
+ /// Gets the Git reference if this is a git source, otherwise `None`.
pub fn git_reference(self) -> Option<&'static GitReference> {
match self.inner.kind {
Kind::Git(ref s) => Some(s),
}
}
- /// Create a new SourceId from this source with the given `precise`
+ /// Creates a new `SourceId` from this source with the given `precise`.
pub fn with_precise(self, v: Option<String>) -> SourceId {
SourceId::wrap(SourceIdInner {
precise: v,
})
}
- /// Whether the remote registry is the standard https://crates.io
+ /// Returns `true` if the remote registry is the standard <https://crates.io>.
pub fn is_default_registry(self) -> bool {
match self.inner.kind {
Kind::Registry => {}
self.inner.url.to_string() == CRATES_IO_INDEX
}
- /// Hash `self`
+ /// Hashes `self`.
///
/// For paths, remove the workspace prefix so the same source will give the
/// same hash in different locations.
// or only the root package for non-virtual workspaces.
default_members: Vec<PathBuf>,
- // True, if this is a temporary workspace created for the purposes of
- // cargo install or cargo package.
+ // `true` if this is a temporary workspace created for the purposes of the
+ // `cargo install` or `cargo package` commands.
is_ephemeral: bool,
- // True if this workspace should enforce optional dependencies even when
+ // `true` if this workspace should enforce optional dependencies even when
// not needed; false if this workspace should only enforce dependencies
// needed by the current configuration (such as in cargo install). In some
// cases `false` also results in the non-enforcement of dev-dependencies.
}
impl WorkspaceRootConfig {
- /// Create a new Intermediate Workspace Root configuration.
+ /// Creates a new Intermediate Workspace Root configuration.
pub fn new(
root_dir: &Path,
members: &Option<Vec<String>>,
/// Checks the path against the `excluded` list.
///
- /// This method does NOT consider the `members` list.
+ /// This method does **not** consider the `members` list.
fn is_excluded(&self, manifest_path: &Path) -> bool {
let excluded = self
.exclude
#![cfg_attr(test, deny(warnings))]
#![warn(rust_2018_idioms)]
-// while we're getting used to 2018
-// Clippy isn't enforced by CI, and know that @alexcrichton isn't a fan :)
+// While we're getting used to 2018:
+// Clippy isn't enforced by CI (@alexcrichton isn't a fan).
#![allow(clippy::boxed_local)] // bug rust-lang-nursery/rust-clippy#1123
#![allow(clippy::cyclomatic_complexity)] // large project
#![allow(clippy::derive_hash_xor_eq)] // there's an intentional incoherence
#![allow(clippy::redundant_closure_call)] // closures over try catch blocks
#![allow(clippy::too_many_arguments)] // large project
#![allow(clippy::type_complexity)] // there's an exceptionally complex type
-#![allow(clippy::wrong_self_convention)] // perhaps Rc should be special cased in Clippy?
+#![allow(clippy::wrong_self_convention)] // perhaps `Rc` should be special-cased in Clippy?
use std::fmt;
}
pub struct CfgInfo {
- // Information about the git repository we may have been built from.
+ // Information about the Git repository we may have been built from.
pub commit_info: Option<CommitInfo>,
// The release channel we were built for.
pub release_channel: String,
pub patch: u8,
pub pre_release: Option<String>,
// Information that's only available when we were built with
- // configure/make, rather than cargo itself.
+ // configure/make, rather than Cargo itself.
pub cfg_info: Option<CfgInfo>,
}
exit_code,
unknown,
} = err;
- // exit_code == 0 is non-fatal error, e.g. docopt version info
+ // `exit_code` of 0 means non-fatal error (e.g., docopt version info).
let fatal = exit_code != 0;
let hide = unknown && shell.verbosity() != Verbose;
let verbose = shell.verbosity();
if verbose == Verbose {
- // The first error has already been printed to the shell
- // Print all remaining errors
+ // The first error has already been printed to the shell.
+ // Print all remaining errors.
for err in cargo_err.iter_causes() {
print(&err.to_string(), shell);
}
} else {
- // The first error has already been printed to the shell
- // Print remaining errors until one marked as Internal appears
+ // The first error has already been printed to the shell.
+ // Print remaining errors until one marked as `Internal` appears.
for err in cargo_err.iter_causes() {
if err.downcast_ref::<Internal>().is_some() {
return false;
-//!
-//! Cargo compile currently does the following steps:
+//! Cargo `compile` currently does the following steps.
//!
//! All configurations are already injected as environment variables via the
-//! main cargo command
+//! main cargo command.
//!
-//! 1. Read the manifest
+//! 1. Read the manifest.
//! 2. Shell out to `cargo-resolve` with a list of dependencies and sources as
-//! stdin
+//! stdin.
//!
-//! a. Shell out to `--do update` and `--do list` for each source
-//! b. Resolve dependencies and return a list of name/version/source
+//! a. Shell out to `--do update` and `--do list` for each source.
+//! b. Resolve dependencies and return a list of name/version/source.
//!
-//! 3. Shell out to `--do download` for each source
+//! 3. Shell out to `--do download` for each source.
//! 4. Shell out to `--do get` for each source, and build up the list of paths
-//! to pass to rustc -L
+//! to pass to `rustc -L`.
//! 5. Call `cargo-rustc` with the results of the resolver zipped together with
-//! the results of the `get`
+//! the results of the `get`.
//!
-//! a. Topologically sort the dependencies
+//! a. Topologically sort the dependencies.
//! b. Compile each dependency in order, passing in the -L's pointing at each
-//! previously compiled dependency
-//!
+//! previously compiled dependency.
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
if units.len() != 1 {
failure::bail!(
"extra arguments to `{}` can only be passed to one \
- target, consider filtering\nthe package by passing \
- e.g. `--lib` or `--bin NAME` to specify a single target",
+ target, consider filtering\nthe package by passing, \
+ e.g., `--lib` or `--bin NAME` to specify a single target",
extra_args_name
);
}
/// A proposed target.
///
-/// Proposed targets are later filtered into actual Units based on whether or
+/// Proposed targets are later filtered into actual `Unit`s based on whether or
/// not the target requires its features to be present.
#[derive(Debug)]
struct Proposal<'a> {
}
/// Generates all the base targets for the packages the user has requested to
-/// compile. Dependencies for these targets are computed later in
-/// `unit_dependencies`.
+/// compile. Dependencies for these targets are computed later in `unit_dependencies`.
fn generate_targets<'a>(
ws: &Workspace<'_>,
profiles: &Profiles,
resolve: &Resolve,
build_config: &BuildConfig,
) -> CargoResult<Vec<Unit<'a>>> {
- // Helper for creating a Unit struct.
+ // Helper for creating a `Unit` struct.
let new_unit = |pkg: &'a Package, target: &'a Target, target_mode: CompileMode| {
let unit_for = if build_config.mode.is_any_test() {
- // NOTE: The UnitFor here is subtle. If you have a profile
+ // NOTE: the `UnitFor` here is subtle. If you have a profile
// with `panic` set, the `panic` flag is cleared for
- // tests/benchmarks and their dependencies. If this
+ // tests/benchmarks and their dependencies. If this
// was `normal`, then the lib would get compiled three
// times (once with panic, once without, and once with
- // --test).
+ // `--test`).
//
- // This would cause a problem for Doc tests, which would fail
+ // This would cause a problem for doc tests, which would fail
// because `rustdoc` would attempt to link with both libraries
// at the same time. Also, it's probably not important (or
// even desirable?) for rustdoc to link with a lib with
// `panic` set.
//
// As a consequence, Examples and Binaries get compiled
- // without `panic` set. This probably isn't a bad deal.
+ // without `panic` set. This probably isn't a bad deal.
//
// Forcing the lib to be compiled three times during `cargo
// test` is probably also not desirable.
UnitFor::new_test()
} else if target.for_host() {
- // proc-macro/plugin should not have `panic` set.
+ // Proc macro / plugin should not have `panic` set.
UnitFor::new_compiler()
} else {
UnitFor::new_normal()
TargetKind::Bench => CompileMode::Bench,
_ => CompileMode::Build,
},
- // CompileMode::Bench is only used to inform filter_default_targets
+ // `CompileMode::Bench` is only used to inform `filter_default_targets`
// which command is being used (`cargo bench`). Afterwards, tests
// and benches are treated identically. Switching the mode allows
- // de-duplication of units that are essentially identical. For
+ // de-duplication of units that are essentially identical. For
// example, `cargo build --all-targets --release` creates the units
// (lib profile:bench, mode:test) and (lib profile:bench, mode:bench)
- // and since these are the same, we want them to be de-duped in
+ // and since these are the same, we want them to be de-duplicated in
// `unit_dependencies`.
CompileMode::Bench => CompileMode::Test,
_ => target_mode,
};
- // Plugins or proc-macro should be built for the host.
+ // Plugins or proc macros should be built for the host.
let kind = if target.for_host() {
Kind::Host
} else {
proposals.extend(libs);
}
- // If --tests was specified, add all targets that would be
+ // If `--tests` was specified, add all targets that would be
// generated by `cargo test`.
let test_filter = match tests {
FilterRule::All => Target::tested,
CompileMode::Check { .. } => CompileMode::Check { test: true },
_ => build_config.mode,
};
- // If --benches was specified, add all targets that would be
+ // If `--benches` was specified, add all targets that would be
// generated by `cargo bench`.
let bench_filter = match benches {
FilterRule::All => Target::benched,
.collect();
failure::bail!(
"target `{}` in package `{}` requires the features: {}\n\
- Consider enabling them by passing e.g. `--features=\"{}\"`",
+ Consider enabling them by passing, e.g., `--features=\"{}\"`",
target.name(),
pkg.name(),
quoted_required_features.join(", "),
Ok(proposals)
}
-/// Find the targets for a specifically named target.
+/// Finds the targets for a specifically named target.
fn find_named_targets<'a>(
packages: &[&'a Package],
target_name: &str,
(dep.name().as_str(), dep.source_id())
}
- // Removes all package ids in `b` from `a`. Note that this is somewhat
- // more complicated because the equality for source ids does not take
- // precise versions into account (e.g. git shas), but we want to take
+ // Removes all package IDs in `b` from `a`. Note that this is somewhat
+ // more complicated because the equality for source IDs does not take
+ // precise versions into account (e.g., git shas), but we want to take
// that into account here.
fn vec_subtract(a: &[PackageId], b: &[PackageId]) -> Vec<PackageId> {
a.iter()
.filter(|a| {
- // If this package id is not found in `b`, then it's definitely
- // in the subtracted set
+ // If this package ID is not found in `b`, then it's definitely
+ // in the subtracted set.
let i = match b.binary_search(a) {
Ok(i) => i,
Err(..) => return true,
//
// Note that we only check this for non-registry sources,
// however, as registries contain enough version information in
- // the package id to disambiguate
+ // the package ID to disambiguate.
if a.source_id().is_registry() {
return false;
}
.collect()
}
- // Map (package name, package source) to (removed versions, added versions).
+ // Map `(package name, package source)` to `(removed versions, added versions)`.
let mut changes = BTreeMap::new();
let empty = (Vec::new(), Vec::new());
for dep in previous_resolve.iter() {
fs::create_dir_all(&dst)?;
// Copy all binaries to a temporary directory under `dst` first, catching
- // some failure modes (e.g. out of space) before touching the existing
+ // some failure modes (e.g., out of space) before touching the existing
// binaries. This directory will get cleaned up via RAII.
let staging_dir = TempFileBuilder::new()
.prefix("cargo-install")
}
}
-/// write the ignore file to the given directory. If the ignore file for the
+/// Writes the ignore file to the given directory. If the ignore file for the
/// given vcs system already exists, its content is read and duplicate ignore
/// file entries are filtered out.
fn write_ignore_file(
Ok(ignore)
}
-/// initialize the correct vcs system based on the provided config
+/// Initializes the correct VCS system based on the provided config.
fn init_vcs(path: &Path, vcs: VersionControl, config: &Config) -> CargoResult<()> {
match vcs {
VersionControl::Git => {
let name = opts.name;
let cfg = global_config(config)?;
- // using the push method with two arguments ensures that the entries for
- // both ignore and hgignore are in sync.
+ // Using the push method with two arguments ensures that the entries for
+ // both `ignore` and `hgignore` are in sync.
let mut ignore = IgnoreList::new();
ignore.push("/target", "^target/");
ignore.push("**/*.rs.bk", "glob:*.rs.bk\n");
write_ignore_file(path, &ignore, vcs)?;
let (author_name, email) = discover_author()?;
- // Hoo boy, sure glad we've got exhaustiveness checking behind us.
let author = match (cfg.name, cfg.email, author_name, email) {
(Some(name), Some(email), _, _)
| (Some(name), None, _, Some(email))
let mut cargotoml_path_specifier = String::new();
- // Calculate what [lib] and [[bin]]s do we need to append to Cargo.toml
+ // Calculate what `[lib]` and `[[bin]]`s we need to append to `Cargo.toml`.
for i in &opts.source_files {
if i.bin {
}
}
- // Create Cargo.toml file with necessary [lib] and [[bin]] sections, if needed
+ // Create `Cargo.toml` file with necessary `[lib]` and `[[bin]]` sections, if needed.
paths::write(
&path.join("Cargo.toml"),
.as_bytes(),
)?;
- // Create all specified source files
- // (with respective parent directories)
- // if they are don't exist
+ // Create all specified source files (with respective parent directories) if they don't exist.
for i in &opts.source_files {
let path_of_source_file = path.join(i.relative_path.clone());
}
/// Newtype wrapper to provide a custom `Serialize` implementation.
-/// The one from lockfile does not fit because it uses a non-standard
+/// The one from lock file does not fit because it uses a non-standard
/// format for `PackageId`s
#[derive(Serialize)]
struct MetadataResolve {
pkg.manifest().publish_lockfile() && pkg.targets().iter().any(|t| t.is_example() || t.is_bin())
}
-// check that the package has some piece of metadata that a human can
+// Checks that the package has some piece of metadata that a human can
// use to tell what the package is about.
fn check_metadata(pkg: &Package, config: &Config) -> CargoResult<()> {
let md = pkg.manifest().metadata();
if !missing.is_empty() {
let mut things = missing[..missing.len() - 1].join(", ");
- // things will be empty if and only if length == 1 (i.e. the only case
+ // `things` will be empty if and only if its length is 1 (i.e., the only case
// to have no `or`).
if !things.is_empty() {
things.push_str(" or ");
config.shell().warn(&format!(
"manifest has no {things}.\n\
- See http://doc.crates.io/manifest.html#package-metadata for more info.",
+ See <http://doc.crates.io/manifest.html#package-metadata> for more info.",
things = things
))?
}
Ok(())
}
-// check that the package dependencies are safe to deploy.
+// Checks that the package dependencies are safe to deploy.
fn verify_dependencies(pkg: &Package) -> CargoResult<()> {
for dep in pkg.dependencies() {
if dep.source_id().is_path() && !dep.specified_req() {
Ok(())
}
-// Check if the package source is in a *git* DVCS repository. If *git*, and
-// the source is *dirty* (e.g. has uncommited changes) and not `allow_dirty`
+// Checks if the package source is in a *git* DVCS repository. If *git*, and
+// the source is *dirty* (e.g., has uncommited changes) and not `allow_dirty`
// then `bail!` with an informative message. Otherwise return the sha1 hash of
// the current *HEAD* commit, or `None` if *dirty*.
fn check_repo_state(
})?;
}
- // No VCS with a checked in Cargo.toml found. so we don't know if the
- // directory is dirty or not, so we have to assume that it's clean.
+ // No VCS with a checked in `Cargo.toml` found, so we don't know if the
+ // directory is dirty or not, thus we have to assume that it's clean.
return Ok(None);
fn git(
}
}
-// Check for and `bail!` if a source file matches ROOT/VCS_INFO_FILE, since
-// this is now a cargo reserved file name, and we don't want to allow
-// forgery.
+// Checks for and `bail!` if a source file matches `ROOT/VCS_INFO_FILE`, since
+// this is now a Cargo reserved file name, and we don't want to allow forgery.
fn check_vcs_file_collision(pkg: &Package, src_files: &[PathBuf]) -> CargoResult<()> {
let root = pkg.root();
let vcs_info_path = Path::new(VCS_INFO_FILE);
dst: &File,
filename: &str,
) -> CargoResult<()> {
- // Prepare the encoder and its header
+ // Prepare the encoder and its header.
let filename = Path::new(filename);
let encoder = GzBuilder::new()
.filename(util::path2bytes(filename)?)
.write(dst, Compression::best());
- // Put all package files into a compressed archive
+ // Put all package files into a compressed archive.
let mut ar = Builder::new(encoder);
let pkg = ws.current()?;
let config = ws.config();
relative
);
- // The tar::Builder type by default will build GNU archives, but
+ // The `tar::Builder` type by default will build GNU archives, but
// unfortunately we force it here to use UStar archives instead. The
// UStar format has more limitations on the length of path name that it
// can encode, so it's not quite as nice to use.
//
// For an instance of this in the wild, use the tar-rs 0.3.3 library to
// unpack the selectors 0.4.0 crate on crates.io. Either that or take a
- // look at rust-lang/cargo#2326
+ // look at rust-lang/cargo#2326.
let mut header = Header::new_ustar();
header
.set_path(&path)
&exec,
)?;
- // Check that build.rs didn't modify any files in the src directory.
+ // Check that `build.rs` didn't modify any files in the `src` directory.
let ws_fingerprint = src.last_modified_file(ws.current()?)?;
if pkg_fingerprint != ws_fingerprint {
let (_, path) = ws_fingerprint;
) -> CargoResult<Option<ProcessError>> {
let config = ws.config();
- // We compute the `bins` here *just for diagnosis*. The actual set of
+ // We compute the `bins` here *just for diagnosis*. The actual set of
// packages to be run is determined by the `ops::compile` call below.
let packages = options.spec.get_packages(ws)?;
let bins: Vec<_> = packages
if !options.filter.is_specific() {
failure::bail!("a bin target must be available for `cargo run`")
} else {
- // this will be verified in cargo_compile
+ // This will be verified in `cargo_compile`.
}
}
}
let (test, mut errors) = run_unit_tests(options, test_args, &compilation)?;
- // If we have an error and want to fail fast, return
+ // If we have an error and want to fail fast, then return.
if !errors.is_empty() && !options.no_fail_fast {
return Ok(Some(CargoTestError::new(test, errors)));
}
Ok(compilation)
}
-/// Run the unit and integration tests of a package.
+/// Runs the unit and integration tests of a package.
fn run_unit_tests(
options: &TestOptions<'_>,
test_args: &[String],
let mut errors = Vec::new();
let config = options.compile_opts.config;
- // We don't build/rust doctests if target != host
+ // We don't build/run doc tests if `target` does not equal `host`.
if compilation.host != compilation.target {
return Ok((Test::Doc, errors));
}
pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions<'_>) -> CargoResult<()> {
check_version_control(opts)?;
- // Spin up our lock server which our subprocesses will use to synchronize
- // fixes.
+ // Spin up our lock server, which our subprocesses will use to synchronize fixes.
let lock_server = LockServer::new()?;
opts.compile_opts
.build_config
// *stop* compiling then we want to back them out and continue to print
// warnings to the user.
//
- // If we didn't actually make any changes then we can immediately exec the
+ // If we didn't actually make any changes then we can immediately execute the
// new rustc, and otherwise we capture the output to hide it in the scenario
// that we have to back it all out.
if !fixes.files.is_empty() {
return Ok(true);
}
- // Otherwise if our rustc just failed then that means that we broke the
+ // Otherwise, if our rustc just failed, then that means that we broke the
// user's code with our changes. Back out everything and fall through
// below to recompile again.
if !output.status.success() {
) -> Result<FixedCrate, Error> {
args.verify_not_preparing_for_enabled_edition()?;
- // First up we want to make sure that each crate is only checked by one
+ // First up, we want to make sure that each crate is only checked by one
// process at a time. If two invocations concurrently check a crate then
// it's likely to corrupt it.
//
- // Currently we do this by assigning the name on our lock to the manifest
+ // We currently do this by assigning the name on our lock to the manifest
// directory.
let dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is missing?");
let _lock = LockServerClient::lock(&lock_addr.parse()?, dir)?;
- // Next up this is a bit suspicious, but we *iteratively* execute rustc and
+ // Next up, this is a bit suspicious, but we *iteratively* execute rustc and
// collect suggestions to feed to rustfix. Once we hit our limit of times to
// execute rustc or we appear to be reaching a fixed point we stop running
// rustc.
//
// where there are two fixes to happen here: `crate::foo::<crate::Bar>()`.
// The spans for these two suggestions are overlapping and its difficult in
- // the compiler to *not* have overlapping spans here. As a result, a naive
+ // the compiler to **not** have overlapping spans here. As a result, a naive
// implementation would feed the two compiler suggestions for the above fix
// into `rustfix`, but one would be rejected because it overlaps with the
// other.
// failed to apply, assuming that they can be fixed the next time we run
// rustc.
//
- // Naturally we want a few protections in place here though to avoid looping
+ // Naturally, we want a few protections in place here though to avoid looping
// forever or otherwise losing data. To that end we have a few termination
// conditions:
//
last_fix_counts.clear();
for (path, file) in fixes.files.iter_mut() {
last_fix_counts.insert(path.clone(), file.fixes_applied);
- file.errors_applying_fixes.clear(); // we'll generate new errors below
+ // We'll generate new errors below.
+ file.errors_applying_fixes.clear();
}
rustfix_and_fix(&mut fixes, rustc, filename, args)?;
let mut progress_yet_to_be_made = false;
Ok(fixes)
}
-/// Execute `rustc` to apply one round of suggestions to the crate in question.
+/// Executes `rustc` to apply one round of suggestions to the crate in question.
///
/// This will fill in the `fixes` map with original code, suggestions applied,
/// and any errors encountered while fixing files.
filename: &Path,
args: &FixArgs,
) -> Result<(), Error> {
- // If not empty, filter by these lints
- //
- // TODO: Implement a way to specify this
+ // If not empty, filter by these lints.
+ // TODO: implement a way to specify this.
let only = HashSet::new();
let mut cmd = Command::new(rustc);
.map(|_| rustfix::Filter::Everything)
.unwrap_or(rustfix::Filter::MachineApplicableOnly);
- // Sift through the output of the compiler to look for JSON messages
+ // Sift through the output of the compiler to look for JSON messages.
// indicating fixes that we can apply.
- let stderr = str::from_utf8(&output.stderr).context("failed to parse rustc stderr as utf-8")?;
+ let stderr = str::from_utf8(&output.stderr).context("failed to parse rustc stderr as UTF-8")?;
let suggestions = stderr
.lines()
.filter(|x| !x.is_empty())
.inspect(|y| trace!("line: {}", y))
- // Parse each line of stderr ignoring errors as they may not all be json
+ // Parse each line of stderr, ignoring errors, as they may not all be JSON.
.filter_map(|line| serde_json::from_str::<Diagnostic>(line).ok())
- // From each diagnostic try to extract suggestions from rustc
+ // From each diagnostic, try to extract suggestions from rustc.
.filter_map(|diag| rustfix::collect_suggestions(&diag, &only, fix_mode));
// Collect suggestions by file so we can apply them one at a time later.
}
}
- /// Verify that we're not both preparing for an enabled edition and enabling
+ /// Verifies that we're not both preparing for an enabled edition and enabling
/// the edition.
///
/// This indicates that `cargo fix --prepare-for` is being executed out of
}
pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &Resolve) -> CargoResult<()> {
- // Load the original lockfile if it exists.
+ // Load the original lock file if it exists.
let ws_root = Filesystem::new(ws.root().to_path_buf());
let orig = ws_root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file");
let orig = orig.and_then(|mut f| {
out.push_str(&meta.to_string());
}
- // If the lockfile contents haven't changed so don't rewrite it. This is
+ // If the lock file contents haven't changed so don't rewrite it. This is
// helpful on read-only filesystems.
if let Ok(orig) = orig {
if are_equal_lockfiles(orig, &out, ws) {
orig = orig.replace("\r\n", "\n");
}
- // If we want to try and avoid updating the lockfile, parse both and
+ // If we want to try and avoid updating the lock file, parse both and
// compare them; since this is somewhat expensive, don't do it in the
- // common case where we can update lockfiles.
+ // common case where we can update lock files.
if !ws.config().lock_update_allowed() {
let res: CargoResult<bool> = (|| {
let old: resolver::EncodableResolve = toml::from_str(&orig)?;
Ok((Registry::new_handle(api_host, token, handle), sid))
}
-/// Create a new HTTP handle with appropriate global configuration for cargo.
+/// Creates a new HTTP handle with appropriate global configuration for cargo.
pub fn http_handle(config: &Config) -> CargoResult<Easy> {
let (mut handle, timeout) = http_handle_and_timeout(config)?;
timeout.configure(&mut handle)?;
}
}
-/// Find an explicit HTTP proxy if one is available.
+/// Finds an explicit HTTP proxy if one is available.
///
/// Favor cargo's `http.proxy`, then git's `http.proxy`. Proxies specified
/// via environment variables are picked up by libcurl.
what is locked in the Cargo.lock file, run `cargo update` to use the new
version. This may also occur with an optional dependency that is not enabled.";
-/// Resolve all dependencies for the workspace using the previous
-/// lockfile as a guide if present.
+/// Resolves all dependencies for the workspace using the previous
+/// lock file as a guide if present.
///
/// This function will also write the result of resolution as a new
-/// lockfile.
+/// lock file.
pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolve)> {
let mut registry = PackageRegistry::new(ws.config())?;
let resolve = resolve_with_registry(ws, &mut registry, true)?;
// Second, resolve with precisely what we're doing. Filter out
// transitive dependencies if necessary, specify features, handle
// overrides, etc.
- let _p = profile::start("resolving w/ overrides...");
+ let _p = profile::start("resolving with overrides...");
add_overrides(&mut registry, ws)?;
Ok(resolve)
}
-/// Resolve all dependencies for a package using an optional previous instance
+/// Resolves all dependencies for a package using an optional previous instance.
/// of resolve to guide the resolution process.
///
/// This also takes an optional hash set, `to_avoid`, which is a list of package
-/// ids that should be avoided when consulting the previous instance of resolve
+/// IDs that should be avoided when consulting the previous instance of resolve
/// (often used in pairings with updates).
///
-/// The previous resolve normally comes from a lockfile. This function does not
-/// read or write lockfiles from the filesystem.
+/// The previous resolve normally comes from a lock file. This function does not
+/// read or write lock files from the filesystem.
pub fn resolve_with_previous<'cfg>(
registry: &mut PackageRegistry<'cfg>,
ws: &Workspace<'cfg>,
warn: bool,
) -> CargoResult<Resolve> {
// Here we place an artificial limitation that all non-registry sources
- // cannot be locked at more than one revision. This means that if a git
+ // cannot be locked at more than one revision. This means that if a Git
// repository provides more than one package, they must all be updated in
// step when any of them are updated.
//
- // TODO: This seems like a hokey reason to single out the registry as being
- // different
+ // TODO: this seems like a hokey reason to single out the registry as being
+ // different.
let mut to_avoid_sources: HashSet<SourceId> = HashSet::new();
if let Some(to_avoid) = to_avoid {
to_avoid_sources.extend(
/// want to make sure that we properly re-resolve (conservatively) instead of
/// providing an opaque error.
///
-/// The logic here is somewhat subtle but there should be more comments below to
-/// help out, and otherwise feel free to ask on IRC if there's questions!
+/// The logic here is somewhat subtle, but there should be more comments below to
+/// clarify things.
///
/// Note that this function, at the time of this writing, is basically the
-/// entire fix for #4127
+/// entire fix for issue #4127.
fn register_previous_locks(
ws: &Workspace<'_>,
registry: &mut PackageRegistry<'_>,
};
// Ok so we've been passed in a `keep` function which basically says "if I
- // return true then this package wasn't listed for an update on the command
- // line". AKA if we run `cargo update -p foo` then `keep(bar)` will return
- // `true`, whereas `keep(foo)` will return `true` (roughly).
+ // return `true` then this package wasn't listed for an update on the command
+ // line". That is, if we run `cargo update -p foo` then `keep(bar)` will return
+ // `true`, whereas `keep(foo)` will return `false` (roughly speaking).
//
// This isn't actually quite what we want, however. Instead we want to
// further refine this `keep` function with *all transitive dependencies* of
- // the packages we're not keeping. For example consider a case like this:
+ // the packages we're not keeping. For example, consider a case like this:
//
- // * There's a crate `log`
- // * There's a crate `serde` which depends on `log`
+ // * There's a crate `log`.
+ // * There's a crate `serde` which depends on `log`.
//
// Let's say we then run `cargo update -p serde`. This may *also* want to
// update the `log` dependency as our newer version of `serde` may have a
// newer version of `serde` requires a new version of `log` it'll get pulled
// in (as we didn't accidentally lock it to an old version).
//
- // Additionally here we process all path dependencies listed in the previous
+ // Additionally, here we process all path dependencies listed in the previous
// resolve. They can not only have their dependencies change but also
// the versions of the package change as well. If this ends up happening
- // then we want to make sure we don't lock a package id node that doesn't
+ // then we want to make sure we don't lock a package ID node that doesn't
// actually exist. Note that we don't do transitive visits of all the
// package's dependencies here as that'll be covered below to poison those
// if they changed.
}
}
- // Ok but the above loop isn't the entire story! Updates to the dependency
+ // Ok, but the above loop isn't the entire story! Updates to the dependency
// graph can come from two locations, the `cargo update` command or
// manifests themselves. For example a manifest on the filesystem may
// have been updated to have an updated version requirement on `serde`. In
for dep in member.dependencies() {
// If this dependency didn't match anything special then we may want
// to poison the source as it may have been added. If this path
- // dependencies is *not* a workspace member, however, and it's an
+ // dependencies is **not** a workspace member, however, and it's an
// optional/non-transitive dependency then it won't be necessarily
// be in our lock file. If this shows up then we avoid poisoning
// this source as otherwise we'd repeatedly update the registry.
//
// TODO: this breaks adding an optional dependency in a
- // non-workspace member and then simultaneously editing the
- // dependency on that crate to enable the feature. For now
- // this bug is better than the always updating registry
- // though...
+ // non-workspace member and then simultaneously editing the
+ // dependency on that crate to enable the feature. For now,
+ // this bug is better than the always-updating registry though.
if !ws
.members()
.any(|pkg| pkg.package_id() == member.package_id())
continue;
}
- // If this is a path dependency then try to push it onto our
- // worklist
+ // If this is a path dependency, then try to push it onto our
+ // worklist.
if let Some(pkg) = path_pkg(dep.source_id()) {
path_deps.push(pkg);
continue;
}
// If we match *anything* in the dependency graph then we consider
- // ourselves A-OK and assume that we'll resolve to that.
+ // ourselves all ok, and assume that we'll resolve to that.
if resolve.iter().any(|id| dep.matches_ignoring_source(id)) {
continue;
}
- // Ok if nothing matches, then we poison the source of this
+ // Ok if nothing matches, then we poison the source of these
// dependencies and the previous lock file.
debug!(
"poisoning {} because {} looks like it changed {}",
}
// Alright now that we've got our new, fresh, shiny, and refined `keep`
- // function let's put it to action. Take a look at the previous lockfile,
+ // function let's put it to action. Take a look at the previous lock file,
// filter everything by this callback, and then shove everything else into
// the registry as a locked dependency.
let keep = |id: &PackageId| keep(id) && !avoid_locking.contains(id);
registry.register_lock(node, deps);
}
- /// recursively add `node` and all its transitive dependencies to `set`
+ /// Recursively add `node` and all its transitive dependencies to `set`.
fn add_deps(resolve: &Resolve, node: PackageId, set: &mut HashSet<PackageId>) {
if !set.insert(node) {
return;
Ok(format!("{}-{}", ident, short_hash(&url)))
}
-// Some hacks and heuristics for making equivalent URLs hash the same
+// Some hacks and heuristics for making equivalent URLs hash the same.
pub fn canonicalize_url(url: &Url) -> CargoResult<Url> {
let mut url = url.clone();
- // cannot-be-a-base-urls are not supported
- // eg. github.com:rust-lang-nursery/rustfmt.git
+ // cannot-be-a-base-urls (e.g., `github.com:rust-lang-nursery/rustfmt.git`)
+ // are not supported.
if url.cannot_be_a_base() {
failure::bail!(
"invalid url `{}`: cannot-be-a-base-URLs are not supported",
)
}
- // Strip a trailing slash
+ // Strip a trailing slash.
if url.path().ends_with('/') {
url.path_segments_mut().unwrap().pop_if_empty();
}
- // HACKHACK: For GitHub URL's specifically just lowercase
- // everything. GitHub treats both the same, but they hash
+ // HACK: for GitHub URLs specifically, just lower-case
+ // everything. GitHub treats both the same, but they hash
// differently, and we're gonna be hashing them. This wants a more
// general solution, and also we're almost certainly not using the
- // same case conversion rules that GitHub does. (#84)
+ // same case conversion rules that GitHub does. (See issue #84.)
if url.host_str() == Some("github.com") {
url.set_scheme("https").unwrap();
let path = url.path().to_lowercase();
url.set_path(&path);
}
- // Repos generally can be accessed with or w/o '.git'
+ // Repos can generally be accessed with or without `.git` extension.
let needs_chopping = url.path().ends_with(".git");
if needs_chopping {
let last = {
let src = self
.path_source
.as_mut()
- .expect("BUG: update() must be called before query()");
+ .expect("BUG: `update()` must be called before `query()`");
src.query(dep, f)
}
let src = self
.path_source
.as_mut()
- .expect("BUG: update() must be called before query()");
+ .expect("BUG: `update()` must be called before `query()`");
src.fuzzy_query(dep, f)
}
(self.remote.db_at(&db_path)?, actual_rev.unwrap())
};
- // Don’t use the full hash,
- // to contribute less to reaching the path length limit on Windows:
- // https://github.com/servo/servo/pull/14397
+ // Don’t use the full hash, in order to contribute less to reaching the path length limit
+ // on Windows. See <https://github.com/servo/servo/pull/14397>.
let short_id = db.to_short_id(&actual_rev).unwrap();
let checkout_path = lock
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
trace!(
- "getting packages for package id `{}` from `{:?}`",
+ "getting packages for package ID `{}` from `{:?}`",
id,
self.remote
);
self.path_source
.as_mut()
- .expect("BUG: update() must be called before get()")
+ .expect("BUG: `update()` must be called before `get()`")
.download(id)
}
}
fn describe(&self) -> String {
- format!("git repository {}", self.source_id)
+ format!("Git repository {}", self.source_id)
}
fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {}
}
fn reset(&self, config: &Config) -> CargoResult<()> {
- // If we're interrupted while performing this reset (e.g. we die because
+ // If we're interrupted while performing this reset (e.g., we die because
// of a signal) Cargo needs to be sure to try to check out this repo
// again on the next go-round.
//
///
/// * If a username/password is allowed, then we fallback to git2-rs's
/// implementation of the credential helper. This is what is configured
-/// with `credential.helper` in git, and is the interface for the OSX
+/// with `credential.helper` in git, and is the interface for the macOS
/// keychain, for example.
///
/// * After the above two have failed, we just kinda grapple attempting to
// ssh-agent currently.
//
// If we get called with this then the only way that should be possible
- // is if a username is specified in the URL itself (e.g. `username` is
+ // is if a username is specified in the URL itself (e.g., `username` is
// Some), hence the unwrap() here. We try custom usernames down below.
if allowed.contains(git2::CredentialType::SSH_KEY) && !tried_sshkey {
// If ssh-agent authentication fails, libgit2 will keep
// for another mode of authentication.
//
// Essentially, if `attempts == 2` then in theory the only error was
- // that this username failed to authenticate (e.g. no other network
+ // that this username failed to authenticate (e.g., no other network
// errors happened). Otherwise something else is funny so we bail
// out.
if attempts != 2 {
}
impl<'cfg> PathSource<'cfg> {
- /// Invoked with an absolute path to a directory that contains a Cargo.toml.
+ /// Invoked with an absolute path to a directory that contains a `Cargo.toml`.
///
/// This source will only return the package at precisely the `path`
/// specified, and it will be an error if there's not a package at `path`.
/// stages are:
///
/// 1) Only warn users about the future change iff their matching rules are
- /// affected. (CURRENT STAGE)
+ /// affected. (CURRENT STAGE)
///
/// 2) Switch to the new strategy and update documents. Still keep warning
/// affected users.
///
/// 3) Drop the old strategy and no more warnings.
///
- /// See <https://github.com/rust-lang/cargo/issues/4268> for more info.
+ /// See rust-lang/cargo#4268 for more info.
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathBuf>> {
let root = pkg.root();
let no_include_option = pkg.manifest().include().is_empty();
- // glob-like matching rules
+ // Glob-like matching rules.
let glob_parse = |p: &String| {
let pattern: &str = if p.starts_with('/') {
.any(|pattern| pattern.matches_path(relative_path))
}
- // include and exclude options are mutually exclusive.
+ // "Include" and "exclude" options are mutually exclusive.
if no_include_option {
!glob_match(&glob_exclude, relative_path)
} else {
}
};
- // ignore-like matching rules
+ // Ignore-like matching rules.
let mut exclude_builder = GitignoreBuilder::new(root);
for rule in pkg.manifest().exclude() {
let ignore_include = include_builder.build()?;
let ignore_should_package = |relative_path: &Path| -> CargoResult<bool> {
- // include and exclude options are mutually exclusive.
+ // "Include" and "exclude" options are mutually exclusive.
if no_include_option {
match ignore_exclude
.matched_path_or_any_parents(relative_path, /* is_dir */ false)
}
};
- // matching to paths
+ // Matching to paths.
let mut filter = |path: &Path| -> CargoResult<bool> {
let relative_path = path.strip_prefix(root)?;
self.config.shell().warn(format!(
"Pattern matching for Cargo's include/exclude fields is changing and \
file `{}` WILL be excluded in a future Cargo version.\n\
- See https://github.com/rust-lang/cargo/issues/4268 for more info",
+ See <https://github.com/rust-lang/cargo/issues/4268> for more \
+ information.",
relative_path.display()
))?;
} else {
self.config.shell().warn(format!(
"Pattern matching for Cargo's include/exclude fields is changing and \
file `{}` WILL NOT be included in a future Cargo version.\n\
- See https://github.com/rust-lang/cargo/issues/4268 for more info",
+ See <https://github.com/rust-lang/cargo/issues/4268> for more \
+ information.",
relative_path.display()
))?;
}
self.config.shell().warn(format!(
"Pattern matching for Cargo's include/exclude fields is changing and \
file `{}` WILL NOT be excluded in a future Cargo version.\n\
- See https://github.com/rust-lang/cargo/issues/4268 for more info",
+ See <https://github.com/rust-lang/cargo/issues/4268> for more \
+ information.",
relative_path.display()
))?;
} else {
self.config.shell().warn(format!(
"Pattern matching for Cargo's include/exclude fields is changing and \
file `{}` WILL be included in a future Cargo version.\n\
- See https://github.com/rust-lang/cargo/issues/4268 for more info",
+ See <https://github.com/rust-lang/cargo/issues/4268> for more \
+ information.",
relative_path.display()
))?;
}
}
- // Update to ignore_should_package for Stage 2
+ // Update to `ignore_should_package` for Stage 2.
Ok(glob_should_package)
};
- // attempt git-prepopulate only if no `include` (rust-lang/cargo#4135)
+ // Attempt Git-prepopulate only if no `include` (see rust-lang/cargo#4135).
if no_include_option {
if let Some(result) = self.discover_git_and_list_files(pkg, root, &mut filter) {
return result;
self.list_files_walk(pkg, &mut filter)
}
- // Returns Some(_) if found sibling Cargo.toml and .git folder;
- // otherwise caller should fall back on full file list.
+ // Returns `Some(_)` if found sibling `Cargo.toml` and `.git` directory;
+ // otherwise, caller should fall back on full file list.
fn discover_git_and_list_files(
&self,
pkg: &Package,
root: &Path,
filter: &mut dyn FnMut(&Path) -> CargoResult<bool>,
) -> Option<CargoResult<Vec<PathBuf>>> {
- // If this package is in a git repository, then we really do want to
- // query the git repository as it takes into account items such as
- // .gitignore. We're not quite sure where the git repository is,
+ // If this package is in a Git repository, then we really do want to
+ // query the Git repository as it takes into account items such as
+ // `.gitignore`. We're not quite sure where the Git repository is,
// however, so we do a bit of a probe.
//
// We walk this package's path upwards and look for a sibling
- // Cargo.toml and .git folder. If we find one then we assume that we're
- // part of that repository.
+ // `Cargo.toml` and `.git` directory. If we find one then we assume that
+ // we're part of that repository.
let mut cur = root;
loop {
if cur.join("Cargo.toml").is_file() {
- // If we find a git repository next to this Cargo.toml, we still
+ // If we find a Git repository next to this `Cargo.toml`, we still
// check to see if we are indeed part of the index. If not, then
- // this is likely an unrelated git repo, so keep going.
+ // this is likely an unrelated Git repo, so keep going.
if let Ok(repo) = git2::Repository::open(cur) {
let index = match repo.index() {
Ok(index) => index,
}
}
}
- // don't cross submodule boundaries
+ // Don't cross submodule boundaries.
if cur.join(".git").is_dir() {
break;
}
let mut ret = Vec::<PathBuf>::new();
- // We use information from the git repository to guide us in traversing
+ // We use information from the Git repository to guide us in traversing
// its tree. The primary purpose of this is to take advantage of the
- // .gitignore and auto-ignore files that don't matter.
+ // `.gitignore` and auto-ignore files that don't matter.
//
// Here we're also careful to look at both tracked and untracked files as
// the untracked files are often part of a build and may become relevant
}
match file_path.file_name().and_then(|s| s.to_str()) {
- // Filter out Cargo.lock and target always, we don't want to
+ // Filter out `Cargo.lock` and `target` always; we don't want to
// package a lock file no one will ever read and we also avoid
- // build artifacts
+ // build artifacts.
Some("Cargo.lock") | Some("target") => continue,
// Keep track of all sub-packages found and also strip out all
// matches we've found so far. Note, though, that if we find
- // our own `Cargo.toml` we keep going.
+ // our own `Cargo.toml`, we keep going.
Some("Cargo.toml") => {
let path = file_path.parent().unwrap();
if path != pkg_path {
}
return Ok(());
}
- // Don't recurse into any sub-packages that we have
+ // Don't recurse into any sub-packages that we have.
if !is_root && fs::metadata(&path.join("Cargo.toml")).is_ok() {
return Ok(());
}
// For package integration tests, we need to sort the paths in a deterministic order to
// be able to match stdout warnings in the same order.
//
- // TODO: Drop collect and sort after transition period and dropping warning tests.
- // See <https://github.com/rust-lang/cargo/issues/4268>
- // and <https://github.com/rust-lang/cargo/pull/4270>
+ // TODO: drop `collect` and sort after transition period and dropping warning tests.
+ // See rust-lang/cargo#4268 and rust-lang/cargo#4270.
let mut entries: Vec<PathBuf> = fs::read_dir(path)?.map(|e| e.unwrap().path()).collect();
entries.sort_unstable_by(|a, b| a.as_os_str().cmp(b.as_os_str()));
for path in entries {
let name = path.file_name().and_then(|s| s.to_str());
- // Skip dotfile directories
+ // Skip dotfile directories.
if name.map(|s| s.starts_with('.')) == Some(true) {
continue;
}
if is_root {
- // Skip cargo artifacts
+ // Skip Cargo artifacts.
match name {
Some("target") | Some("Cargo.lock") => continue,
_ => {}
let mut max = FileTime::zero();
let mut max_path = PathBuf::new();
for file in self.list_files(pkg)? {
- // An fs::stat error here is either because path is a
+ // An `fs::stat` error here is either because path is a
// broken symlink, a permissions error, or a race
- // condition where this path was rm'ed - either way,
- // we can ignore the error and treat the path's mtime
- // as 0.
+ // condition where this path was `rm`-ed -- either way,
+ // we can ignore the error and treat the path's `mtime`
+ // as `0`.
let mtime = paths::mtime(&file).unwrap_or_else(|_| FileTime::zero());
if mtime > max {
max = mtime;
use crate::sources::registry::{RegistryPackage, INDEX_LOCK};
use crate::util::{internal, CargoResult, Config, Filesystem, ToSemver};
-/// Crates.io treats hyphen and underscores as interchangeable
-/// but, the index and old cargo do not. So the index must store uncanonicalized version
-/// of the name so old cargos can find it.
-/// This loop tries all possible combinations of switching
-/// hyphen and underscores to find the uncanonicalized one.
-/// As all stored inputs have the correct spelling, we start with the spelling as provided.
+/// Crates.io treats hyphen and underscores as interchangeable, but the index and old Cargo do not.
+/// Therefore, the index must store uncanonicalized version of the name so old Cargo's can find it.
+/// This loop tries all possible combinations of switching hyphen and underscores to find the
+/// uncanonicalized one. As all stored inputs have the correct spelling, we start with the spelling
+/// as-provided.
struct UncanonicalizedIter<'s> {
input: &'s str,
num_hyphen_underscore: u32,
source_id: SourceId,
path: Filesystem,
cache: HashMap<&'static str, Vec<(Summary, bool)>>,
- hashes: HashMap<&'static str, HashMap<Version, String>>, // (name, vers) => cksum
+ // `(name, vers)` -> `checksum`
+ hashes: HashMap<&'static str, HashMap<Version, String>>,
config: &'cfg Config,
locked: bool,
}
}
}
- /// Return the hash listed for a specified PackageId.
+ /// Returns the hash listed for a specified `PackageId`.
pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> CargoResult<String> {
let name = pkg.name().as_str();
let version = pkg.version();
.map(|s| s.clone())
}
- /// Parse the on-disk metadata for the package provided
+ /// Parses the on-disk metadata for the package provided.
///
- /// Returns a list of pairs of (summary, yanked) for the package name
- /// specified.
+ /// Returns a list of pairs of `(summary, yanked)` for the package name specified.
pub fn summaries(
&mut self,
name: &'static str,
.flat_map(|c| c.to_lowercase())
.collect::<String>();
- // see module comment for why this is structured the way it is
+ // See module comment for why this is structured the way it is.
let raw_path = match fs_name.len() {
1 => format!("1/{}", fs_name),
2 => format!("2/{}", fs_name),
Ok(ret)
}
- /// Parse a line from the registry's index file into a Summary for a
- /// package.
+ /// Parses a line from the registry's index file into a `Summary` for a package.
///
/// The returned boolean is whether or not the summary has been yanked.
fn parse_registry_package(&mut self, line: &str) -> CargoResult<(Summary, bool)> {
impl<'cfg> Source for RegistrySource<'cfg> {
fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
- // If this is a precise dependency, then it came from a lockfile and in
+ // If this is a precise dependency, then it came from a lock file and in
// theory the registry is known to contain this version. If, however, we
// come back with no summaries, then our registry may need to be
// updated, so we fall back to performing a lazy update.
) -> Arg<'static, 'static> {
// Note that all `.multiple(true)` arguments in Cargo should specify
// `.number_of_values(1)` as well, so that `--foo val1 val2` is
- // **not** parsed as `foo` with values ["val1", "val2"].
+ // *not* parsed as `foo` with values ["val1", "val2"].
// `number_of_values` should become the default in clap 3.
opt(name, help)
.value_name(value_name)
validate_package_name(registry, "registry name", "")?;
if registry == CRATES_IO_REGISTRY {
- // If "crates.io" is specified then we just need to return None
+ // If "crates.io" is specified, then we just need to return `None`,
// as that will cause cargo to use crates.io. This is required
// for the case where a default alternative registry is used
// but the user wants to switch back to crates.io for a single
}
fn index(&self, config: &Config) -> CargoResult<Option<String>> {
- // TODO: Deprecated
- // remove once it has been decided --host can be removed
- // We may instead want to repurpose the host flag, as
- // mentioned in this issue
- // https://github.com/rust-lang/cargo/issues/4208
+ // TODO: deprecated. Remove once it has been decided `--host` can be removed
+ // We may instead want to repurpose the host flag, as mentioned in issue
+ // rust-lang/cargo#4208.
let msg = "The flag '--host' is no longer valid.
Previous versions of Cargo accepted this flag, but it is being
use lazycell::LazyCell;
use serde::Deserialize;
use serde::{de, de::IntoDeserializer};
+use url::Url;
use crate::core::profiles::ConfigProfiles;
use crate::core::shell::Verbosity;
use crate::util::Rustc;
use crate::util::ToUrl;
use crate::util::{paths, validate_package_name};
-use url::Url;
-
use self::ConfigValue as CV;
/// Configuration information for cargo. This is not specific to a build, it is information
Ok(Config::new(shell, cwd, homedir))
}
- /// The user's cargo home directory (OS-dependent)
+ /// Gets the user's Cargo home directory (OS-dependent).
pub fn home(&self) -> &Filesystem {
&self.home_path
}
- /// The cargo git directory (`<cargo_home>/git`)
+ /// Gets the Cargo Git directory (`<cargo_home>/git`).
pub fn git_path(&self) -> Filesystem {
self.home_path.join("git")
}
- /// The cargo registry index directory (`<cargo_home>/registry/index`)
+ /// Gets the Cargo registry index directory (`<cargo_home>/registry/index`).
pub fn registry_index_path(&self) -> Filesystem {
self.home_path.join("registry").join("index")
}
- /// The cargo registry cache directory (`<cargo_home>/registry/path`)
+ /// Gets the Cargo registry cache directory (`<cargo_home>/registry/path`).
pub fn registry_cache_path(&self) -> Filesystem {
self.home_path.join("registry").join("cache")
}
- /// The cargo registry source directory (`<cargo_home>/registry/src`)
+ /// Gets the Cargo registry source directory (`<cargo_home>/registry/src`).
pub fn registry_source_path(&self) -> Filesystem {
self.home_path.join("registry").join("src")
}
- /// The default cargo registry (`alternative-registry`)
+ /// Gets the default Cargo registry.
pub fn default_registry(&self) -> CargoResult<Option<String>> {
Ok(match self.get_string("registry.default")? {
Some(registry) => Some(registry.val),
})
}
- /// Get a reference to the shell, for e.g. writing error messages
+ /// Gets a reference to the shell, e.g., for writing error messages.
pub fn shell(&self) -> RefMut<'_, Shell> {
self.shell.borrow_mut()
}
- /// Get the path to the `rustdoc` executable
+ /// Gets the path to the `rustdoc` executable.
pub fn rustdoc(&self) -> CargoResult<&Path> {
self.rustdoc
.try_borrow_with(|| self.get_tool("rustdoc"))
.map(AsRef::as_ref)
}
- /// Get the path to the `rustc` executable
+ /// Gets the path to the `rustc` executable.
pub fn rustc(&self, ws: Option<&Workspace<'_>>) -> CargoResult<Rustc> {
let cache_location = ws.map(|ws| {
ws.target_dir()
)
}
- /// Get the path to the `cargo` executable
+ /// Gets the path to the `cargo` executable.
pub fn cargo_exe(&self) -> CargoResult<&Path> {
self.cargo_exe
.try_borrow_with(|| {
fn from_current_exe() -> CargoResult<PathBuf> {
- // Try fetching the path to `cargo` using env::current_exe().
+ // Try fetching the path to `cargo` using `env::current_exe()`.
// The method varies per operating system and might fail; in particular,
- // it depends on /proc being mounted on Linux, and some environments
+ // it depends on `/proc` being mounted on Linux, and some environments
// (like containers or chroots) may not have that available.
let exe = env::current_exe()?.canonicalize()?;
Ok(exe)
}
fn from_argv() -> CargoResult<PathBuf> {
- // Grab argv[0] and attempt to resolve it to an absolute path.
- // If argv[0] has one component, it must have come from a PATH lookup,
- // so probe PATH in that case.
+ // Grab `argv[0]` and attempt to resolve it to an absolute path.
+ // If `argv[0]` has one component, it must have come from a `PATH` lookup,
+ // so probe `PATH` in that case.
// Otherwise, it has multiple components and is either:
- // - a relative path (e.g. `./cargo`, `target/debug/cargo`), or
- // - an absolute path (e.g. `/usr/local/bin/cargo`).
- // In either case, Path::canonicalize will return the full absolute path
- // to the target if it exists
+ // - a relative path (e.g., `./cargo`, `target/debug/cargo`), or
+ // - an absolute path (e.g., `/usr/local/bin/cargo`).
+ // In either case, `Path::canonicalize` will return the full absolute path
+ // to the target if it exists.
let argv0 = env::args_os()
.map(PathBuf::from)
.next()
self.values.try_borrow_with(|| self.load_values())
}
- // Note: This is used by RLS, not Cargo.
+ // Note: this is used by RLS, not Cargo.
pub fn set_values(&self, values: HashMap<String, ConfigValue>) -> CargoResult<()> {
if self.values.borrow().is_some() {
failure::bail!("config values already found")
if is_path {
definition.root(self).join(value)
} else {
- // A pathless name
+ // A pathless name.
PathBuf::from(value)
}
}
Ok(None)
}
- // NOTE: This does *not* support environment variables. Use `get` instead
+ // NOTE: this does **not** support environment variables. Use `get` instead
// if you want that.
pub fn get_list(&self, key: &str) -> CargoResult<OptValue<Vec<(String, PathBuf)>>> {
match self.get_cv(key)? {
}
}
- // Recommend use `get` if you want a specific type, such as an unsigned value.
- // Example: config.get::<Option<u32>>("some.key")?
+ // Recommended to use `get` if you want a specific type, such as an unsigned value.
+ // Example: `config.get::<Option<u32>>("some.key")?`.
pub fn get_i64(&self, key: &str) -> CargoResult<OptValue<i64>> {
self.get_integer(&ConfigKey::from_str(key))
.map_err(|e| e.into())
let verbosity = match (verbose, cfg_verbose, quiet) {
(Some(true), _, None) | (None, Some(true), None) => Verbosity::Verbose,
- // command line takes precedence over configuration, so ignore the
- // configuration.
+ // Command line takes precedence over configuration, so ignore the
+ // configuration..
(None, _, Some(true)) => Verbosity::Quiet,
// Can't pass both at the same time on the command line regardless
!self.frozen && !self.locked
}
- /// Loads configuration from the filesystem
+ /// Loads configuration from the filesystem.
pub fn load_values(&self) -> CargoResult<HashMap<String, ConfigValue>> {
self.load_values_from(&self.cwd)
}
)
}
- /// Loads credentials config from the credentials file into the ConfigValue object, if present.
+ /// Loads credentials config from the credentials file into the `ConfigValue` object, if
+ /// present.
fn load_credentials(&self, cfg: &mut ConfigValue) -> CargoResult<()> {
let home_path = self.home_path.clone().into_path_unlocked();
let credentials = home_path.join("credentials");
)
})?;
- // backwards compatibility for old .cargo/credentials layout
+ // Backwards compatibility for old `.cargo/credentials` layout.
{
let value = match value {
CV::Table(ref mut value, _) => value,
}
}
- // we want value to override cfg, so swap these
+ // We want value to override `cfg`, so swap these.
mem::swap(cfg, &mut value);
cfg.merge(value)?;
Ok(())
}
- /// Look for a path for `tool` in an environment variable or config path, but return `None`
+ /// Looks for a path for `tool` in an environment variable or config path, and returns `None`
/// if it's not present.
fn maybe_get_tool(&self, tool: &str) -> CargoResult<Option<PathBuf>> {
let var = tool
Ok(None)
}
- /// Look for a path for `tool` in an environment variable or config path, defaulting to `tool`
+ /// Looks for a path for `tool` in an environment variable or config path, defaulting to `tool`
/// as a path.
fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
self.maybe_get_tool(tool)
self.creation_time
}
- // Retrieve a config variable.
+ // Retrieves a config variable.
+ //
+ // This supports most serde `Deserialize` types. Examples:
//
- // This supports most serde `Deserialize` types. Examples:
// let v: Option<u32> = config.get("some.nested.key")?;
// let v: Option<MyStruct> = config.get("some.key")?;
// let v: Option<HashMap<String, MyStruct>> = config.get("foo")?;
}
impl std::error::Error for ConfigError {
- // This can be removed once 1.27 is stable.
- fn description(&self) -> &str {
- "An error has occurred."
- }
}
-// Future Note: Currently we cannot override Fail::cause (due to
+// Future note: currently, we cannot override `Fail::cause` (due to
// specialization) so we have no way to return the underlying causes. In the
// future, once this limitation is lifted, this should instead implement
// `cause` and avoid doing the cause formatting here.
if self.config.has_key(&self.key) {
visitor.visit_some(self)
} else {
- // Treat missing values as None.
+ // Treat missing values as `None`.
visitor.visit_none()
}
}
) -> Result<ConfigMapAccess<'config>, ConfigError> {
let mut set = HashSet::new();
if let Some(mut v) = config.get_table(&key.to_config())? {
- // v: Value<HashMap<String, CV>>
+ // `v: Value<HashMap<String, CV>>`
for (key, _value) in v.val.drain() {
set.insert(ConfigKeyPart::CasePart(key));
}
}
if config.cli_unstable().advanced_env {
- // CARGO_PROFILE_DEV_OVERRIDES_
+ // `CARGO_PROFILE_DEV_OVERRIDES_`
let env_pattern = format!("{}_", key.to_env());
for env_key in config.env.keys() {
if env_key.starts_with(&env_pattern) {
- // CARGO_PROFILE_DEV_OVERRIDES_bar_OPT_LEVEL = 3
+ // `CARGO_PROFILE_DEV_OVERRIDES_bar_OPT_LEVEL = 3`
let rest = &env_key[env_pattern.len()..];
- // rest = bar_OPT_LEVEL
+ // `rest = bar_OPT_LEVEL`
let part = rest.splitn(2, '_').next().unwrap();
- // part = "bar"
+ // `part = "bar"`
set.insert(ConfigKeyPart::CasePart(part.to_string()));
}
}
.as_array()
.expect("env var was not array");
for value in values {
- // TODO: support other types
+ // TODO: support other types.
let s = value.as_str().ok_or_else(|| {
ConfigError::new(
format!("expected string, found {}", value.type_str()),
T: de::DeserializeSeed<'de>,
{
match self.list_iter.next() {
- // TODO: Add def to err?
+ // TODO: add `def` to error?
Some((value, _def)) => seed.deserialize(value.into_deserializer()).map(Some),
None => Ok(None),
}
}
/// Use with the `get` API to fetch a string that will be converted to a
-/// `PathBuf`. Relative paths are converted to absolute paths based on the
+/// `PathBuf`. Relative paths are converted to absolute paths based on the
/// location of the config file.
#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
pub struct ConfigRelativePath(PathBuf);
let mut toml = cargo_toml::parse(&contents, file.path(), cfg)?;
- // move the old token location to the new one
+ // Move the old token location to the new one.
if let Some(token) = toml.as_table_mut().unwrap().remove("token") {
let mut map = HashMap::new();
map.insert("token".to_string(), token);
Some((fresh, key, data))
}
- /// Returns whether there are remaining packages to be built.
+ /// Returns `true` if there are remaining packages to be built.
pub fn is_empty(&self) -> bool {
self.dep_map.is_empty() && self.pending.is_empty()
}
// File locking on Unix is currently implemented via `flock`, which is known
// to be broken on NFS. We could in theory just ignore errors that happen on
// NFS, but apparently the failure mode [1] for `flock` on NFS is **blocking
- // forever**, even if the nonblocking flag is passed!
+ // forever**, even if the "non-blocking" flag is passed!
//
// As a result, we just skip all file locks entirely on NFS mounts. That
// should avoid calling any `flock` functions at all, and it wouldn't work
// In addition to ignoring NFS which is commonly not working we also
// just ignore locking on filesystems that look like they don't
// implement file locking. We detect that here via the return value of
- // locking (e.g. inspecting errno).
+ // locking (e.g., inspecting errno).
#[cfg(unix)]
Err(ref e) if e.raw_os_error() == Some(libc::ENOTSUP) => return Ok(()),
use std::fs;
use std::path::{Path, PathBuf};
-/// Find the root Cargo.toml
+/// Finds the root `Cargo.toml`.
pub fn find_root_manifest_for_wd(cwd: &Path) -> CargoResult<PathBuf> {
let file = "Cargo.toml";
for current in paths::ancestors(cwd) {
)
}
-/// Return the path to the `file` in `pwd`, if it exists.
+/// Returns the path to the `file` in `pwd`, if it exists.
pub fn find_project_manifest_exact(pwd: &Path, file: &str) -> CargoResult<PathBuf> {
let manifest = pwd.join(file);
fn drop(&mut self) {
// On normal exits (not ctrl-c), we don't want to kill any child
// processes. The destructor here configures our job object to
- // *not* kill everything on close, then closes the job object.
+ // **not** kill everything on close, then closes the job object.
unsafe {
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
info = mem::zeroed();
args: Vec<OsString>,
/// Any environment variables that should be set for the program.
env: HashMap<String, Option<OsString>>,
- /// Which directory to run the program from.
+ /// The directory to run the program from.
cwd: Option<OsString>,
/// The `make` jobserver. See the [jobserver crate][jobserver_docs] for
/// more information.
///
/// [jobserver_docs]: https://docs.rs/jobserver/0.1.6/jobserver/
jobserver: Option<Client>,
- /// Whether to include environment variable in display
+ /// `true` to include environment variable in display.
display_env_vars: bool,
}
}
impl ProcessBuilder {
- /// (chainable) Set the executable for the process.
+ /// (chainable) Sets the executable for the process.
pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
self.program = program.as_ref().to_os_string();
self
}
- /// (chainable) Add an arg to the args list.
+ /// (chainable) Adds `arg` to the args list.
pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
self.args.push(arg.as_ref().to_os_string());
self
}
- /// (chainable) Add many args to the args list.
- pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
+ /// (chainable) Adds multiple `args` to the args list.
+ pub fn args<T: AsRef<OsStr>>(&mut self, args: &[T]) -> &mut ProcessBuilder {
self.args
- .extend(arguments.iter().map(|t| t.as_ref().to_os_string()));
+ .extend(args.iter().map(|t| t.as_ref().to_os_string()));
self
}
- /// (chainable) Replace args with new args list
- pub fn args_replace<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
- self.args = arguments
+ /// (chainable) Replaces the args list with the given `args`.
+ pub fn args_replace<T: AsRef<OsStr>>(&mut self, args: &[T]) -> &mut ProcessBuilder {
+ self.args = args
.iter()
.map(|t| t.as_ref().to_os_string())
.collect();
self
}
- /// (chainable) Set the current working directory of the process
+ /// (chainable) Sets the current working directory of the process.
pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {
self.cwd = Some(path.as_ref().to_os_string());
self
}
- /// (chainable) Set an environment variable for the process.
+ /// (chainable) Sets an environment variable for the process.
pub fn env<T: AsRef<OsStr>>(&mut self, key: &str, val: T) -> &mut ProcessBuilder {
self.env
.insert(key.to_string(), Some(val.as_ref().to_os_string()));
self
}
- /// (chainable) Unset an environment variable for the process.
+ /// (chainable) Unsets an environment variable for the process.
pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {
self.env.insert(key.to_string(), None);
self
}
- /// Get the executable name.
+ /// Gets the executable name.
pub fn get_program(&self) -> &OsString {
&self.program
}
- /// Get the program arguments
+ /// Gets the program arguments.
pub fn get_args(&self) -> &[OsString] {
&self.args
}
- /// Get the current working directory for the process
+ /// Gets the current working directory for the process.
pub fn get_cwd(&self) -> Option<&Path> {
self.cwd.as_ref().map(Path::new)
}
- /// Get an environment variable as the process will see it (will inherit from environment
+ /// Gets an environment variable as the process will see it (will inherit from environment
/// unless explicitally unset).
pub fn get_env(&self, var: &str) -> Option<OsString> {
self.env
.and_then(|s| s)
}
- /// Get all environment variables explicitly set or unset for the process (not inherited
+ /// Gets all environment variables explicitly set or unset for the process (not inherited
/// vars).
pub fn get_envs(&self) -> &HashMap<String, Option<OsString>> {
&self.env
}
- /// Set the `make` jobserver. See the [jobserver crate][jobserver_docs] for
+ /// Sets the `make` jobserver. See the [jobserver crate][jobserver_docs] for
/// more information.
///
/// [jobserver_docs]: https://docs.rs/jobserver/0.1.6/jobserver/
self
}
- /// Enable environment variable display
+ /// Enables environment variable display.
pub fn display_env_vars(&mut self) -> &mut Self {
self.display_env_vars = true;
self
}
- /// Run the process, waiting for completion, and mapping non-success exit codes to an error.
+ /// Runs the process, waiting for completion, and mapping non-success exit codes to an error.
pub fn exec(&self) -> CargoResult<()> {
let mut command = self.build_command();
let exit = command.status().chain_err(|| {
/// Replaces the current process with the target process.
///
- /// On Unix, this executes the process using the unix syscall `execvp`, which will block
+ /// On Unix, this executes the process using the Unix syscall `execvp`, which will block
/// this process, and will only return if there is an error.
///
/// On Windows this isn't technically possible. Instead we emulate it to the best of our
- /// ability. One aspect we fix here is that we specify a handler for the ctrl-c handler.
- /// In doing so (and by effectively ignoring it) we should emulate proxying ctrl-c
+ /// ability. One aspect we fix here is that we specify a handler for the Ctrl-C handler.
+ /// In doing so (and by effectively ignoring it) we should emulate proxying Ctrl-C
/// handling to the application at hand, which will either terminate or handle it itself.
- /// According to microsoft's documentation at:
- /// https://docs.microsoft.com/en-us/windows/console/ctrl-c-and-ctrl-break-signals
- /// the ctrl-c signal is sent to all processes attached to a terminal, which should
+ /// According to Microsoft's documentation at
+ /// <https://docs.microsoft.com/en-us/windows/console/ctrl-c-and-ctrl-break-signals>.
+ /// the Ctrl-C signal is sent to all processes attached to a terminal, which should
/// include our child process. If the child terminates then we'll reap them in Cargo
/// pretty quickly, and if the child handles the signal then we won't terminate
/// (and we shouldn't!) until the process itself later exits.
imp::exec_replace(self)
}
- /// Execute the process, returning the stdio output, or an error if non-zero exit status.
+ /// Executes the process, returning the stdio output, or an error if non-zero exit status.
pub fn exec_with_output(&self) -> CargoResult<Output> {
let mut command = self.build_command();
}
}
- /// Execute a command, passing each line of stdout and stderr to the supplied callbacks, which
+ /// Executes a command, passing each line of stdout and stderr to the supplied callbacks, which
/// can mutate the string data.
///
/// If any invocations of these function return an error, it will be propagated.
Ok(output)
}
- /// Converts ProcessBuilder into a `std::process::Command`, and handles the jobserver if
+ /// Converts `ProcessBuilder` into a `std::process::Command`, and handles the jobserver, if
/// present.
pub fn build_command(&self) -> Command {
let mut command = Command::new(&self.program);
use winapi::um::consoleapi::SetConsoleCtrlHandler;
unsafe extern "system" fn ctrlc_handler(_: DWORD) -> BOOL {
- // Do nothing. Let the child process handle it.
+ // Do nothing; let the child process handle it.
TRUE
}
}
}
- // Just exec the process as normal.
+ // Just execute the process as normal.
process_builder.exec()
}
}
}
impl Rustc {
- /// Run the compiler at `path` to learn various pieces of information about
+ /// Runs the compiler at `path` to learn various pieces of information about
/// it, with an optional wrapper.
///
/// If successful this function returns a description of the compiler along
})
}
- /// Get a process builder set up to use the found rustc version, with a wrapper if Some
+ /// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.
pub fn process(&self) -> ProcessBuilder {
match self.wrapper {
Some(ref wrapper) if !wrapper.as_os_str().is_empty() => {
TOML file found which contains invalid syntax and will soon not parse
at `{}`.
-The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
+The TOML spec requires newlines after table definitions (e.g., `[a] b = 1` is
invalid), but this file has a table header which does not have a newline after
it. A newline needs to be added and this warning will soon become a hard error
in the future.",
/// Represents the `package`/`project` sections of a `Cargo.toml`.
///
/// Note that the order of the fields matters, since this is the order they
-/// are serialized to a TOML file. For example, you cannot have values after
+/// are serialized to a TOML file. For example, you cannot have values after
/// the field `metadata`, since it is a table and values cannot appear after
/// tables.
#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(rename = "default-run")]
default_run: Option<String>,
- // package metadata
+ // Package metadata.
description: Option<String>,
homepage: Option<String>,
documentation: Option<String>,
let mut warnings = vec![];
let mut errors = vec![];
- // Parse features first so they will be available when parsing other parts of the toml
+ // Parse features first so they will be available when parsing other parts of the TOML.
let empty = Vec::new();
let cargo_features = me.cargo_features.as_ref().unwrap_or(&empty);
let features = Features::new(&cargo_features, &mut warnings)?;
features.require(Feature::metabuild())?;
}
- // If we have no lib at all, use the inferred lib if available
- // If we have a lib with a path, we're done
- // If we have a lib with no path, use the inferred lib or_else package name
+ // If we have no lib at all, use the inferred lib, if available.
+ // If we have a lib with a path, we're done.
+ // If we have a lib with no path, use the inferred lib or else the package name.
let targets = targets(
&features,
me,
Ok(())
}
- // Collect the deps
+ // Collect the dependencies.
process_dependencies(&mut cx, me.dependencies.as_ref(), None)?;
let dev_deps = me
.dev_dependencies
) -> Option<PathBuf> {
let build_rs = package_root.join("build.rs");
match *build {
- Some(StringOrBool::Bool(false)) => None, // explicitly no build script
+ // Explicitly no build script.
+ Some(StringOrBool::Bool(false)) => None,
Some(StringOrBool::Bool(true)) => Some(build_rs),
Some(StringOrBool::String(ref s)) => Some(PathBuf::from(s)),
None => {
match fs::metadata(&build_rs) {
- // If there is a build.rs file next to the Cargo.toml, assume it is
- // a build script
+ // If there is a `build.rs` file next to the `Cargo.toml`, assume it is
+ // a build script.
Ok(ref e) if e.is_file() => Some(build_rs),
Ok(_) | Err(_) => None,
}
}
}
-/// Will check a list of build targets, and make sure the target names are unique within a vector.
+/// Checks a list of build targets, and ensures the target names are unique within a vector.
/// If not, the name of the offending build target is returned.
fn unique_build_targets(targets: &[Target], package_root: &Path) -> Result<(), String> {
let mut seen = HashSet::new();
}
(None, Some(path), _, _) => {
cx.nested_paths.push(PathBuf::from(path));
- // If the source id for the package we're parsing is a path
+ // If the source ID for the package we're parsing is a path
// source, then we normalize the path here to get rid of
// components like `..`.
//
- // The purpose of this is to get a canonical id for the package
+ // The purpose of this is to get a canonical ID for the package
// that we're depending on to ensure that builds of this package
// always end up hashing to the same value no matter where it's
// built from.
// Per the Macros 1.1 RFC:
//
- // > Initially if a crate is compiled with the proc-macro crate type
+ // > Initially if a crate is compiled with the `proc-macro` crate type
// > (and possibly others) it will forbid exporting any items in the
// > crate other than those functions tagged #[proc_macro_derive] and
// > those functions must also be placed at the crate root.
vec![LibKind::ProcMacro]
}
(_, Some(true), Some(true)) => {
- failure::bail!("lib.plugin and lib.proc-macro cannot both be true")
+ failure::bail!("`lib.plugin` and `lib.proc-macro` cannot both be `true`")
}
(Some(kinds), _, _) => kinds.iter().map(|s| s.into()).collect(),
(None, Some(true), _) => vec![LibKind::Dylib],
=== Display Options
By default the Rust test harness hides output from benchmark execution to keep
-results readable. Benchmark output can be recovered (e.g. for debugging) by
+results readable. Benchmark output can be recovered (e.g., for debugging) by
passing `--nocapture` to the benchmark binaries:
cargo bench -- --nocapture
=== Display Options
By default the Rust test harness hides output from test execution to keep
-results readable. Test output can be recovered (e.g. for debugging) by passing
+results readable. Test output can be recovered (e.g., for debugging) by passing
`--nocapture` to the test binaries:
cargo test -- --nocapture
<h3 id="cargo_bench_display_options">Display Options</h3>
<div class="paragraph">
<p>By default the Rust test harness hides output from benchmark execution to keep
-results readable. Benchmark output can be recovered (e.g. for debugging) by
+results readable. Benchmark output can be recovered (e.g., for debugging) by
passing <code>--nocapture</code> to the benchmark binaries:</p>
</div>
<div class="literalblock">
<h3 id="cargo_test_display_options">Display Options</h3>
<div class="paragraph">
<p>By default the Rust test harness hides output from test execution to keep
-results readable. Test output can be recovered (e.g. for debugging) by passing
+results readable. Test output can be recovered (e.g., for debugging) by passing
<code>--nocapture</code> to the test binaries:</p>
</div>
<div class="literalblock">
The *package root* is the directory where the package's `Cargo.toml` manifest
is located.
-The [*package id specification*][pkgid-spec], or *SPEC*, is a string used to
+The [*package ID specification*][pkgid-spec], or *SPEC*, is a string used to
uniquely reference a specific version of a package from a specific source.
### Project
### Spec
-See [package id specification](#package).
+See [package ID specification](#package).
### Target
## Configuration
This document will explain how Cargo’s configuration system works, as well as
-available keys or configuration. For configuration of a package through its
+available keys or configuration. For configuration of a package through its
manifest, see the [manifest format](reference/manifest.html).
### Hierarchical structure
[http]
proxy = "host:port" # HTTP proxy to use for HTTP requests (defaults to none)
- # in libcurl format, e.g. "socks5h://host:port"
+ # in libcurl format, e.g., "socks5h://host:port"
timeout = 30 # Timeout for each HTTP request, in seconds
cainfo = "cert.pem" # Path to Certificate Authority (CA) bundle (optional)
check-revoke = true # Indicates whether SSL certs are checked for revocation
system:
* `CARGO_HOME` — Cargo maintains a local cache of the registry index and of git
- checkouts of crates. By default these are stored under `$HOME/.cargo`, but
+ checkouts of crates. By default these are stored under `$HOME/.cargo`, but
this variable overrides the location of this directory. Once a crate is cached
it is not removed by the clean command.
* `CARGO_TARGET_DIR` — Location of where to place all generated artifacts,
* `CARGO_PKG_HOMEPAGE` - The home page from the manifest of your package.
* `CARGO_PKG_REPOSITORY` - The repository from the manifest of your package.
* `OUT_DIR` - If the package has a build script, this is set to the folder where the build
- script should place its output. See below for more information.
+ script should place its output. See below for more information.
### Environment variables Cargo sets for build scripts
#### The `edition` field (optional)
You can opt in to a specific Rust Edition for your package with the
-`edition` key in `Cargo.toml`. If you don't specify the edition, it will
+`edition` key in `Cargo.toml`. If you don't specify the edition, it will
default to 2015.
```toml
Documentation links from specific hosts are blacklisted. Hosts are added
to the blacklist if they are known to not be hosting documentation and are
-possibly of malicious intent e.g. ad tracking networks. URLs from the
+possibly of malicious intent e.g., ad tracking networks. URLs from the
following hosts are blacklisted:
* rust-ci.org
# they must match exactly.
categories = ["...", "..."]
-# This is an SPDX 2.1 license expression for this package. Currently
+# This is an SPDX 2.1 license expression for this package. Currently
# crates.io will validate the license provided against a whitelist of
# known license and exception identifiers from the SPDX license list
-# 2.4. Parentheses are not currently supported.
+# 2.4. Parentheses are not currently supported.
#
# Multiple licenses can be separated with a `/`, although that usage
-# is deprecated. Instead, use a license expression with AND and OR
+# is deprecated. Instead, use a license expression with AND and OR
# operators to get more explicit semantics.
license = "..."
published crate.
SPDX 2.1 license expressions are documented
-[here][spdx-2.1-license-expressions]. The current version of the
+[here][spdx-2.1-license-expressions]. The current version of the
license list is available [here][spdx-license-list], and version 2.4
is available [here][spdx-license-list-2.4].
# string is specified like 'thin' then `-C lto=thin` will
# be passed.
debug-assertions = true # controls whether debug assertions are enabled
- # (e.g. debug_assert!() and arithmetic overflow checks)
+ # (e.g., debug_assert!() and arithmetic overflow checks)
codegen-units = 16 # if > 1 enables parallel code generation which improves
# compile times, but prevents some optimizations.
# Passes `-C codegen-units`.
# Passes the `-C overflow-checks=...` flag to the compiler.
# The release profile, used for `cargo build --release` (and the dependencies
-# for `cargo test --release`, including the local library or binary).
+# for `cargo test --release`, including the local library or binary).
[profile.release]
opt-level = 3
debug = false
* The *root crate*'s `Cargo.toml` contains the `[workspace]` table, but is not
required to have other configuration.
* Whenever any crate in the workspace is compiled, output is placed in the
- *workspace root*. i.e. next to the *root crate*'s `Cargo.toml`.
+ *workspace root* (i.e., next to the *root crate*'s `Cargo.toml`).
* The lock file for all crates in the workspace resides in the *workspace root*.
* The `[patch]`, `[replace]` and `[profile.*]` sections in `Cargo.toml`
are only recognized
with a name of the parent directory.
Do note, however, once you add a `[[bin]]` section ([see
below](#configuring-a-target)), Cargo will no longer automatically build files
-located in `src/bin/*.rs`. Instead you must create a `[[bin]]` section for
+located in `src/bin/*.rs`. Instead you must create a `[[bin]]` section for
each file you want to build.
Your package can optionally contain folders named `examples`, `tests`, and
"bar:1.0.2" = { path = 'my/local/bar' }
```
-Each key in the `[replace]` table is a [package id
-specification](reference/pkgid-spec.html) which allows arbitrarily choosing a node in the
+Each key in the `[replace]` table is a [package ID
+specification](reference/pkgid-spec.html), which allows arbitrarily choosing a node in the
dependency graph to override. The value of each key is the same as the
`[dependencies]` syntax for specifying dependencies, except that you can't
specify features. Note that when a crate is overridden the copy it's overridden
with must have both the same name and version, but it can come from a different
-source (e.g. git or a local path).
+source (e.g., git or a local path).
More information about overriding dependencies can be found in the [overriding
dependencies][replace] section of the documentation.
```
This command will inform Cargo of your API token and store it locally in your
-`~/.cargo/credentials` (previously it was `~/.cargo/config`). Note that this
+`~/.cargo/credentials` (previously it was `~/.cargo/config`). Note that this
token is a **secret** and should not be shared with anyone else. If it leaks for
any reason, you should regenerate it immediately.
Now’s a good time to take a look at the `*.crate` file to make sure you didn’t
accidentally package up that 2GB video asset, or large data files used for code
-generation, integration tests, or benchmarking. There is currently a 10MB
+generation, integration tests, or benchmarking. There is currently a 10MB
upload size limit on `*.crate` files. So, if the size of `tests` and `benches`
directories and their dependencies are up to a couple of MBs, you can keep them
in your package; otherwise, better to exclude them.
https://github.com/organizations/:org/settings/oauth_application_policy
-where `:org` is the name of the organization (e.g. rust-lang). You may see
+where `:org` is the name of the organization (e.g., `rust-lang`). You may see
something like:
![Organization Access Control](images/org-level-acl.png)
### Multiple requirements
-Multiple version requirements can also be separated with a comma, e.g. `>= 1.2,
+Multiple version requirements can also be separated with a comma, e.g., `>= 1.2,
< 1.5`.
### Specifying dependencies from other registries
## Unstable Features
-Experimental Cargo features are only available on the nightly channel. You
-typically use one of the `-Z` flags to enable them. Run `cargo -Z help` to
+Experimental Cargo features are only available on the nightly channel. You
+typically use one of the `-Z` flags to enable them. Run `cargo -Z help` to
see a list of flags available.
`-Z unstable-options` is a generic flag for enabling other unstable
-command-line flags. Options requiring this will be called out below.
+command-line flags. Options requiring this will be called out below.
Some unstable features will require you to specify the `cargo-features` key in
`Cargo.toml`.
* Tracking Issue: [#5654](https://github.com/rust-lang/cargo/issues/5654)
When creating a `.crate` file for distribution, Cargo has historically
-not included the `Cargo.lock` file. This can cause problems with
-using `cargo install` with a binary. You can specify that your package
+not included the `Cargo.lock` file. This can cause problems with
+using `cargo install` with a binary. You can specify that your package
should include the `Cargo.lock` file when using `cargo package` or `cargo publish`
-by specifying the `publish-lockfile` key in `Cargo.toml`. This also requires the
+by specifying the `publish-lockfile` key in `Cargo.toml`. This also requires the
appropriate `cargo-features`:
```toml
* Tracking Issue: [#5655](https://github.com/rust-lang/cargo/issues/5655)
The `-Z offline` flag prevents Cargo from attempting to access the network for
-any reason. Typically Cargo will stop with an error if it wants to access the
+any reason. Typically Cargo will stop with an error if it wants to access the
network and it is not available.
Beware that this may result in different dependency resolution than online
-mode. Cargo will restrict itself to crates that are available locally, even
+mode. Cargo will restrict itself to crates that are available locally, even
if there might be a newer version as indicated in the local copy of the index.
### no-index-update
* Original Issue: [#3479](https://github.com/rust-lang/cargo/issues/3479)
The `-Z no-index-update` flag ensures that Cargo does not attempt to update
-the registry index. This is intended for tools such as Crater that issue many
+the registry index. This is intended for tools such as Crater that issue many
Cargo commands, and you want to avoid the network latency for updating the
index each time.
When running commands such as `cargo install` or `cargo build`, Cargo
currently requires dev-dependencies to be downloaded, even if they are not
-used. The `-Z avoid-dev-deps` flag allows Cargo to avoid downloading
-dev-dependencies if they are not needed. The `Cargo.lock` file will not be
+used. The `-Z avoid-dev-deps` flag allows Cargo to avoid downloading
+dev-dependencies if they are not needed. The `Cargo.lock` file will not be
generated if dev-dependencies are skipped.
### minimal-versions
* Original Issue: [#4875](https://github.com/rust-lang/cargo/issues/4875)
This feature allows you to specify the directory where artifacts will be
-copied to after they are built. Typically artifacts are only written to the
-`target/release` or `target/debug` directories. However, determining the
+copied to after they are built. Typically artifacts are only written to the
+`target/release` or `target/debug` directories. However, determining the
exact filename can be tricky since you need to parse JSON output. The
`--out-dir` flag makes it easier to predictably access the artifacts. Note
that the artifacts are copied, so the originals are still in the `target`
-directory. Example:
+directory. Example:
```
cargo +nightly build --out-dir=out -Z unstable-options
* Tracking Issue: [rust-lang/rust#48683](https://github.com/rust-lang/rust/issues/48683)
* RFC: [#2282](https://github.com/rust-lang/rfcs/blob/master/text/2282-profile-dependencies.md)
-Profiles can be specified in `.cargo/config` files. The `-Z config-profile`
-command-line flag is required to use this feature. The format is the same as
-in a `Cargo.toml` manifest. If found in multiple config files, settings will
+Profiles can be specified in `.cargo/config` files. The `-Z config-profile`
+command-line flag is required to use this feature. The format is the same as
+in a `Cargo.toml` manifest. If found in multiple config files, settings will
be merged using the regular [config hierarchy](reference/config.html#hierarchical-structure).
Config settings take precedence over manifest settings.
* Tracking Issue: [rust-lang/rust#49803](https://github.com/rust-lang/rust/issues/49803)
* RFC: [#2196](https://github.com/rust-lang/rfcs/blob/master/text/2196-metabuild.md)
-Metabuild is a feature to have declarative build scripts. Instead of writing
+Metabuild is a feature to have declarative build scripts. Instead of writing
a `build.rs` script, you specify a list of build dependencies in the
-`metabuild` key in `Cargo.toml`. A build script is automatically generated
-that runs each build dependency in order. Metabuild packages can then read
+`metabuild` key in `Cargo.toml`. A build script is automatically generated
+that runs each build dependency in order. Metabuild packages can then read
metadata from `Cargo.toml` to specify their behavior.
Include `cargo-features` at the top of `Cargo.toml`, a `metabuild` key in the
`package`, list the dependencies in `build-dependencies`, and add any metadata
-that the metabuild packages require under `package.metadata`. Example:
+that the metabuild packages require under `package.metadata`. Example:
```toml
cargo-features = ["metabuild"]
.SS "Display Options"
.sp
By default the Rust test harness hides output from benchmark execution to keep
-results readable. Benchmark output can be recovered (e.g. for debugging) by
+results readable. Benchmark output can be recovered (e.g., for debugging) by
passing \fB\-\-nocapture\fP to the benchmark binaries:
.sp
.if n .RS 4
.SS "Display Options"
.sp
By default the Rust test harness hides output from test execution to keep
-results readable. Test output can be recovered (e.g. for debugging) by passing
+results readable. Test output can be recovered (e.g., for debugging) by passing
\fB\-\-nocapture\fP to the test binaries:
.sp
.if n .RS 4
warning: TOML file found which contains invalid syntax and will soon not parse
at `[..]config`.
-The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
+The TOML spec requires newlines after table definitions (e.g., `[a] b = 1` is
invalid), but this file has a table header which does not have a newline after
it. A newline needs to be added and this warning will soon become a hard error
in the future.
.run();
}
-/// Check that the `CARGO_INCREMENTAL` environment variable results in
+/// Checks that the `CARGO_INCREMENTAL` environment variable results in
/// `rustc` getting `-Zincremental` passed to it.
#[test]
fn cargo_compile_incremental() {
p.cargo("build -p notAValidDep")
.with_status(101)
- .with_stderr("[ERROR] package id specification `notAValidDep` matched no packages")
+ .with_stderr("[ERROR] package ID specification `notAValidDep` matched no packages")
.run();
p.cargo("build -p d1 -p notAValidDep")
.with_status(101)
- .with_stderr("[ERROR] package id specification `notAValidDep` matched no packages")
+ .with_stderr("[ERROR] package ID specification `notAValidDep` matched no packages")
.run();
}
.file("bar/src/lib.rs", r#"fn dead() {}"#)
.build();
- // Using jobs=1 to ensure that the order of messages is consistent.
+ // Use `jobs=1` to ensure that the order of messages is consistent.
p.cargo("build -v --message-format=json --jobs=1")
.with_json(
r#"
.file("baz/src/lib.rs", "pub fn baz() {}")
.build();
- // The order in which bar and baz are built is not guaranteed
+ // The order in which `bar` and `baz` are built is not guaranteed.
p.cargo("build")
.with_stderr_contains("[..] Compiling baz v0.1.0 ([..])")
.with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
}
#[test]
-#[cfg(not(windows))] // We don't have /usr/bin/env on Windows.
+// NOTE: we don't have `/usr/bin/env` on Windows.
+#[cfg(not(windows))]
fn rustc_wrapper() {
let p = project().file("src/lib.rs", "").build();
p.cargo("build -v")
#[test]
fn deterministic_cfg_flags() {
- // This bug is non-deterministic
+ // This bug is non-deterministic.
let p = project()
.file(
.build();
p.cargo("build -v")
- .without_status() // passes on nightly, fails on stable, b/c --edition is nightly-only
+ // Passes on nightly, fails on stable, since `--edition` is nightly-only.
+ .without_status()
.with_stderr_contains(
"\
[COMPILING] foo v0.0.1 ([..])
assert!(!p.target_debug_dir().join("d.pdb").is_file());
}
-// Make sure that `cargo build` chooses the correct profile for building
-// targets based on filters (assuming --profile is not specified).
+// Ensure that `cargo build` chooses the correct profile for building
+// targets based on filters (assuming `--profile` is not specified).
#[test]
fn build_filter_infer_profile() {
let p = project()
fn targets_selected_default() {
let p = project().file("src/main.rs", "fn main() {}").build();
p.cargo("build -v")
- // bin
+ // Binaries.
.with_stderr_contains(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \
--emit=dep-info,link[..]",
)
- // bench
+ // Benchmarks.
.with_stderr_does_not_contain(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \
-C opt-level=3 --test [..]",
)
- // unit test
+ // Unit tests.
.with_stderr_does_not_contain(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \
fn targets_selected_all() {
let p = project().file("src/main.rs", "fn main() {}").build();
p.cargo("build -v --all-targets")
- // bin
+ // Binaries.
.with_stderr_contains(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \
--emit=dep-info,link[..]",
)
- // unit test
+ // Unit tests.
.with_stderr_contains(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \
fn all_targets_no_lib() {
let p = project().file("src/main.rs", "fn main() {}").build();
p.cargo("build -v --all-targets")
- // bin
+ // Binaries.
.with_stderr_contains(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \
--emit=dep-info,link[..]",
)
- // unit test
+ // Unit tests.
.with_stderr_contains(
"\
[RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \
#[test]
fn no_linkable_target() {
- // Issue 3169. This is currently not an error as per discussion in PR #4797
+ // Issue 3169: this is currently not an error as per discussion in PR #4797.
let p = project()
.file(
"Cargo.toml",
#[test]
fn json_parse_fail() {
- // Ensure when json parsing fails, and rustc exits with non-zero exit
- // code, that a useful error message is displayed.
+ // Ensure when JSON parsing fails, and rustc exits with non-zero exit
+ // code, a useful error message is displayed.
let foo = project()
.file(
"Cargo.toml",
use bufstream::BufStream;
use git2;
-// Test that HTTP auth is offered from `credential.helper`
+// Tests that HTTP auth is offered from `credential.helper`.
#[test]
fn http_auth_offered() {
let server = TcpListener::bind("127.0.0.1:0").unwrap();
errmsg = if cfg!(windows) {
"[..]failed to send request: [..]"
} else if cfg!(target_os = "macos") {
- // OSX is difficult to tests as some builds may use
- // Security.framework and others may use OpenSSL. In that case let's
- // just not verify the error message here.
+ // macOS is difficult to tests as some builds may use Security.framework,
+ // while others may use OpenSSL. In that case, let's just not verify the error
+ // message here.
"[..]"
} else {
"[..]SSL error: [..]"
t.join().ok().unwrap();
}
-// Boy, sure would be nice to have an SSH implementation in rust!
+// It would sure be nice to have an SSH implementation in Rust!
#[test]
fn ssh_something_happens() {
let server = TcpListener::bind("127.0.0.1:0").unwrap();
"#,
).build();
- // TODO: TEST FAILS BECAUSE OF WRONG STDOUT (but otherwise, the build works)
+ // TODO: TEST FAILS BECAUSE OF WRONG STDOUT (but otherwise, the build works).
p.cargo("build --verbose")
.with_status(101)
.with_stderr(
let p2 = p2.build();
// Move the output `libfoo.so` into the directory of `p2`, and then delete
- // the `p` project. On OSX the `libfoo.dylib` artifact references the
+ // the `p` project. On macOS, the `libfoo.dylib` artifact references the
// original path in `p` so we want to make sure that it can't find it (hence
// the deletion).
let root = if cross {
Symlink { target: &'a Path },
}
-/// Add an empty file with executable flags (and platform-dependent suffix).
-/// TODO: move this to `Project` if other cases using this emerge.
+/// Adds an empty file with executable flags (and platform-dependent suffix).
+//
+// TODO: move this to `Project` if other cases using this emerge.
fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind<'_>) -> Project {
let path = proj
.root()
.with_stdout_contains(
" build Compile a local package and all of its dependencies",
)
- // assert read-manifest prints the right one-line description followed by another command, indented.
+ // Assert that `read-manifest` prints the right one-line description followed by another
+ // command, indented.
.with_stdout_contains(
" read-manifest Print a JSON representation of a Cargo.toml manifest.",
)
);
}
-// windows and symlinks don't currently agree that well
+// Windows and symlinks don't currently mix well.
#[cfg(unix)]
#[test]
fn list_command_resolves_symlinks() {
.run();
}
-// if a subcommand is more than 3 edit distance away, we don't make a suggestion
+// If a subcommand is more than an edit distance of 3 away, we don't make a suggestion.
#[test]
fn find_closest_dont_correct_nonsense() {
cargo_process("there-is-no-way-that-there-is-a-command-close-to-this")
.run();
}
-// Test that the output of 'cargo -Z help' shows a different help screen with
-// all the -Z flags.
+// Test that the output of `cargo -Z help` shows a different help screen with
+// all the `-Z` flags.
#[test]
fn z_flags_help() {
cargo_process("-Z help")
.file("b/src/lib.rs", "")
.build();
- // j=1 is required because on windows you'll get an error because
- // two processes will be writing to the file at the same time.
+ // `j=1` is required because on Windows you'll get an error due to
+ // two processes writing to the file at the same time.
p.cargo("build -j=1")
.with_stderr_contains(&format!("\
[WARNING] output filename collision.
Colliding filename is: [..]/foo/target/debug/deps/{}a{}
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
-This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313
+This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX))
.run();
}
Colliding filename is: [..]/foo/target/debug/examples/ex1[EXE]
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
-This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313
+This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
.run();
}
#[test]
fn collision_export() {
- // --out-dir combines some things which can cause conflicts.
+ // `--out-dir` combines some things which can cause conflicts.
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("examples/foo.rs", "fn main() {}")
Colliding filename is: [..]/foo/out/foo[EXE]
The exported filenames should be unique.
Consider changing their names to be unique or compiling them separately.
-This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313
+This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
.run();
}
("CARGO_PROFILE_DEV_OVERRIDES_bar_OPT_LEVEL", "2"),
]);
- // TODO: don't use actual tomlprofile
+ // TODO: don't use actual `tomlprofile`.
let p: toml::TomlProfile = config.get("profile.dev").unwrap();
let mut overrides = collections::BTreeMap::new();
let key = toml::ProfilePackageSpec::Spec(::cargo::core::PackageIdSpec::parse("bar").unwrap());
this could be indicative of a few possible errors:
* the lock file is corrupt
- * a replacement source in use (e.g. a mirror) returned a different checksum
+ * a replacement source in use (e.g., a mirror) returned a different checksum
* the source itself may be corrupt in one way or another
unable to verify that `bar v0.1.0` is the same as when the lockfile was generated
-use crate::support;
use std::fs::{self, File};
use std::io::Read;
use std::str;
+use glob::glob;
+
use crate::support::paths::CargoPathExt;
use crate::support::registry::Package;
use crate::support::{basic_lib_manifest, basic_manifest, git, project};
use crate::support::{is_nightly, rustc_host};
-use glob::glob;
#[test]
fn simple() {
#[test]
fn plugins_no_use_target() {
- if !support::is_nightly() {
+ if !is_nightly() {
return;
}
let p = project()
#[test]
fn doc_all_member_dependency_same_name() {
- if !is_nightly() {
- // This can be removed once 1.29 is stable (rustdoc --cap-lints).
- return;
- }
let p = project()
.file(
"Cargo.toml",
#[test]
fn doc_edition() {
- if !support::is_nightly() {
- // Stable rustdoc won't have the edition option. Remove this once it
+ if !is_nightly() {
+ // Stable rustdoc won't have the edition option. Remove this once it
// is stabilized.
return;
}
#[test]
fn doc_target_edition() {
- if !support::is_nightly() {
+ if !is_nightly() {
return;
}
let p = project()
#[test]
fn doc_cap_lints() {
if !is_nightly() {
- // This can be removed once 1.29 is stable (rustdoc --cap-lints).
+ // This can be removed once intra_doc_link_resolution_failure fails on stable.
return;
}
let a = git::new("a", |p| {
#[test]
fn doc_message_format() {
if !is_nightly() {
- // This can be removed once 1.30 is stable (rustdoc --error-format stabilized).
+ // This can be removed once intra_doc_link_resolution_failure fails on stable.
return;
}
let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build();
#[test]
fn short_message_format() {
if !is_nightly() {
- // This can be removed once 1.30 is stable (rustdoc --error-format stabilized).
+ // This can be removed once intra_doc_link_resolution_failure fails on stable.
return;
}
let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build();
p.cargo("build")
.with_status(101)
- .with_stderr("[ERROR] Cyclic feature dependency: feature `default` depends on itself")
+ .with_stderr("[ERROR] cyclic feature dependency: feature `default` depends on itself")
.run();
}
.file("src/lib.rs", "")
.build();
- // should fail due to a duplicate package `common` in the lockfile
+ // should fail due to a duplicate package `common` in the lock file
b.cargo("build")
.with_status(101)
.with_stderr_contains(
p.cargo("build").with_stdout("").run();
// Commit the changes and make sure we don't trigger a recompile because the
- // lockfile says not to change
+ // lock file says not to change
let repo = git2::Repository::open(&git_project.root()).unwrap();
git::add(&repo);
git::commit(&repo);
foo.cargo("build").run();
foo.process(&foo.bin("foo")).run();
- // Update the repo, and simulate someone else updating the lockfile and then
+ // Update the repo, and simulate someone else updating the lock file and then
// us pulling it down.
File::create(&bar.root().join("src/lib.rs"))
.unwrap()
)
.build();
- // Generate a lockfile which did not use `bar` to compile, but had to update
- // `bar` to generate the lockfile
+ // Generate a lock file which did not use `bar` to compile, but had to update
+ // `bar` to generate the lock file
p.cargo("build")
.with_stderr(&format!(
"\
.file("src/main.rs", "fn main() {}")
.build();
- // Generate a lockfile which did not use `bar` to compile, but had to update
- // `bar` to generate the lockfile
+ // Generate a lock file which did not use `bar` to compile, but had to update
+ // `bar` to generate the lock file
p.cargo("build")
.with_stderr(&format!(
"\
)
.run();
- println!("build 3: touch `src/not_incl.rs`; expect build script *not* re-run");
+ println!("build 3: touch `src/not_incl.rs`; expect build script **not** re-run");
sleep_ms(1000);
File::create(p.root().join("src").join("not_incl.rs")).unwrap();
-use crate::support;
use std::fs::{self, File, OpenOptions};
use std::io::prelude::*;
+use git2;
+
+use crate::support;
use crate::support::cross_compile;
use crate::support::git;
use crate::support::install::{assert_has_installed_exe, assert_has_not_installed_exe, cargo_home};
use crate::support::paths;
use crate::support::registry::Package;
use crate::support::{basic_manifest, cargo_process, project};
-use git2;
fn pkg(name: &str, vers: &str) {
Package::new(name, vers)
.file("src/main.rs", "fn main() {}")
.build();
- // use `--locked` to test that we don't even try to write a lockfile
+ // Use `--locked` to test that we don't even try to write a lock file.
cargo_process("install --locked --git")
.arg(p.url().to_string())
.with_stderr(
fn uninstall_pkg_does_not_exist() {
cargo_process("uninstall foo")
.with_status(101)
- .with_stderr("[ERROR] package id specification `foo` matched no packages")
+ .with_stderr("[ERROR] package ID specification `foo` matched no packages")
.run();
}
cargo_process("uninstall foo")
.with_status(101)
- .with_stderr("[ERROR] package id specification `foo` matched no packages")
+ .with_stderr("[ERROR] package ID specification `foo` matched no packages")
.run();
}
#[test]
fn installs_from_cwd_with_2018_warnings() {
if !support::is_nightly() {
- // Stable rust won't have the edition option. Remove this once it
+ // Stable rust won't have the edition option. Remove this once it
// is stabilized.
return;
}
.with_stderr(
"\
[REMOVING] [CWD]/home/.cargo/bin/foo[EXE]
-error: package id specification `bar` matched no packages
+error: package ID specification `bar` matched no packages
[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
error: some packages failed to uninstall
",
this could be indicative of a few possible errors:
* the lock file is corrupt
- * a replacement source in use (e.g. a mirror) returned a different checksum
+ * a replacement source in use (e.g., a mirror) returned a different checksum
* the source itself may be corrupt in one way or another
unable to verify that `bar v0.0.1` is the same as when the lockfile was generated
this could be indicative of a few possible errors:
* the lock file is corrupt
- * a replacement source in use (e.g. a mirror) returned a different checksum
+ * a replacement source in use (e.g., a mirror) returned a different checksum
* the source itself may be corrupt in one way or another
unable to verify that `bar v0.1.0` is the same as when the lockfile was generated
.run();
}
-// If the checksum is unlisted in the lockfile (e.g. <none>) yet we can
-// calculate it (e.g. it's a registry dep), then we should in theory just fill
+// If the checksum is unlisted in the lock file (e.g., <none>) yet we can
+// calculate it (e.g., it's a registry dep), then we should in theory just fill
// it in.
#[test]
fn unlisted_checksum_is_bad_if_we_calculate() {
.run();
}
-// If the checksum is listed in the lockfile yet we cannot calculate it (e.g.
-// git dependencies as of today), then make sure we choke.
+// If the checksum is listed in the lock file yet we cannot calculate it (e.g.,
+// Git dependencies as of today), then make sure we choke.
#[test]
fn listed_checksum_bad_if_we_cannot_compute() {
let git = git::new("bar", |p| {
assert_eq!(causes[1].manifest_path(), &missing_manifest_path);
}
-/// Test dependency version errors provide which package failed via a `ResolveError`.
+/// Tests dependency version errors provide which package failed via a `ResolveError`.
#[test]
fn member_manifest_version_error() {
let p = project()
"\
warning: manifest has no description, license, license-file, documentation, \
homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
.with_stderr(
"\
warning: manifest has no description, documentation, homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
.with_stderr(
"\
[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([..])
[ARCHIVING] [..]
[ARCHIVING] [..]
.with_stderr(
"\
[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] a v0.0.1 ([..])
[ARCHIVING] Cargo.toml
[ARCHIVING] src/lib.rs
.with_stderr(
"\
[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
.with_stderr(
"\
[WARNING] manifest has no documentation, homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[ERROR] all path dependencies must have a version specified when packaging.
dependency `bar` does not specify a version.
",
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
.file("bar.txt", "")
.file("src/bar.txt", "")
- // file in root
+ // File in root.
.file("file_root_1", "")
.file("file_root_2", "")
.file("file_root_3", "")
.file("file_root_4", "")
.file("file_root_5", "")
- // file in sub-dir
+ // File in sub-dir.
.file("some_dir/file_deep_1", "")
.file("some_dir/file_deep_2", "")
.file("some_dir/file_deep_3", "")
.file("some_dir/file_deep_4", "")
.file("some_dir/file_deep_5", "")
- // dir in root
+ // Dir in root.
.file("dir_root_1/some_dir/file", "")
.file("dir_root_2/some_dir/file", "")
.file("dir_root_3/some_dir/file", "")
.file("dir_root_4/some_dir/file", "")
.file("dir_root_5/some_dir/file", "")
- // dir in sub-dir
+ // Dir in sub-dir.
.file("some_dir/dir_deep_1/some_dir/file", "")
.file("some_dir/dir_deep_2/some_dir/file", "")
.file("some_dir/dir_deep_3/some_dir/file", "")
.with_stderr(
"\
[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[WARNING] [..] file `dir_root_1/some_dir/file` WILL be excluded [..]
See [..]
[WARNING] [..] file `dir_root_2/some_dir/file` WILL be excluded [..]
)
.file("foo.txt", "")
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
- .file("src/bar.txt", "") // should be ignored when packaging
+ // Should be ignored when packaging.
+ .file("src/bar.txt", "")
.build();
cargo_process("package --no-verify -v")
.with_stderr(
"\
[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([..])
[ARCHIVING] [..]
[ARCHIVING] [..]
.with_stderr(
"\
[WARNING] manifest has no documentation[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
+See <http://doc.crates.io/manifest.html#package-metadata> for more info.
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
);
}
-#[cfg(unix)] // windows doesn't allow these characters in filenames
+// Windows doesn't allow these characters in filenames.
+#[cfg(unix)]
#[test]
fn package_weird_characters() {
let p = project()
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
use crate::support::{basic_lib_manifest, basic_manifest, main_file, project};
#[test]
-#[cfg(not(windows))] // I have no idea why this is failing spuriously on
- // Windows, for more info see #3466.
+// I have no idea why this is failing spuriously on Windows;
+// for more info, see #3466.
+#[cfg(not(windows))]
fn cargo_compile_with_nested_deps_shorthand() {
let p = project()
.file(
)
.build();
- let msg = " lib.plugin and lib.proc-macro cannot both be true";
+ let msg = " `lib.plugin` and `lib.proc-macro` cannot both be `true`";
p.cargo("build")
.with_status(101)
.with_stderr_contains(msg)
-use crate::support::is_nightly;
use crate::support::{basic_manifest, project, Project};
-// These tests try to exercise exactly which profiles are selected for every
-// target.
+// These tests try to exercise exactly which profiles are selected for every target.
fn all_target_project() -> Project {
// This abuses the `codegen-units` setting so that we can verify exactly
}
"#,
)
- // bar package
+ // `bar` package.
.file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
.file("bar/src/lib.rs", "")
- // bdep package
+ // `bdep` package.
.file(
"bdep/Cargo.toml",
r#"
fn profile_selection_build() {
let p = all_target_project();
- // Build default targets.
+ // `build`
// NOTES:
// - bdep `panic` is not set because it thinks `build.rs` is a plugin.
// - build_script_build is built without panic because it thinks `build.rs` is a plugin.
fn profile_selection_build_release() {
let p = all_target_project();
- // Build default targets, release.
+ // `build --release`
p.cargo("build --release -vv").with_stderr_unordered("\
[COMPILING] bar [..]
[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
#[test]
fn profile_selection_build_all_targets() {
let p = all_target_project();
- // Build all explicit targets.
- // NOTES
+ // `build`
+ // NOTES:
// - bdep `panic` is not set because it thinks `build.rs` is a plugin.
// - build_script_build is built without panic because it thinks
// `build.rs` is a plugin.
// - Benchmark dependencies are compiled in `dev` mode, which may be
- // surprising. See https://github.com/rust-lang/cargo/issues/4929.
+ // surprising. See issue rust-lang/cargo#4929.
//
// - Dependency profiles:
// Pkg Target Profile Reason
// bdep lib dev-panic For foo build.rs
// foo custom dev-panic
//
- // - foo target list is:
+ // - `foo` target list is:
// Target Profile Mode
// ------ ------- ----
// lib dev+panic build (a normal lib target)
#[test]
fn profile_selection_build_all_targets_release() {
let p = all_target_project();
- // Build all explicit targets, release.
- // NOTES
+ // `build --all-targets --release`
+ // NOTES:
// - bdep `panic` is not set because it thinks `build.rs` is a plugin.
- // - bar compiled twice. It tries with and without panic, but the "is a
+ // - bar compiled twice. It tries with and without panic, but the "is a
// plugin" logic is forcing it to be cleared.
// - build_script_build is built without panic because it thinks
// `build.rs` is a plugin.
- // - build_script_build is being run two times. Once for the `dev` and
+ // - build_script_build is being run two times. Once for the `dev` and
// `test` targets, once for the `bench` targets.
// TODO: "PROFILE" says debug both times, though!
//
// bdep lib release-panic For foo build.rs
// foo custom release-panic
//
- // - foo target list is:
+ // - `foo` target list is:
// Target Profile Mode
// ------ ------- ----
// lib release+panic build (a normal lib target)
#[test]
fn profile_selection_test() {
let p = all_target_project();
- // Test default.
+ // `test`
// NOTES:
// - Dependency profiles:
// Pkg Target Profile Reason
// bdep lib dev-panic For foo build.rs
// foo custom dev-panic
//
- // - foo target list is:
+ // - `foo` target list is:
// Target Profile Mode
// ------ ------- ----
// lib dev-panic build (for tests)
#[test]
fn profile_selection_test_release() {
let p = all_target_project();
- // Test default release.
+ // `test --release`
// NOTES:
// - Dependency profiles:
// Pkg Target Profile Reason
// bdep lib release-panic For foo build.rs
// foo custom release-panic
//
- // - foo target list is:
+ // - `foo` target list is:
// Target Profile Mode
// ------ ------- ----
// lib release-panic build (for tests)
fn profile_selection_bench() {
let p = all_target_project();
- // Bench default.
+ // `bench`
// NOTES:
// - Dependency profiles:
// Pkg Target Profile Reason
// bdep lib release-panic For foo build.rs
// foo custom release-panic
//
- // - foo target list is:
+ // - `foo` target list is:
// Target Profile Mode
// ------ ------- ----
// lib release-panic build (for benches)
#[test]
fn profile_selection_check_all_targets() {
- if !is_nightly() {
- // This can be removed once 1.27 is stable, see below.
- return;
- }
-
let p = all_target_project();
- // check
+ // `check`
// NOTES:
// - Dependency profiles:
// Pkg Target Profile Action Reason
[FINISHED] dev [unoptimized + debuginfo] [..]
").run();
// Starting with Rust 1.27, rustc emits `rmeta` files for bins, so
- // everything should be completely fresh. Previously, bins were being
+ // everything should be completely fresh. Previously, bins were being
// rechecked.
- // See https://github.com/rust-lang/rust/pull/49289 and
- // https://github.com/rust-lang/cargo/issues/3624
+ // See PR rust-lang/rust#49289 and issue rust-lang/cargo#3624.
p.cargo("check --all-targets -vv")
.with_stderr_unordered(
"\
#[test]
fn profile_selection_check_all_targets_release() {
- if !is_nightly() {
- // See note in profile_selection_check_all_targets.
- return;
- }
-
let p = all_target_project();
- // check --release
- // https://github.com/rust-lang/cargo/issues/5218
+ // `check --release`
+ // See issue rust-lang/cargo#5218.
// This is a pretty straightforward variant of
// `profile_selection_check_all_targets` that uses `release` instead of
// `dev` for all targets.
#[test]
fn profile_selection_check_all_targets_test() {
- if !is_nightly() {
- // See note in profile_selection_check_all_targets.
- return;
- }
-
let p = all_target_project();
- // check --profile=test
+ // `check --profile=test`
// NOTES:
- // - This doesn't actually use the "test" profile. Everything uses dev.
- // It probably should use "test"??? Probably doesn't really matter.
+ // - This doesn't actually use the "test" profile. Everything uses "dev".
+ // It should probably use "test", although it probably doesn't really matter.
// - Dependency profiles:
// Pkg Target Profile Action Reason
// --- ------ ------- ------ ------
#[test]
fn profile_selection_doc() {
let p = all_target_project();
- // doc
+ // `doc`
// NOTES:
// - Dependency profiles:
// Pkg Target Profile Action Reason
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo_1` in package `foo` requires the features: `b`, `c`
-Consider enabling them by passing e.g. `--features=\"b c\"`
+Consider enabling them by passing, e.g., `--features=\"b c\"`
",
)
.run();
.with_stderr(
"\
error: target `foo_1` in package `foo` requires the features: `b`, `c`
-Consider enabling them by passing e.g. `--features=\"b c\"`
+Consider enabling them by passing, e.g., `--features=\"b c\"`
",
)
.run();
.with_stderr(
"\
error: target `foo_2` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
Caused by:
target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
Caused by:
target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `bar/a`
-Consider enabling them by passing e.g. `--features=\"bar/a\"`
+Consider enabling them by passing, e.g., `--features=\"bar/a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `bar/a`
-Consider enabling them by passing e.g. `--features=\"bar/a\"`
+Consider enabling them by passing, e.g., `--features=\"bar/a\"`
",
)
.run();
.with_stderr(
"\
error: target `foo` in package `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
+Consider enabling them by passing, e.g., `--features=\"a\"`
",
)
.run();
const CARGO_RUSTC_ERROR: &str =
"[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering
-the package by passing e.g. `--lib` or `--bin NAME` to specify a single target";
+the package by passing, e.g., `--lib` or `--bin NAME` to specify a single target";
#[test]
fn build_lib_for_foo() {
use crate::support::{basic_bin_manifest, main_file, project};
pub fn disabled() -> bool {
- // First, disable if ./configure requested so
+ // First, disable if `./configure` requested so.
match env::var("CFG_DISABLE_CROSS_TESTS") {
Ok(ref s) if *s == "1" => return true,
_ => {}
}
- // Right now the windows bots cannot cross compile due to the mingw setup,
- // so we disable ourselves on all but macos/linux setups where the rustc
- // install script ensures we have both architectures
+ // Right now, the Windows bots cannot cross compile due to the Mingw setup,
+ // so we disable ourselves on all but macOS/Linux setups where the rustc
+ // install script ensures we have both architectures.
if !(cfg!(target_os = "macos") || cfg!(target_os = "linux") || cfg!(target_env = "msvc")) {
return true;
}
if CAN_RUN_CROSS_TESTS.load(Ordering::SeqCst) {
// We were able to compile a simple project, so the user has the
- // necessary std:: bits installed. Therefore, tests should not
+ // necessary `std::` bits installed. Therefore, tests should not
// be disabled.
return false;
}
- // We can't compile a simple cross project. We want to warn the user
+ // We can't compile a simple cross project. We want to warn the user
// by failing a single test and having the remainder of the cross tests
- // pass. We don't use std::sync::Once here because panicing inside its
- // call_once method would poison the Once instance, which is not what
+ // pass. We don't use `std::sync::Once` here because panicking inside its
+ // `call_once` method would poison the `Once` instance, which is not what
// we want.
static HAVE_WARNED: AtomicBool = AtomicBool::new(false);
return true;
}
- // We are responsible for warning the user, which we do by panicing.
+ // We are responsible for warning the user, which we do by panicking.
let rustup_available = Command::new("rustup").output().is_ok();
let linux_help = if cfg!(target_os = "linux") {
/// Add all files in the working directory to the git index.
pub fn add(repo: &git2::Repository) {
- // FIXME(libgit2/libgit2#2514): apparently add_all will add all submodules
- // as well, and then fail b/c they're a directory. As a stopgap, we just
+ // FIXME(libgit2/libgit2#2514): apparently, `add_all` will add all submodules
+ // as well, and then fail because they're directories. As a stop-gap, we just
// ignore all submodules.
let mut s = t!(repo.submodules());
for submodule in s.iter_mut() {
use crate::support::paths;
/// Used by `cargo install` tests to assert an executable binary
-/// has been installed. Example usage:
+/// has been installed. Example usage:
///
/// assert_has_installed_exe(cargo_home(), "foo");
pub fn assert_has_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) {
/*
-# Introduction To `support`
+# Introduction to `support`.
Cargo has a wide variety of integration tests that execute the `cargo` binary
-and verify its behavior. The `support` module contains many helpers to make
+and verify its behavior. The `support` module contains many helpers to make
this process easy.
The general form of a test involves creating a "project", running cargo, and
-checking the result. Projects are created with the `ProjectBuilder` where you
-specify some files to create. The general form looks like this:
+checking the result. Projects are created with the `ProjectBuilder` where you
+specify some files to create. The general form looks like this:
```
let p = project()
The project creates a mini sandbox under the "cargo integration test"
directory with each test getting a separate directory such as
-`/path/to/cargo/target/cit/t123/`. Each project appears as a separate
-directory. There is also an empty `home` directory created that will be used
+`/path/to/cargo/target/cit/t123/`. Each project appears as a separate
+directory. There is also an empty `home` directory created that will be used
as a home directory instead of your normal home directory.
See `support::lines_match` for an explanation of the string pattern matching.
When checking output, use `/` for paths even on Windows: the actual output
of `\` on Windows will be replaced with `/`.
-Be careful when executing binaries on Windows. You should not rename, delete,
-or overwrite a binary immediately after running it. Under some conditions
+Be careful when executing binaries on Windows. You should not rename, delete,
+or overwrite a binary immediately after running it. Under some conditions
Windows will fail with errors like "directory not empty" or "failed to remove"
or "access is denied".
self
}
- /// Add a file to the project.
+ /// Adds a file to the project.
pub fn file<B: AsRef<Path>>(mut self, path: B, body: &str) -> Self {
self._file(path.as_ref(), body);
self
.push(FileBuilder::new(self.root.root().join(path), body));
}
- /// Add a symlink to the project.
+ /// Adds a symlink to the project.
pub fn symlink<T: AsRef<Path>>(mut self, dst: T, src: T) -> Self {
self.symlinks.push(SymlinkBuilder::new(
self.root.root().join(dst),
self
}
- /// Create the project.
+ /// Creates the project.
pub fn build(mut self) -> Project {
// First, clean the directory if it already exists
self.rm_root();
))
}
- /// Change the contents of an existing file.
+ /// Changes the contents of an existing file.
pub fn change_file(&self, path: &str, body: &str) {
FileBuilder::new(self.root().join(path), body).mk()
}
- /// Create a `ProcessBuilder` to run a program in the project
+ /// Creates a `ProcessBuilder` to run a program in the project
/// and wrap it in an Execs to assert on the execution.
/// Example:
/// p.process(&p.bin("foo"))
execs().with_process_builder(p)
}
- /// Create a `ProcessBuilder` to run cargo.
+ /// Creates a `ProcessBuilder` to run cargo.
/// Arguments can be separated by spaces.
/// Example:
/// p.cargo("build --bin foo").run();
/// times, you should instead use `cargo build` and use this
/// method to run the executable. Each time you call this,
/// use a new name for `dst`.
- /// See https://github.com/rust-lang/cargo/issues/5481
+ /// See rust-lang/cargo#5481.
pub fn rename_run(&self, src: &str, dst: &str) -> Execs {
let src = self.bin(src);
let dst = self.bin(dst);
self
}
- /// Verify that stdout is equal to the given lines.
+ /// Verifies that stdout is equal to the given lines.
/// See `lines_match` for supported patterns.
pub fn with_stdout<S: ToString>(&mut self, expected: S) -> &mut Self {
self.expect_stdout = Some(expected.to_string());
self
}
- /// Verify that stderr is equal to the given lines.
+ /// Verifies that stderr is equal to the given lines.
/// See `lines_match` for supported patterns.
pub fn with_stderr<S: ToString>(&mut self, expected: S) -> &mut Self {
self.expect_stderr = Some(expected.to_string());
self
}
- /// Verify the exit code from the process.
+ /// Verifies the exit code from the process.
///
/// This is not necessary if the expected exit code is `0`.
pub fn with_status(&mut self, expected: i32) -> &mut Self {
self
}
- /// Remove exit code check for the process.
+ /// Removes exit code check for the process.
///
/// By default, the expected exit code is `0`.
pub fn without_status(&mut self) -> &mut Self {
self
}
- /// Verify that stdout contains the given contiguous lines somewhere in
+ /// Verifies that stdout contains the given contiguous lines somewhere in
/// its output.
/// See `lines_match` for supported patterns.
pub fn with_stdout_contains<S: ToString>(&mut self, expected: S) -> &mut Self {
self
}
- /// Verify that stderr contains the given contiguous lines somewhere in
+ /// Verifies that stderr contains the given contiguous lines somewhere in
/// its output.
/// See `lines_match` for supported patterns.
pub fn with_stderr_contains<S: ToString>(&mut self, expected: S) -> &mut Self {
self
}
- /// Verify that either stdout or stderr contains the given contiguous
+ /// Verifies that either stdout or stderr contains the given contiguous
/// lines somewhere in its output.
/// See `lines_match` for supported patterns.
pub fn with_either_contains<S: ToString>(&mut self, expected: S) -> &mut Self {
self
}
- /// Verify that stdout contains the given contiguous lines somewhere in
+ /// Verifies that stdout contains the given contiguous lines somewhere in
/// its output, and should be repeated `number` times.
/// See `lines_match` for supported patterns.
pub fn with_stdout_contains_n<S: ToString>(&mut self, expected: S, number: usize) -> &mut Self {
self
}
- /// Verify that stdout does not contain the given contiguous lines.
+ /// Verifies that stdout does not contain the given contiguous lines.
/// See `lines_match` for supported patterns.
/// See note on `with_stderr_does_not_contain`.
pub fn with_stdout_does_not_contain<S: ToString>(&mut self, expected: S) -> &mut Self {
self
}
- /// Verify that stderr does not contain the given contiguous lines.
+ /// Verifies that stderr does not contain the given contiguous lines.
/// See `lines_match` for supported patterns.
///
/// Care should be taken when using this method because there is a
- /// limitless number of possible things that *won't* appear. A typo means
+ /// limitless number of possible things that *won't* appear. A typo means
/// your test will pass without verifying the correct behavior. If
/// possible, write the test first so that it fails, and then implement
/// your fix/feature to make it pass.
self
}
- /// Verify that all of the stderr output is equal to the given lines,
+ /// Verifies that all of the stderr output is equal to the given lines,
/// ignoring the order of the lines.
/// See `lines_match` for supported patterns.
/// This is useful when checking the output of `cargo build -v` since
///
/// Be careful when using patterns such as `[..]`, because you may end up
/// with multiple lines that might match, and this is not smart enough to
- /// do anything like longest-match. For example, avoid something like:
+ /// do anything like longest-match. For example, avoid something like:
+ ///
/// [RUNNING] `rustc [..]
/// [RUNNING] `rustc --crate-name foo [..]
+ ///
/// This will randomly fail if the other crate name is `bar`, and the
/// order changes.
pub fn with_stderr_unordered<S: ToString>(&mut self, expected: S) -> &mut Self {
self
}
- /// Verify the JSON output matches the given JSON.
+ /// Verifies the JSON output matches the given JSON.
/// Typically used when testing cargo commands that emit JSON.
/// Each separate JSON object should be separated by a blank line.
/// Example:
self
}
- /// Verify JSON output contains the given objects (in any order) somewhere
+ /// Verifies JSON output contains the given objects (in any order) somewhere
/// in its output.
///
/// CAUTION: Be very careful when using this. Make sure every object is
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
Ok(actual) => actual,
};
- // Let's not deal with \r\n vs \n on windows...
+ // Let's not deal with `\r\n` vs `\n` on Windows.
let actual = actual.replace("\r", "");
let actual = actual.replace("\t", "<tab>");
Unordered,
}
-/// Compare a line with an expected pattern.
+/// Compares a line with an expected pattern.
/// - Use `[..]` as a wildcard to match 0 or more characters on the same line
/// (similar to `.*` in a regex).
/// - Use `[EXE]` to optionally add `.exe` on Windows (empty string on other
}
/// Compares JSON object for approximate equality.
-/// You can use `[..]` wildcard in strings (useful for OS dependent things such
-/// as paths). You can use a `"{...}"` string literal as a wildcard for
+/// You can use `[..]` wildcard in strings (useful for OS-dependent things such
+/// as paths). You can use a `"{...}"` string literal as a wildcard for
/// arbitrary nested JSON (useful for parts of object emitted by other programs
-/// (e.g. rustc) rather than Cargo itself). Arrays are sorted before comparison.
+/// (e.g., rustc) rather than Cargo itself). Arrays are sorted before comparison.
pub fn find_json_mismatch(expected: &Value, actual: &Value) -> Result<(), String> {
match find_json_mismatch_r(expected, &actual) {
Some((expected_part, actual_part)) => Err(format!(
.nth(0)
}
(&Null, &Null) => None,
- // magic string literal "{...}" acts as wildcard for any sub-JSON
+ // Magic string literal `"{...}"` acts as wildcard for any sub-JSON.
(&String(ref l), _) if l == "{...}" => None,
_ => Some((expected, actual)),
}
.env("HOME", paths::home())
.env("CARGO_HOME", paths::home().join(".cargo"))
.env("__CARGO_TEST_ROOT", paths::root())
- // Force cargo to think it's on the stable channel for all tests, this
+ // Force Cargo to think it's on the stable channel for all tests, this
// should hopefully not surprise us as we add cargo features over time and
// cargo rides the trains.
.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "stable")
::std::thread::sleep(Duration::from_millis(ms));
}
-/// Returns true if the local filesystem has low-resolution mtimes.
+/// Returns `true` if the local filesystem has low-resolution mtimes.
pub fn is_coarse_mtime() -> bool {
// If the filetime crate is being used to emulate HFS then
- // return true, without looking at the actual hardware.
+ // return `true`, without looking at the actual hardware.
cfg!(emulate_second_only_system) ||
- // This should actually be a test that $CARGO_TARGET_DIR is on an HFS
+ // This should actually be a test that `$CARGO_TARGET_DIR` is on an HFS
// filesystem, (or any filesystem with low-resolution mtimes). However,
// that's tricky to detect, so for now just deal with CI.
cfg!(target_os = "macos") && env::var("CI").is_ok()
use flate2::read::GzDecoder;
use tar::Archive;
-/// Check the result of a crate publish.
+/// Checks the result of a crate publish.
pub fn validate_upload(expected_json: &str, expected_crate_name: &str, expected_files: &[&str]) {
let new_path = registry::api_path().join("api/v1/crates/new");
_validate_upload(
);
}
-/// Check the result of a crate publish to an alternative registry.
+/// Checks the result of a crate publish to an alternative registry.
pub fn validate_alt_upload(
expected_json: &str,
expected_crate_name: &str,
let current = f.seek(SeekFrom::Current(0)).unwrap();
assert_eq!(f.seek(SeekFrom::End(0)).unwrap(), current);
- // Verify the tarball
+ // Verify the tarball.
validate_crate_contents(&krate_bytes[..], expected_crate_name, expected_files, &[]);
}
-/// Check the contents of a `.crate` file.
+/// Checks the contents of a `.crate` file.
///
/// - `expected_crate_name` should be something like `foo-0.0.1.crate`.
/// - `expected_files` should be a complete list of files in the crate
use crate::support::git::repo;
use crate::support::paths;
-/// Path to the local index pretending to be crates.io. This is a git repo
+/// Gets the path to the local index pretending to be crates.io. This is a Git repo
/// initialized with a `config.json` file pointing to `dl_path` for downloads
/// and `api_path` for uploads.
pub fn registry_path() -> PathBuf {
pub fn registry_url() -> Url {
Url::from_file_path(registry_path()).ok().unwrap()
}
-/// Path for local web API uploads. Cargo will place the contents of a web API
-/// request here, for example `api/v1/crates/new` is the result of publishing
-/// a crate.
+/// Gets the path for local web API uploads. Cargo will place the contents of a web API
+/// request here. For example, `api/v1/crates/new` is the result of publishing a crate.
pub fn api_path() -> PathBuf {
paths::root().join("api")
}
pub fn api_url() -> Url {
Url::from_file_path(api_path()).ok().unwrap()
}
-/// Path where crates can be downloaded using the web API endpoint. Crates
+/// Gets the path where crates can be downloaded using the web API endpoint. Crates
/// should be organized as `{name}/{version}/download` to match the web API
/// endpoint. This is rarely used and must be manually set up.
pub fn dl_path() -> PathBuf {
pub fn dl_url() -> Url {
Url::from_file_path(dl_path()).ok().unwrap()
}
-/// Alternative-registry version of `registry_path`.
+/// Gets the alternative-registry version of `registry_path`.
pub fn alt_registry_path() -> PathBuf {
paths::root().join("alternative-registry")
}
pub fn alt_registry_url() -> Url {
Url::from_file_path(alt_registry_path()).ok().unwrap()
}
-/// Alternative-registry version of `dl_path`.
+/// Gets the alternative-registry version of `dl_path`.
pub fn alt_dl_path() -> PathBuf {
paths::root().join("alt_dl")
}
let base = Url::from_file_path(alt_dl_path()).ok().unwrap();
format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base)
}
-/// Alternative-registry version of `api_path`.
+/// Gets the alternative-registry version of `api_path`.
pub fn alt_api_path() -> PathBuf {
paths::root().join("alt_api")
}
"#
));
- // Init a new registry
+ // Initialize a new registry.
let _ = repo(®istry_path())
.file(
"config.json",
.build();
fs::create_dir_all(api_path().join("api/v1/crates")).unwrap();
- // Init an alt registry
+ // Initialize an alternative registry.
repo(&alt_registry_path())
.file(
"config.json",
}
impl Package {
- /// Create a new package builder.
+ /// Creates a new package builder.
/// Call `publish()` to finalize and build the package.
pub fn new(name: &str, vers: &str) -> Package {
init();
self
}
- /// Add a file to the package.
+ /// Adds a file to the package.
pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
self.files.push((name.to_string(), contents.to_string()));
self
}
- /// Add an "extra" file that is not rooted within the package.
+ /// Adds an "extra" file that is not rooted within the package.
///
/// Normal files are automatically placed within a directory named
/// `$PACKAGE-$VERSION`. This allows you to override that behavior,
self
}
- /// Add a normal dependency. Example:
+ /// Adds a normal dependency. Example:
/// ```
/// [dependencies]
/// foo = {version = "1.0"}
self.add_dep(&Dependency::new(name, vers))
}
- /// Add a dependency with the given feature. Example:
+ /// Adds a dependency with the given feature. Example:
/// ```
/// [dependencies]
/// foo = {version = "1.0", "features": ["feat1", "feat2"]}
self.add_dep(Dependency::new(name, vers).enable_features(features))
}
- /// Add a platform-specific dependency. Example:
+ /// Adds a platform-specific dependency. Example:
/// ```
/// [target.'cfg(windows)'.dependencies]
/// foo = {version = "1.0"}
self.add_dep(Dependency::new(name, vers).target(target))
}
- /// Add a dependency to the alternative registry.
+ /// Adds a dependency to the alternative registry.
pub fn registry_dep(&mut self, name: &str, vers: &str) -> &mut Package {
self.add_dep(Dependency::new(name, vers).registry("alternative"))
}
- /// Add a dev-dependency. Example:
+ /// Adds a dev-dependency. Example:
/// ```
/// [dev-dependencies]
/// foo = {version = "1.0"}
self.add_dep(Dependency::new(name, vers).dev())
}
- /// Add a build-dependency. Example:
+ /// Adds a build-dependency. Example:
/// ```
/// [build-dependencies]
/// foo = {version = "1.0"}
self
}
- /// Specify whether or not the package is "yanked".
+ /// Specifies whether or not the package is "yanked".
pub fn yanked(&mut self, yanked: bool) -> &mut Package {
self.yanked = yanked;
self
}
- /// Add an entry in the `[features]` section
+ /// Adds an entry in the `[features]` section.
pub fn feature(&mut self, name: &str, deps: &[&str]) -> &mut Package {
let deps = deps.iter().map(|s| s.to_string()).collect();
self.features.insert(name.to_string(), deps);
self
}
- /// Create the package and place it in the registry.
+ /// Creates the package and place it in the registry.
///
/// This does not actually use Cargo's publishing system, but instead
/// manually creates the entry in the registry on the filesystem.
pub fn publish(&self) -> String {
self.make_archive();
- // Figure out what we're going to write into the index
+ // Figure out what we're going to write into the index.
let deps = self
.deps
.iter()
registry_path()
};
- // Write file/line in the index
+ // Write file/line in the index.
let dst = if self.local {
registry_path.join("index").join(&file)
} else {
t!(fs::create_dir_all(dst.parent().unwrap()));
t!(t!(File::create(&dst)).write_all((prev + &line[..] + "\n").as_bytes()));
- // Add the new file to the index
+ // Add the new file to the index.
if !self.local {
let repo = t!(git2::Repository::open(®istry_path));
let mut index = t!(repo.index());
t!(index.write());
let id = t!(index.write_tree());
- // Commit this change
+ // Commit this change.
let tree = t!(repo.find_tree(id));
let sig = t!(repo.signature());
let parent = t!(repo.refname_to_id("refs/heads/master"));
}
}
- /// Change this to `[build-dependencies]`
+ /// Changes this to `[build-dependencies]`.
pub fn build(&mut self) -> &mut Self {
self.kind = "build".to_string();
self
}
- /// Change this to `[dev-dependencies]`
+ /// Changes this to `[dev-dependencies]`.
pub fn dev(&mut self) -> &mut Self {
self.kind = "dev".to_string();
self
}
- /// Change this to `[target.$target.dependencies]`
+ /// Changes this to `[target.$target.dependencies]`.
pub fn target(&mut self, target: &str) -> &mut Self {
self.target = Some(target.to_string());
self
}
- /// Add `registry = $registry` to this dependency
+ /// Adds `registry = $registry` to this dependency.
pub fn registry(&mut self, registry: &str) -> &mut Self {
self.registry = Some(registry.to_string());
self
}
- /// Add `features = [ ... ]` to this dependency
+ /// Adds `features = [ ... ]` to this dependency.
pub fn enable_features(&mut self, features: &[&str]) -> &mut Self {
self.features.extend(features.iter().map(|s| s.to_string()));
self
}
- /// Add `package = ...` to this dependency
+ /// Adds `package = ...` to this dependency.
pub fn package(&mut self, pkg: &str) -> &mut Self {
self.package = Some(pkg.to_string());
self
}
- /// Change this to an optional dependency
+ /// Changes this to an optional dependency.
pub fn optional(&mut self, optional: bool) -> &mut Self {
self.optional = optional;
self
use std::fs::File;
use std::io::prelude::*;
+use cargo;
+
use crate::support::paths::CargoPathExt;
use crate::support::registry::Package;
use crate::support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, project};
use crate::support::{is_nightly, rustc_host, sleep_ms};
-use cargo;
#[test]
fn cargo_test_simple() {
#[test]
fn dylib_doctest2() {
- // can't doctest dylibs as they're statically linked together
+ // Can't doc-test dylibs, as they're statically linked together.
let p = project()
.file(
"Cargo.toml",
.run();
}
-/// This is a freshness test for feature use with workspaces
+/// This is a freshness test for feature use with workspaces.
///
-/// feat_lib is used by caller1 and caller2, but with different features enabled.
-/// This test ensures that alternating building caller1, caller2 doesn't force
-/// recompile of feat_lib.
+/// `feat_lib` is used by `caller1` and `caller2`, but with different features enabled.
+/// This test ensures that alternating building `caller1`, `caller2` doesn't force
+/// recompile of `feat_lib`.
///
-/// Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
-/// a single cargo build at the top level will be enough.
+/// Ideally, once we solve rust-lang/cargo#3620, then a single Cargo build at the top level
+/// will be enough.
#[test]
fn dep_used_with_separate_features() {
let p = project()
.file("caller2/src/lib.rs", "");
let p = p.build();
- // Build the entire workspace
+ // Build the entire workspace.
p.cargo("build --all")
.with_stderr(
"\
assert!(p.bin("caller1").is_file());
assert!(p.bin("caller2").is_file());
- // Build caller1. should build the dep library. Because the features
+ // Build `caller1`. Should build the dep library. Because the features
// are different than the full workspace, it rebuilds.
- // Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
- // a single cargo build at the top level will be enough.
+ // Ideally once we solve rust-lang/cargo#3620, then a single Cargo build at the top level
+ // will be enough.
p.cargo("build")
.cwd(p.root().join("caller1"))
.with_stderr(
)
.run();
- // Alternate building caller2/caller1 a few times, just to make sure
- // features are being built separately. Should not rebuild anything
+ // Alternate building `caller2`/`caller1` a few times, just to make sure
+ // features are being built separately. Should not rebuild anything.
p.cargo("build")
.cwd(p.root().join("caller2"))
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
}
-/*FIXME: This fails because of how workspace.exclude and workspace.members are working.
+// FIXME: this fails because of how workspace.exclude and workspace.members are working.
+/*
#[test]
fn include_and_exclude() {
let p = project()