diff -Nru cargo-0.62.0ubuntu0libgit2/benches/benchsuite/benches/resolve.rs cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/benches/resolve.rs --- cargo-0.62.0ubuntu0libgit2/benches/benchsuite/benches/resolve.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/benches/resolve.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,145 +1,12 @@ +use benchsuite::fixtures; use cargo::core::compiler::{CompileKind, RustcTargetData}; -use cargo::core::resolver::features::{CliFeatures, FeatureOpts, FeatureResolver, ForceAllTargets}; -use cargo::core::resolver::{HasDevUnits, ResolveBehavior}; +use cargo::core::resolver::features::{FeatureOpts, FeatureResolver}; +use cargo::core::resolver::{CliFeatures, ForceAllTargets, HasDevUnits, ResolveBehavior}; use cargo::core::{PackageIdSpec, Workspace}; use cargo::ops::WorkspaceResolve; use cargo::Config; use criterion::{criterion_group, criterion_main, Criterion}; -use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command; -use url::Url; - -// This is an arbitrary commit that existed when I started. This helps -// ensure consistent results. It can be updated if needed, but that can -// make it harder to compare results with older versions of cargo. -const CRATES_IO_COMMIT: &str = "85f7bfd61ea4fee08ec68c468762e886b2aebec6"; - -fn setup() { - create_home(); - create_target_dir(); - clone_index(); - unpack_workspaces(); -} - -fn root() -> PathBuf { - let mut p = PathBuf::from(env!("CARGO_TARGET_TMPDIR")); - p.push("bench"); - p -} - -fn target_dir() -> PathBuf { - let mut p = root(); - p.push("target"); - p -} - -fn cargo_home() -> PathBuf { - let mut p = root(); - p.push("chome"); - p -} - -fn index() -> PathBuf { - let mut p = root(); - p.push("index"); - p -} - -fn workspaces_path() -> PathBuf { - let mut p = root(); - p.push("workspaces"); - p -} - -fn registry_url() -> Url { - Url::from_file_path(index()).unwrap() -} - -fn create_home() { - let home = cargo_home(); - if !home.exists() { - fs::create_dir_all(&home).unwrap(); - } - fs::write( - home.join("config.toml"), - format!( - r#" - [source.crates-io] - replace-with = 'local-snapshot' - - [source.local-snapshot] - registry = '{}' - "#, - registry_url() - ), - ) - .unwrap(); -} - -fn create_target_dir() { - // This is necessary to ensure the .rustc_info.json file is written. - // Otherwise it won't be written, and it is very expensive to create. - if !target_dir().exists() { - std::fs::create_dir_all(target_dir()).unwrap(); - } -} - -/// This clones crates.io at a specific point in time into tmp/index. -fn clone_index() { - let index = index(); - let maybe_git = |command: &str| { - let status = Command::new("git") - .current_dir(&index) - .args(command.split_whitespace().collect::>()) - .status() - .expect("git should be installed"); - status.success() - }; - let git = |command: &str| { - if !maybe_git(command) { - panic!("failed to run git command: {}", command); - } - }; - if index.exists() { - if maybe_git(&format!( - "rev-parse -q --verify {}^{{commit}}", - CRATES_IO_COMMIT - )) { - // Already fetched. - return; - } - } else { - fs::create_dir_all(&index).unwrap(); - git("init --bare"); - git("remote add origin https://github.com/rust-lang/crates.io-index"); - } - git(&format!("fetch origin {}", CRATES_IO_COMMIT)); - git("branch -f master FETCH_HEAD"); -} - -/// This unpacks the compressed workspace skeletons into tmp/workspaces. -fn unpack_workspaces() { - let ws_dir = Path::new(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .join("workspaces"); - let archives = fs::read_dir(ws_dir) - .unwrap() - .map(|e| e.unwrap().path()) - .filter(|p| p.extension() == Some(std::ffi::OsStr::new("tgz"))); - for archive in archives { - let name = archive.file_stem().unwrap(); - let f = fs::File::open(&archive).unwrap(); - let f = flate2::read::GzDecoder::new(f); - let dest = workspaces_path().join(&name); - if dest.exists() { - fs::remove_dir_all(&dest).unwrap(); - } - let mut archive = tar::Archive::new(f); - archive.unpack(workspaces_path()).unwrap(); - } -} +use std::path::Path; struct ResolveInfo<'cfg> { ws: Workspace<'cfg>, @@ -152,36 +19,12 @@ ws_resolve: WorkspaceResolve<'cfg>, } -/// Vec of `(ws_name, ws_root)`. -fn workspaces() -> Vec<(String, PathBuf)> { - // CARGO_BENCH_WORKSPACES can be used to override, otherwise it just uses - // the workspaces in the workspaces directory. - let mut ps: Vec<_> = match std::env::var_os("CARGO_BENCH_WORKSPACES") { - Some(s) => std::env::split_paths(&s).collect(), - None => fs::read_dir(workspaces_path()) - .unwrap() - .map(|e| e.unwrap().path()) - // These currently fail in most cases on Windows due to long - // filenames in the git checkouts. - .filter(|p| { - !(cfg!(windows) - && matches!(p.file_name().unwrap().to_str().unwrap(), "servo" | "tikv")) - }) - .collect(), - }; - // Sort so it is consistent. - ps.sort(); - ps.into_iter() - .map(|p| (p.file_name().unwrap().to_str().unwrap().to_owned(), p)) - .collect() -} - /// Helper for resolving a workspace. This will run the resolver once to /// download everything, and returns all the data structures that are used /// during resolution. fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> { let requested_kinds = [CompileKind::Host]; - let ws = cargo::core::Workspace::new(&ws_root.join("Cargo.toml"), config).unwrap(); + let ws = Workspace::new(&ws_root.join("Cargo.toml"), config).unwrap(); let target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap(); let cli_features = CliFeatures::from_command_line(&[], false, true).unwrap(); let pkgs = cargo::ops::Packages::Default; @@ -212,38 +55,14 @@ } } -/// Creates a new Config. -/// -/// This is separate from `do_resolve` to deal with the ownership and lifetime. -fn make_config(ws_root: &Path) -> Config { - let shell = cargo::core::Shell::new(); - let mut config = cargo::util::Config::new(shell, ws_root.to_path_buf(), cargo_home()); - // Configure is needed to set the target_dir which is needed to write - // the .rustc_info.json file which is very expensive. - config - .configure( - 0, - false, - None, - false, - false, - false, - &Some(target_dir()), - &[], - &[], - ) - .unwrap(); - config -} - /// Benchmark of the full `resolve_ws_with_opts` which runs the resolver /// twice, the feature resolver, and more. This is a major component of a /// regular cargo build. fn resolve_ws(c: &mut Criterion) { - setup(); + let fixtures = fixtures!(); let mut group = c.benchmark_group("resolve_ws"); - for (ws_name, ws_root) in workspaces() { - let config = make_config(&ws_root); + for (ws_name, ws_root) in fixtures.workspaces() { + let config = fixtures.make_config(&ws_root); // The resolver info is initialized only once in a lazy fashion. This // allows criterion to skip this workspace if the user passes a filter // on the command-line (like `cargo bench -- resolve_ws/tikv`). @@ -282,10 +101,10 @@ /// Benchmark of the feature resolver. fn feature_resolver(c: &mut Criterion) { - setup(); + let fixtures = fixtures!(); let mut group = c.benchmark_group("feature_resolver"); - for (ws_name, ws_root) in workspaces() { - let config = make_config(&ws_root); + for (ws_name, ws_root) in fixtures.workspaces() { + let config = fixtures.make_config(&ws_root); let mut lazy_info = None; group.bench_function(&ws_name, |b| { let ResolveInfo { diff -Nru cargo-0.62.0ubuntu0libgit2/benches/benchsuite/benches/workspace_initialization.rs cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/benches/workspace_initialization.rs --- cargo-0.62.0ubuntu0libgit2/benches/benchsuite/benches/workspace_initialization.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/benches/workspace_initialization.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,27 @@ +use benchsuite::fixtures; +use cargo::core::Workspace; +use criterion::{criterion_group, criterion_main, Criterion}; + +fn workspace_initialization(c: &mut Criterion) { + let fixtures = fixtures!(); + let mut group = c.benchmark_group("workspace_initialization"); + for (ws_name, ws_root) in fixtures.workspaces() { + let config = fixtures.make_config(&ws_root); + // The resolver info is initialized only once in a lazy fashion. This + // allows criterion to skip this workspace if the user passes a filter + // on the command-line (like `cargo bench -- workspace_initialization/tikv`). + group.bench_function(ws_name, |b| { + b.iter(|| Workspace::new(&ws_root.join("Cargo.toml"), &config).unwrap()) + }); + } + group.finish(); +} + +// Criterion complains about the measurement time being too small, but the +// measurement time doesn't seem important to me, what is more important is +// the number of iterations which defaults to 100, which seems like a +// reasonable default. Otherwise, the measurement time would need to be +// changed per workspace. We wouldn't want to spend 60s on every workspace, +// that would take too long and isn't necessary for the smaller workspaces. +criterion_group!(benches, workspace_initialization); +criterion_main!(benches); diff -Nru cargo-0.62.0ubuntu0libgit2/benches/benchsuite/Cargo.toml cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/Cargo.toml --- cargo-0.62.0ubuntu0libgit2/benches/benchsuite/Cargo.toml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/Cargo.toml 2022-10-20 06:00:42.000000000 +0000 @@ -13,9 +13,16 @@ # Consider removing html_reports in 0.4 and switching to `cargo criterion`. criterion = { version = "0.3.5", features = ["html_reports"] } flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } -tar = { version = "0.4.35", default-features = false } +tar = { version = "0.4.38", default-features = false } url = "2.2.2" +[lib] +bench = false + [[bench]] name = "resolve" harness = false + +[[bench]] +name = "workspace_initialization" +harness = false diff -Nru cargo-0.62.0ubuntu0libgit2/benches/benchsuite/src/lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/src/lib.rs --- cargo-0.62.0ubuntu0libgit2/benches/benchsuite/src/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/benches/benchsuite/src/lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,197 @@ +use cargo::Config; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; +use url::Url; + +#[macro_export] +macro_rules! fixtures { + () => { + $crate::Fixtures::new(env!("CARGO_TARGET_TMPDIR")) + }; +} + +// This is an arbitrary commit that existed when I started. This helps +// ensure consistent results. It can be updated if needed, but that can +// make it harder to compare results with older versions of cargo. +const CRATES_IO_COMMIT: &str = "85f7bfd61ea4fee08ec68c468762e886b2aebec6"; + +pub struct Fixtures { + cargo_target_tmpdir: PathBuf, +} + +impl Fixtures { + pub fn new(cargo_target_tmpdir: &str) -> Self { + let bench = Self { + cargo_target_tmpdir: PathBuf::from(cargo_target_tmpdir), + }; + bench.create_home(); + bench.create_target_dir(); + bench.clone_index(); + bench.unpack_workspaces(); + bench + } + + fn root(&self) -> PathBuf { + self.cargo_target_tmpdir.join("bench") + } + + fn target_dir(&self) -> PathBuf { + let mut p = self.root(); + p.push("target"); + p + } + + fn cargo_home(&self) -> PathBuf { + let mut p = self.root(); + p.push("chome"); + p + } + + fn index(&self) -> PathBuf { + let mut p = self.root(); + p.push("index"); + p + } + + fn workspaces_path(&self) -> PathBuf { + let mut p = self.root(); + p.push("workspaces"); + p + } + + fn registry_url(&self) -> Url { + Url::from_file_path(self.index()).unwrap() + } + + fn create_home(&self) { + let home = self.cargo_home(); + if !home.exists() { + fs::create_dir_all(&home).unwrap(); + } + fs::write( + home.join("config.toml"), + format!( + r#" + [source.crates-io] + replace-with = 'local-snapshot' + + [source.local-snapshot] + registry = '{}' + "#, + self.registry_url() + ), + ) + .unwrap(); + } + + fn create_target_dir(&self) { + // This is necessary to ensure the .rustc_info.json file is written. + // Otherwise it won't be written, and it is very expensive to create. + if !self.target_dir().exists() { + fs::create_dir_all(self.target_dir()).unwrap(); + } + } + + /// This clones crates.io at a specific point in time into tmp/index. + fn clone_index(&self) { + let index = self.index(); + let maybe_git = |command: &str| { + let status = Command::new("git") + .current_dir(&index) + .args(command.split_whitespace().collect::>()) + .status() + .expect("git should be installed"); + status.success() + }; + let git = |command: &str| { + if !maybe_git(command) { + panic!("failed to run git command: {}", command); + } + }; + if index.exists() { + if maybe_git(&format!( + "rev-parse -q --verify {}^{{commit}}", + CRATES_IO_COMMIT + )) { + // Already fetched. + return; + } + } else { + fs::create_dir_all(&index).unwrap(); + git("init --bare"); + git("remote add origin https://github.com/rust-lang/crates.io-index"); + } + git(&format!("fetch origin {}", CRATES_IO_COMMIT)); + git("branch -f master FETCH_HEAD"); + } + + /// This unpacks the compressed workspace skeletons into tmp/workspaces. + fn unpack_workspaces(&self) { + let ws_dir = Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .join("workspaces"); + let archives = fs::read_dir(ws_dir) + .unwrap() + .map(|e| e.unwrap().path()) + .filter(|p| p.extension() == Some(std::ffi::OsStr::new("tgz"))); + for archive in archives { + let name = archive.file_stem().unwrap(); + let f = fs::File::open(&archive).unwrap(); + let f = flate2::read::GzDecoder::new(f); + let dest = self.workspaces_path().join(&name); + if dest.exists() { + fs::remove_dir_all(&dest).unwrap(); + } + let mut archive = tar::Archive::new(f); + archive.unpack(self.workspaces_path()).unwrap(); + } + } + + /// Vec of `(ws_name, ws_root)`. + pub fn workspaces(&self) -> Vec<(String, PathBuf)> { + // CARGO_BENCH_WORKSPACES can be used to override, otherwise it just uses + // the workspaces in the workspaces directory. + let mut ps: Vec<_> = match std::env::var_os("CARGO_BENCH_WORKSPACES") { + Some(s) => std::env::split_paths(&s).collect(), + None => fs::read_dir(self.workspaces_path()) + .unwrap() + .map(|e| e.unwrap().path()) + // These currently fail in most cases on Windows due to long + // filenames in the git checkouts. + .filter(|p| { + !(cfg!(windows) + && matches!(p.file_name().unwrap().to_str().unwrap(), "servo" | "tikv")) + }) + .collect(), + }; + // Sort so it is consistent. + ps.sort(); + ps.into_iter() + .map(|p| (p.file_name().unwrap().to_str().unwrap().to_owned(), p)) + .collect() + } + + /// Creates a new Config. + pub fn make_config(&self, ws_root: &Path) -> Config { + let shell = cargo::core::Shell::new(); + let mut config = Config::new(shell, ws_root.to_path_buf(), self.cargo_home()); + // Configure is needed to set the target_dir which is needed to write + // the .rustc_info.json file which is very expensive. + config + .configure( + 0, + false, + None, + false, + false, + false, + &Some(self.target_dir()), + &[], + &[], + ) + .unwrap(); + config + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/benches/capture/Cargo.toml cargo-0.66.0+ds0ubuntu0.libgit2/benches/capture/Cargo.toml --- cargo-0.62.0ubuntu0libgit2/benches/capture/Cargo.toml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/benches/capture/Cargo.toml 2022-10-20 06:00:42.000000000 +0000 @@ -8,5 +8,5 @@ [dependencies] cargo_metadata = "0.14.0" flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } -tar = { version = "0.4.35", default-features = false } -toml_edit = { version = "0.13.0", features = ["easy"] } +tar = { version = "0.4.38", default-features = false } +toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] } Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/cargo.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/cargo.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/diem.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/diem.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/empty.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/empty.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/gecko-dev.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/gecko-dev.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/rust.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/rust.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/rust-ws-inherit.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/rust-ws-inherit.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/servo.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/servo.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/substrate.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/substrate.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/tikv.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/tikv.tgz differ Binary files /tmp/tmp5td8pgn4/VEAbNEoehn/cargo-0.62.0ubuntu0libgit2/benches/workspaces/toml-rs.tgz and /tmp/tmp5td8pgn4/MgWIZk0OIT/cargo-0.66.0+ds0ubuntu0.libgit2/benches/workspaces/toml-rs.tgz differ diff -Nru cargo-0.62.0ubuntu0libgit2/build.rs cargo-0.66.0+ds0ubuntu0.libgit2/build.rs --- cargo-0.62.0ubuntu0libgit2/build.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/build.rs 2022-10-20 06:00:42.000000000 +0000 @@ -53,6 +53,7 @@ .arg("-1") .arg("--date=short") .arg("--format=%H %h %cd") + .arg("--abbrev=9") .output() { Ok(output) if output.status.success() => output, diff -Nru cargo-0.62.0ubuntu0libgit2/Cargo.toml cargo-0.66.0+ds0ubuntu0.libgit2/Cargo.toml --- cargo-0.62.0ubuntu0libgit2/Cargo.toml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/Cargo.toml 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,6 @@ [package] name = "cargo" -version = "0.62.0" +version = "0.66.0" edition = "2021" license = "MIT OR Apache-2.0" homepage = "https://crates.io" @@ -19,32 +19,33 @@ atty = "0.2" bytesize = "1.0" cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } -cargo-util = { path = "crates/cargo-util", version = "0.1.2" } +cargo-util = { path = "crates/cargo-util", version = "0.2.1" } crates-io = { path = "crates/crates-io", version = "0.34.0" } -crossbeam-utils = "0.8" -curl = { version = "0.4.41", features = ["http2"] } -curl-sys = "0.4.50" +curl = { version = "0.4.43", features = ["http2"] } +curl-sys = "0.4.55" env_logger = "0.9.0" pretty_env_logger = { version = "0.4", optional = true } anyhow = "1.0" filetime = "0.2.9" flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } -git2 = "0.14.2" -git2-curl = "0.15.0" +git2 = "0.15.0" +git2-curl = "0.16.0" glob = "0.3.0" hex = "0.4" home = "0.5" humantime = "2.0.0" +indexmap = "1" ignore = "0.4.7" lazy_static = "1.2.0" jobserver = "0.1.24" lazycell = "1.2.0" libc = "0.2" log = "0.4.6" -libgit2-sys = "0.13.2" +libgit2-sys = "0.14.0" memchr = "2.1.3" opener = "0.5" -os_info = "3.0.7" +os_info = "3.5.0" +pathdiff = "0.2" percent-encoding = "2.0" rustfix = "0.6.0" semver = { version = "1.0.3", features = ["serde"] } @@ -53,14 +54,14 @@ serde_json = { version = "1.0.30", features = ["raw_value"] } shell-escape = "0.1.4" strip-ansi-escapes = "0.1.0" -tar = { version = "0.4.36", default-features = false } +tar = { version = "0.4.38", default-features = false } tempfile = "3.0" termcolor = "1.1" -toml_edit = { version = "0.13.4", features = ["serde", "easy"] } +toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] } unicode-xid = "0.2.0" url = "2.2.2" walkdir = "2.2" -clap = "3.1.0" +clap = "3.2.18" unicode-width = "0.1.5" openssl = { version = '0.10.11', optional = true } im-rc = "15.0.0" @@ -98,10 +99,11 @@ [dev-dependencies] cargo-test-macro = { path = "crates/cargo-test-macro" } cargo-test-support = { path = "crates/cargo-test-support" } +snapbox = { version = "0.3.0", features = ["diff", "path"] } [build-dependencies] flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } -tar = { version = "0.4.26", default-features = false } +tar = { version = "0.4.38", default-features = false } [[bin]] name = "cargo" diff -Nru cargo-0.62.0ubuntu0libgit2/CHANGELOG.md cargo-0.66.0+ds0ubuntu0.libgit2/CHANGELOG.md --- cargo-0.62.0ubuntu0libgit2/CHANGELOG.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/CHANGELOG.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,7 +1,240 @@ # Changelog -## Cargo 1.61 (2022-04-07) -[ea2a21c9...HEAD](https://github.com/rust-lang/cargo/compare/ea2a21c9...HEAD) +## Cargo 1.65 (2022-11-03) +[4fd148c4...HEAD](https://github.com/rust-lang/cargo/compare/4fd148c4...HEAD) + +### Added + +### Changed + +- Cargo now uses the standard library's `available_parallelism` instead of the + `num_cpus` crate for determining the default parallelism. + [#10969](https://github.com/rust-lang/cargo/pull/10969) + +### Fixed + +### Nightly only + + +## Cargo 1.64 (2022-09-22) +[a5e08c47...rust-1.64.0](https://github.com/rust-lang/cargo/compare/a5e08c47...rust-1.64.0) + +### Added + +- 🎉 Packages can now inherit settings from the workspace so that the settings + can be centralized in one place. See + [`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacepackage-table) + and + [`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-workspacedependencies-table) + for more details on how to define these common settings. + [#10859](https://github.com/rust-lang/cargo/pull/10859) +- Added the + [`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type) + flag to `cargo rustc` to override the crate type. + [#10838](https://github.com/rust-lang/cargo/pull/10838) +- Cargo commands can now accept multiple `--target` flags to build for + multiple targets at once, and the + [`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget) + config option may now take an array of multiple targets. + [#10766](https://github.com/rust-lang/cargo/pull/10766) +- The `--jobs` argument can now take a negative number to count backwards from + the max CPUs. + [#10844](https://github.com/rust-lang/cargo/pull/10844) + +### Changed +- Bash completion of `cargo install --path` now supports path completion. + [#10798](https://github.com/rust-lang/cargo/pull/10798) +- Significantly improved the performance fetching git dependencies from GitHub + when using a hash in the `rev` field. + [#10079](https://github.com/rust-lang/cargo/pull/10079) +- Published packages will now include the resolver setting from the workspace + to ensure that they use the same resolver when used in isolation. + [#10911](https://github.com/rust-lang/cargo/pull/10911) + [#10961](https://github.com/rust-lang/cargo/pull/10961) + [#10970](https://github.com/rust-lang/cargo/pull/10970) +- `cargo add` will now update `Cargo.lock`. + [#10902](https://github.com/rust-lang/cargo/pull/10902) +- The path in the config output of `cargo vendor` now translates backslashes + to forward slashes so that the settings should work across platforms. + [#10668](https://github.com/rust-lang/cargo/pull/10668) +- The + [`workspace.default-members`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#package-selection) + setting now allows a value of `"."` in a non-virtual workspace to refer to + the root package. + [#10784](https://github.com/rust-lang/cargo/pull/10784) + +### Fixed +- The `os` output in `cargo --version --verbose` now supports more platforms. + [#10802](https://github.com/rust-lang/cargo/pull/10802) +- Cached git checkouts will now be rebuilt if they are corrupted. This may + happen when using `net.git-fetch-with-cli` and interrupting the clone + process. + [#10829](https://github.com/rust-lang/cargo/pull/10829) +- Fixed panic in `cargo add --offline`. + [#10817](https://github.com/rust-lang/cargo/pull/10817) + + +### Nightly only +- Fixed deserialization of unstable `check-cfg` in `config.toml`. + [#10799](https://github.com/rust-lang/cargo/pull/10799) + + +## Cargo 1.63 (2022-08-11) +[3f052d8e...rust-1.63.0](https://github.com/rust-lang/cargo/compare/3f052d8e...rust-1.63.0) + +### Added + +- 🎉 Added the `--config` CLI option to pass config options directly on the CLI. + [#10755](https://github.com/rust-lang/cargo/pull/10755) +- The `CARGO_PKG_RUST_VERSION` environment variable is now set when compiling + a crate if the manifest has the `rust-version` field set. + [#10713](https://github.com/rust-lang/cargo/pull/10713) + + +### Changed +- A warning is emitted when encountering multiple packages with the same name + in a git dependency. This will ignore packages with `publish=false`. + [#10701](https://github.com/rust-lang/cargo/pull/10701) + [#10767](https://github.com/rust-lang/cargo/pull/10767) +- Change tracking now uses the contents of a `.json` target spec file instead + of its path. This should help avoid rebuilds if the path changes. + [#10746](https://github.com/rust-lang/cargo/pull/10746) +- Git dependencies with a submodule configured with the `update=none` strategy + in `.gitmodules` is now honored, and the submodule will not be fetched. + [#10717](https://github.com/rust-lang/cargo/pull/10717) +- Crate files now use a more recent date (Jul 23, 2006 instead of Nov 29, 1973) + for deterministic behavior. + [#10720](https://github.com/rust-lang/cargo/pull/10720) +- The initial template used for `cargo new` now includes a slightly more + realistic test structure that has `use super::*;` in the test module. + [#10706](https://github.com/rust-lang/cargo/pull/10706) +- Updated the internal HTTP library libcurl with various small fixes and updates. + [#10696](https://github.com/rust-lang/cargo/pull/10696) + +### Fixed +- Fix zsh completions for `cargo add` and `cargo locate-project` + [#10810](https://github.com/rust-lang/cargo/pull/10810) + [#10811](https://github.com/rust-lang/cargo/pull/10811) +- Fixed `-p` being ignored with `cargo publish` in the root of a virtual + workspace. Some additional checks were also added to generate an error if + multiple packages were selected (previously it would pick the first one). + [#10677](https://github.com/rust-lang/cargo/pull/10677) +- The human-readable executable name is no longer displayed for `cargo test` + when using JSON output. + [#10691](https://github.com/rust-lang/cargo/pull/10691) + +### Nightly only + +- Added `-Zcheck-cfg=output` to support build-scripts declaring their + supported set of `cfg` values with `cargo:rustc-check-cfg`. + [#10539](https://github.com/rust-lang/cargo/pull/10539) +- `-Z http-registry` now uses https://index.crates.io/ when accessing crates-io. + [#10725](https://github.com/rust-lang/cargo/pull/10725) +- Fixed formatting of `.workspace` key in `cargo add` for workspace inheritance. + [#10705](https://github.com/rust-lang/cargo/pull/10705) +- Sparse HTTP registry URLs must now end with a `/`. + [#10698](https://github.com/rust-lang/cargo/pull/10698) +- Fixed issue with `cargo add` and workspace inheritance of the `default-features` key. + [#10685](https://github.com/rust-lang/cargo/pull/10685) + + + +## Cargo 1.62 (2022-06-30) +[1ef1e0a1...rust-1.62.0](https://github.com/rust-lang/cargo/compare/1ef1e0a1...rust-1.62.0) + +### Added + +- 🎉 Added the `cargo add` command for adding dependencies to `Cargo.toml` from + the command-line. + [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-add.html) + [#10472](https://github.com/rust-lang/cargo/pull/10472) + [#10577](https://github.com/rust-lang/cargo/pull/10577) + [#10578](https://github.com/rust-lang/cargo/pull/10578) +- Package ID specs now support `name@version` syntax in addition to the + previous `name:version` to align with the behavior in `cargo add` and other + tools. `cargo install` and `cargo yank` also now support this syntax so the + version does not need to passed as a separate flag. + [#10582](https://github.com/rust-lang/cargo/pull/10582) + [#10650](https://github.com/rust-lang/cargo/pull/10650) + [#10597](https://github.com/rust-lang/cargo/pull/10597) +- Added the CLI option `-F` as an alias of `--features`. + [#10576](https://github.com/rust-lang/cargo/pull/10576) +- The `git` and `registry` directories in Cargo's home directory (usually + `~/.cargo`) are now marked as cache directories so that they are not + included in backups or content indexing (on Windows). + [#10553](https://github.com/rust-lang/cargo/pull/10553) +- Added the `--version` flag to `cargo yank` to replace the `--vers` flag to + be consistent with `cargo install`. + [#10575](https://github.com/rust-lang/cargo/pull/10575) +- Added automatic `@` argfile support, which will use "response files" if the + command-line to `rustc` exceeds the operating system's limit. + [#10546](https://github.com/rust-lang/cargo/pull/10546) +- `cargo clean` now has a progress bar (if it takes longer than half a second). + [#10236](https://github.com/rust-lang/cargo/pull/10236) + +### Changed + +- `cargo install` no longer generates an error if no binaries were found + to install (such as missing required features). + [#10508](https://github.com/rust-lang/cargo/pull/10508) +- `cargo test` now passes `--target` to `rustdoc` if the specified target is + the same as the host target. + [#10594](https://github.com/rust-lang/cargo/pull/10594) +- `cargo doc` now automatically passes `-Arustdoc::private-intra-doc-links` + when documenting a binary (which automatically includes + `--document-private-items`). The + [`private-intra-doc-links`](https://doc.rust-lang.org/rustdoc/lints.html#private_intra_doc_links) + lint is only relevant when *not* documenting private items, which doesn't + apply to binaries. + [#10142](https://github.com/rust-lang/cargo/pull/10142) +- The length of the short git hash in the `cargo --version` output is now + fixed to 9 characters. Previously the length was inconsistent between + different platforms. + [#10579](https://github.com/rust-lang/cargo/pull/10579) +- Attempting to publish a package with a `Cargo.toml.orig` file will now + result in an error. The filename would otherwise conflict with the + automatically-generated file. + [#10551](https://github.com/rust-lang/cargo/pull/10551) + +### Fixed + +- The `build.dep-info-basedir` configuration setting now properly supports the + use of `..` in the path to refer to a parent directory. + [#10281](https://github.com/rust-lang/cargo/pull/10281) +- Fixed regression in automatic detection of the default number of CPUs to use + on systems using cgroups v1. + [#10737](https://github.com/rust-lang/cargo/pull/10737) + [#10739](https://github.com/rust-lang/cargo/pull/10739) + + +### Nightly only + +- `cargo fetch` now works with `-Zbuild-std` to fetch the standard library's dependencies. + [#10129](https://github.com/rust-lang/cargo/pull/10129) +- Added support for workspace inheritance. + [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#workspace-inheritance) + [#10584](https://github.com/rust-lang/cargo/pull/10584) + [#10568](https://github.com/rust-lang/cargo/pull/10568) + [#10565](https://github.com/rust-lang/cargo/pull/10565) + [#10564](https://github.com/rust-lang/cargo/pull/10564) + [#10563](https://github.com/rust-lang/cargo/pull/10563) + [#10606](https://github.com/rust-lang/cargo/pull/10606) + [#10548](https://github.com/rust-lang/cargo/pull/10548) + [#10538](https://github.com/rust-lang/cargo/pull/10538) +- Added `-Zcheck-cfg` which adds various forms of validating `cfg` expressions + for unknown names and values. + [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg) + [#10486](https://github.com/rust-lang/cargo/pull/10486) + [#10566](https://github.com/rust-lang/cargo/pull/10566) +- The `--config` CLI option no longer allows setting a registry token. + [#10580](https://github.com/rust-lang/cargo/pull/10580) +- Fixed issues with proc-macros and `-Z rustdoc-scrape-examples`. + [#10549](https://github.com/rust-lang/cargo/pull/10549) + [#10533](https://github.com/rust-lang/cargo/pull/10533) + + +## Cargo 1.61 (2022-05-19) +[ea2a21c9...rust-1.61.0](https://github.com/rust-lang/cargo/compare/ea2a21c9...rust-1.61.0) ### Added @@ -9,15 +242,57 @@ - `cargo test --no-run` will now display the path to the test executables. [#10346](https://github.com/rust-lang/cargo/pull/10346) +- `cargo tree --duplicates` no longer reports dependencies that are shared + between the host and the target as duplicates. + [#10466](https://github.com/rust-lang/cargo/pull/10466) +- Updated to the 1.4.2 release of libgit2 which brings in several fixes + [#10442](https://github.com/rust-lang/cargo/pull/10442) + [#10479](https://github.com/rust-lang/cargo/pull/10479) +- `cargo vendor` no longer allows multiple values for `--sync`, you must pass + multiple `--sync` flags instead. + [#10448](https://github.com/rust-lang/cargo/pull/10448) +- Warnings are now issued for manifest keys that have mixed both underscore + and dash variants (such as specifying both `proc_macro` and `proc-macro`) + [#10316](https://github.com/rust-lang/cargo/pull/10316) +- Cargo now uses the standard library's `available_parallelism` instead of the + `num_cpus` crate for determining the default parallelism. + [#10427](https://github.com/rust-lang/cargo/pull/10427) +- `cargo search` terms are now highlighted. + [#10425](https://github.com/rust-lang/cargo/pull/10425) ### Fixed +- Paths passed to VCS tools like `hg` are now added after `--` to avoid + conflict with VCS flags. + [#10483](https://github.com/rust-lang/cargo/pull/10483) +- Fixed the `http.timeout` configuration value to actually work. + [#10456](https://github.com/rust-lang/cargo/pull/10456) +- Fixed issues with `cargo rustc --crate-type` not working in some situations. + [#10388](https://github.com/rust-lang/cargo/pull/10388) + ### Nightly only - Added `-Z check-cfg-features` to enable compile-time checking of features [#10408](https://github.com/rust-lang/cargo/pull/10408) - Added `-Z bindeps` to support binary artifact dependencies (RFC-3028) [#9992](https://github.com/rust-lang/cargo/pull/9992) +- `-Z multitarget` is now supported in the `build.target` config value with an array. + [#10473](https://github.com/rust-lang/cargo/pull/10473) +- Added `--keep-going` flag which will continue compilation even if one crate + fails to compile. + [#10383](https://github.com/rust-lang/cargo/pull/10383) +- Start work on inheriting manifest values in a workspace. + [#10497](https://github.com/rust-lang/cargo/pull/10497) + [#10517](https://github.com/rust-lang/cargo/pull/10517) +- Added support for sparse HTTP registries. + [#10470](https://github.com/rust-lang/cargo/pull/10470) + [#10064](https://github.com/rust-lang/cargo/pull/10064) +- Fixed panic when artifact target is used for `[target.'cfg()'.dependencies]` + [#10433](https://github.com/rust-lang/cargo/pull/10433) +- Fixed host flags to pass to build scripts (`-Z target-applies-to-host`) + [#10395](https://github.com/rust-lang/cargo/pull/10395) +- Added `-Z check-cfg-features` support for rustdoc + [#10428](https://github.com/rust-lang/cargo/pull/10428) ## Cargo 1.60 (2022-04-07) @@ -89,6 +364,9 @@ - `cargo test TEST_FILTER` should no longer build binaries that are explicitly disabled with `test = false`. [#10305](https://github.com/rust-lang/cargo/pull/10305) +- Fixed regression with `term.verbose` without `term.quiet`, and vice versa. + [#10429](https://github.com/rust-lang/cargo/pull/10429) + [#10436](https://github.com/rust-lang/cargo/pull/10436) ### Nightly only @@ -96,6 +374,9 @@ [#10217](https://github.com/rust-lang/cargo/pull/10217) - Changed `--config` to only support dotted keys. [#10176](https://github.com/rust-lang/cargo/pull/10176) +- Fixed profile `rustflags` not being gated in profile overrides. + [#10411](https://github.com/rust-lang/cargo/pull/10411) + [#10413](https://github.com/rust-lang/cargo/pull/10413) ## Cargo 1.59 (2022-02-24) [7f08ace4...rust-1.59.0](https://github.com/rust-lang/cargo/compare/7f08ace4...rust-1.59.0) diff -Nru cargo-0.62.0ubuntu0libgit2/ci/dump-environment.sh cargo-0.66.0+ds0ubuntu0.libgit2/ci/dump-environment.sh --- cargo-0.62.0ubuntu0libgit2/ci/dump-environment.sh 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/ci/dump-environment.sh 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,13 @@ +#!/bin/bash +# This script dumps information about the build environment to stdout. + +set -euo pipefail +IFS=$'\n\t' + +echo "environment variables:" +printenv | sort +echo + +echo "disk usage:" +df -h +echo diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-macro/src/lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-macro/src/lib.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-macro/src/lib.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-macro/src/lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,20 +1,119 @@ extern crate proc_macro; use proc_macro::*; +use std::process::Command; +use std::sync::Once; #[proc_macro_attribute] pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream { + // Ideally these options would be embedded in the test itself. However, I + // find it very helpful to have the test clearly state whether or not it + // is ignored. It would be nice to have some kind of runtime ignore + // support (such as + // https://internals.rust-lang.org/t/pre-rfc-skippable-tests/14611). + // + // Unfortunately a big drawback here is that if the environment changes + // (such as the existence of the `git` CLI), this will not trigger a + // rebuild and the test will still be ignored. In theory, something like + // `tracked_env` or `tracked_path` + // (https://github.com/rust-lang/rust/issues/99515) could help with this, + // but they don't really handle the absence of files well. + let mut ignore = false; + let mut requires_reason = false; + let mut explicit_reason = None; + let mut implicit_reasons = Vec::new(); + macro_rules! set_ignore { + ($predicate:expr, $($arg:tt)*) => { + let p = $predicate; + ignore |= p; + if p { + implicit_reasons.push(std::fmt::format(format_args!($($arg)*))); + } + }; + } + let is_not_nightly = !version().1; + for rule in split_rules(attr) { + match rule.as_str() { + "build_std_real" => { + // Only run the "real" build-std tests on nightly and with an + // explicit opt-in (these generally only work on linux, and + // have some extra requirements, and are slow, and can pollute + // the environment since it downloads dependencies). + set_ignore!(is_not_nightly, "requires nightly"); + set_ignore!( + option_env!("CARGO_RUN_BUILD_STD_TESTS").is_none(), + "CARGO_RUN_BUILD_STD_TESTS must be set" + ); + } + "build_std_mock" => { + // Only run the "mock" build-std tests on nightly and disable + // for windows-gnu which is missing object files (see + // https://github.com/rust-lang/wg-cargo-std-aware/issues/46). + set_ignore!(is_not_nightly, "requires nightly"); + set_ignore!( + cfg!(all(target_os = "windows", target_env = "gnu")), + "does not work on windows-gnu" + ); + } + "nightly" => { + requires_reason = true; + set_ignore!(is_not_nightly, "requires nightly"); + } + s if s.starts_with("requires_") => { + let command = &s[9..]; + set_ignore!(!has_command(command), "{command} not installed"); + } + s if s.starts_with(">=1.") => { + requires_reason = true; + let min_minor = s[4..].parse().unwrap(); + let minor = version().0; + set_ignore!(minor < min_minor, "requires rustc 1.{minor} or newer"); + } + s if s.starts_with("reason=") => { + explicit_reason = Some(s[7..].parse().unwrap()); + } + _ => panic!("unknown rule {:?}", rule), + } + } + if requires_reason && explicit_reason.is_none() { + panic!( + "#[cargo_test] with a rule also requires a reason, \ + such as #[cargo_test(nightly, reason = \"needs -Z unstable-thing\")]" + ); + } + + // Construct the appropriate attributes. let span = Span::call_site(); let mut ret = TokenStream::new(); - ret.extend(Some(TokenTree::from(Punct::new('#', Spacing::Alone)))); - let test = TokenTree::from(Ident::new("test", span)); - ret.extend(Some(TokenTree::from(Group::new( - Delimiter::Bracket, - test.into(), - )))); - - let build_std = contains_ident(&attr, "build_std"); + let add_attr = |ret: &mut TokenStream, attr_name, attr_input| { + ret.extend(Some(TokenTree::from(Punct::new('#', Spacing::Alone)))); + let attr = TokenTree::from(Ident::new(attr_name, span)); + let mut attr_stream: TokenStream = attr.into(); + if let Some(input) = attr_input { + attr_stream.extend(input); + } + ret.extend(Some(TokenTree::from(Group::new( + Delimiter::Bracket, + attr_stream, + )))); + }; + add_attr(&mut ret, "test", None); + if ignore { + let reason = explicit_reason + .or_else(|| { + (!implicit_reasons.is_empty()) + .then(|| TokenTree::from(Literal::string(&implicit_reasons.join(", "))).into()) + }) + .map(|reason: TokenStream| { + let mut stream = TokenStream::new(); + stream.extend(Some(TokenTree::from(Punct::new('=', Spacing::Alone)))); + stream.extend(Some(reason)); + stream + }); + add_attr(&mut ret, "ignore", reason); + } + // Find where the function body starts, and add the boilerplate at the start. for token in item { let group = match token { TokenTree::Group(g) => { @@ -38,17 +137,6 @@ };"#, ); - // If this is a `build_std` test (aka `tests/build-std/*.rs`) then they - // only run on nightly and they only run when specifically instructed to - // on CI. - if build_std { - let ts = to_token_stream("if !cargo_test_support::is_nightly() { return }"); - new_body.extend(ts); - let ts = to_token_stream( - "if std::env::var(\"CARGO_RUN_BUILD_STD_TESTS\").is_err() { return }", - ); - new_body.extend(ts); - } new_body.extend(group.stream()); ret.extend(Some(TokenTree::from(Group::new( group.delimiter(), @@ -59,13 +147,79 @@ ret } -fn contains_ident(t: &TokenStream, ident: &str) -> bool { - t.clone().into_iter().any(|t| match t { - TokenTree::Ident(i) => i.to_string() == ident, +fn split_rules(t: TokenStream) -> Vec { + let tts: Vec<_> = t.into_iter().collect(); + tts.split(|tt| match tt { + TokenTree::Punct(p) => p.as_char() == ',', _ => false, }) + .filter(|parts| !parts.is_empty()) + .map(|parts| { + parts + .into_iter() + .map(|part| part.to_string()) + .collect::() + }) + .collect() } fn to_token_stream(code: &str) -> TokenStream { code.parse().unwrap() } + +static mut VERSION: (u32, bool) = (0, false); + +fn version() -> &'static (u32, bool) { + static INIT: Once = Once::new(); + INIT.call_once(|| { + let output = Command::new("rustc") + .arg("-V") + .output() + .expect("rustc should run"); + let stdout = std::str::from_utf8(&output.stdout).expect("utf8"); + let vers = stdout.split_whitespace().skip(1).next().unwrap(); + let is_nightly = option_env!("CARGO_TEST_DISABLE_NIGHTLY").is_none() + && (vers.contains("-nightly") || vers.contains("-dev")); + let minor = vers.split('.').skip(1).next().unwrap().parse().unwrap(); + unsafe { VERSION = (minor, is_nightly) } + }); + unsafe { &VERSION } +} + +fn has_command(command: &str) -> bool { + let output = match Command::new(command).arg("--version").output() { + Ok(output) => output, + Err(e) => { + // hg is not installed on GitHub macOS or certain constrained + // environments like Docker. Consider installing it if Cargo gains + // more hg support, but otherwise it isn't critical. + if is_ci() && command != "hg" { + panic!( + "expected command `{}` to be somewhere in PATH: {}", + command, e + ); + } + return false; + } + }; + if !output.status.success() { + panic!( + "expected command `{}` to be runnable, got error {}:\n\ + stderr:{}\n\ + stdout:{}\n", + command, + output.status, + String::from_utf8_lossy(&output.stderr), + String::from_utf8_lossy(&output.stdout) + ); + } + true +} + +/// Whether or not this running in a Continuous Integration environment. +fn is_ci() -> bool { + // Consider using `tracked_env` instead of option_env! when it is stabilized. + // `tracked_env` will handle changes, but not require rebuilding the macro + // itself like option_env does. + option_env!("CI").is_some() || option_env!("TF_BUILD").is_some() +} diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/Cargo.toml cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/Cargo.toml --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/Cargo.toml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/Cargo.toml 2022-10-20 06:00:42.000000000 +0000 @@ -11,18 +11,22 @@ anyhow = "1.0.34" cargo-test-macro = { path = "../cargo-test-macro" } cargo-util = { path = "../cargo-util" } +snapbox = { version = "0.3.0", features = ["diff", "path"] } filetime = "0.2" flate2 = { version = "1.0", default-features = false, features = ["zlib"] } -git2 = "0.14.2" +git2 = "0.15.0" glob = "0.3" itertools = "0.10.0" lazy_static = "1.0" remove_dir_all = "0.5" serde_json = "1.0" -tar = { version = "0.4.18", default-features = false } +tar = { version = "0.4.38", default-features = false } termcolor = "1.1.2" -toml_edit = { version = "0.13.0", features = ["serde", "easy"] } +toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] } url = "2.2.2" +[target.'cfg(windows)'.dependencies] +winapi = "0.3" + [features] deny-warnings = [] diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/compare.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/compare.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/compare.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/compare.rs 2022-10-20 06:00:42.000000000 +0000 @@ -41,6 +41,57 @@ use std::str; use url::Url; +/// Default `snapbox` Assertions +/// +/// # Snapshots +/// +/// Updating of snapshots is controlled with the `SNAPSHOTS` environment variable: +/// +/// - `skip`: do not run the tests +/// - `ignore`: run the tests but ignore their failure +/// - `verify`: run the tests +/// - `overwrite`: update the snapshots based on the output of the tests +/// +/// # Patterns +/// +/// - `[..]` is a character wildcard, stopping at line breaks +/// - `\n...\n` is a multi-line wildcard +/// - `[EXE]` matches the exe suffix for the current platform +/// - `[ROOT]` matches [`paths::root()`][crate::paths::root] +/// - `[ROOTURL]` matches [`paths::root()`][crate::paths::root] as a URL +/// +/// # Normalization +/// +/// In addition to the patterns described above, text is normalized +/// in such a way to avoid unwanted differences. The normalizations are: +/// +/// - Backslashes are converted to forward slashes to deal with Windows paths. +/// This helps so that all tests can be written assuming forward slashes. +/// Other heuristics are applied to try to ensure Windows-style paths aren't +/// a problem. +/// - Carriage returns are removed, which can help when running on Windows. +pub fn assert_ui() -> snapbox::Assert { + let root = paths::root(); + // Use `from_file_path` instead of `from_dir_path` so the trailing slash is + // put in the users output, rather than hidden in the variable + let root_url = url::Url::from_file_path(&root).unwrap().to_string(); + let root = root.display().to_string(); + + let mut subs = snapbox::Substitutions::new(); + subs.extend([ + ( + "[EXE]", + std::borrow::Cow::Borrowed(std::env::consts::EXE_SUFFIX), + ), + ("[ROOT]", std::borrow::Cow::Owned(root)), + ("[ROOTURL]", std::borrow::Cow::Owned(root_url)), + ]) + .unwrap(); + snapbox::Assert::new() + .action_env(snapbox::DEFAULT_ACTION_ENV) + .substitutions(subs) +} + /// Normalizes the output so that it can be compared against the expected value. fn normalize_actual(actual: &str, cwd: Option<&Path>) -> String { // It's easier to read tabs in outputs if they don't show up as literal @@ -145,6 +196,7 @@ ("[OWNER]", " Owner"), ("[MIGRATING]", " Migrating"), ("[EXECUTABLE]", " Executable"), + ("[SKIPPING]", " Skipping"), ]; let mut result = input.to_owned(); for &(pat, subst) in ¯os { diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/lib.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/lib.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -32,6 +32,26 @@ }; } +#[macro_export] +macro_rules! curr_dir { + () => { + $crate::_curr_dir(std::path::Path::new(file!())); + }; +} + +#[doc(hidden)] +pub fn _curr_dir(mut file_path: &'static Path) -> &'static Path { + if !file_path.exists() { + // HACK: Must be running in the rust-lang/rust workspace, adjust the paths accordingly. + let prefix = PathBuf::from("src").join("tools").join("cargo"); + if let Ok(crate_relative) = file_path.strip_prefix(prefix) { + file_path = crate_relative + } + } + assert!(file_path.exists(), "{} does not exist", file_path.display()); + file_path.parent().unwrap() +} + #[track_caller] pub fn panic_error(what: &str, err: impl Into) -> ! { let err = err.into(); @@ -59,6 +79,13 @@ pub mod registry; pub mod tools; +pub mod prelude { + pub use crate::ArgLine; + pub use crate::CargoCommand; + pub use crate::ChannelChanger; + pub use crate::TestEnv; +} + /* * * ===== Builders ===== @@ -156,10 +183,16 @@ } } +/// A cargo project to run tests against. +/// +/// See [`ProjectBuilder`] or [`Project::from_template`] to get started. pub struct Project { root: PathBuf, } +/// Create a project to run tests against +/// +/// The project can be constructed programmatically or from the filesystem with [`Project::from_template`] #[must_use] pub struct ProjectBuilder { root: Project, @@ -284,6 +317,14 @@ } impl Project { + /// Copy the test project from a fixed state + pub fn from_template(template_path: impl AsRef) -> Self { + let root = paths::root(); + let project_root = root.join("case"); + snapbox::path::copy_template(template_path.as_ref(), &project_root).unwrap(); + Self { root: project_root } + } + /// Root of the project, ex: `/path/to/cargo/target/cit/t0/foo` pub fn root(&self) -> PathBuf { self.root.clone() @@ -371,7 +412,7 @@ pub fn cargo(&self, cmd: &str) -> Execs { let mut execs = self.process(&cargo_exe()); if let Some(ref mut p) = execs.process_builder { - split_and_add_args(p, cmd); + p.arg_line(cmd); } execs } @@ -470,24 +511,8 @@ buf } -// Path to cargo executables -pub fn cargo_dir() -> PathBuf { - env::var_os("CARGO_BIN_PATH") - .map(PathBuf::from) - .or_else(|| { - env::current_exe().ok().map(|mut path| { - path.pop(); - if path.ends_with("deps") { - path.pop(); - } - path - }) - }) - .unwrap_or_else(|| panic!("CARGO_BIN_PATH wasn't set. Cannot continue running test")) -} - pub fn cargo_exe() -> PathBuf { - cargo_dir().join(format!("cargo{}", env::consts::EXE_SUFFIX)) + snapbox::cmd::cargo_bin("cargo") } /// This is the raw output from the process. @@ -544,6 +569,12 @@ self } + /// Writes the given lines to stdin. + pub fn with_stdin(&mut self, expected: S) -> &mut Self { + self.expect_stdin = Some(expected.to_string()); + self + } + /// Verifies the exit code from the process. /// /// This is not necessary if the expected exit code is `0`. @@ -775,9 +806,14 @@ p.build_command() } - pub fn masquerade_as_nightly_cargo(&mut self) -> &mut Self { + /// Enables nightly features for testing + /// + /// The list of reasons should be why nightly cargo is needed. If it is + /// becuase of an unstable feature put the name of the feature as the reason, + /// e.g. `&["print-im-a-teapot"]` + pub fn masquerade_as_nightly_cargo(&mut self, reasons: &[&str]) -> &mut Self { if let Some(ref mut p) = self.process_builder { - p.masquerade_as_nightly_cargo(); + p.masquerade_as_nightly_cargo(reasons); } self } @@ -795,7 +831,10 @@ #[track_caller] pub fn run(&mut self) { self.ran = true; - let p = (&self.process_builder).clone().unwrap(); + let mut p = (&self.process_builder).clone().unwrap(); + if let Some(stdin) = self.expect_stdin.take() { + p.stdin(stdin); + } if let Err(e) = self.match_process(&p) { panic_error(&format!("test failed running {}", p), e); } @@ -1089,6 +1128,10 @@ pub fn is_nightly() -> bool { let vv = &RUSTC_INFO.verbose_version; + // CARGO_TEST_DISABLE_NIGHTLY is set in rust-lang/rust's CI so that all + // nightly-only tests are disabled there. Otherwise, it could make it + // difficult to land changes which would need to be made simultaneously in + // rust-lang/cargo and rust-lan/rust, which isn't possible. env::var("CARGO_TEST_DISABLE_NIGHTLY").is_err() && (vv.contains("-nightly") || vv.contains("-dev")) } @@ -1099,110 +1142,189 @@ fn _process(t: &OsStr) -> ProcessBuilder { let mut p = ProcessBuilder::new(t); + p.cwd(&paths::root()).test_env(); + p +} - // In general just clear out all cargo-specific configuration already in the - // environment. Our tests all assume a "default configuration" unless - // specified otherwise. - for (k, _v) in env::vars() { - if k.starts_with("CARGO_") { - p.env_remove(&k); - } - } - if env::var_os("RUSTUP_TOOLCHAIN").is_some() { - // Override the PATH to avoid executing the rustup wrapper thousands - // of times. This makes the testsuite run substantially faster. - lazy_static::lazy_static! { - static ref RUSTC_DIR: PathBuf = { - match ProcessBuilder::new("rustup") - .args(&["which", "rustc"]) - .exec_with_output() - { - Ok(output) => { - let s = str::from_utf8(&output.stdout).expect("utf8").trim(); - let mut p = PathBuf::from(s); - p.pop(); - p - } - Err(e) => { - panic!("RUSTUP_TOOLCHAIN was set, but could not run rustup: {}", e); +/// Enable nightly features for testing +pub trait ChannelChanger { + /// The list of reasons should be why nightly cargo is needed. If it is + /// becuase of an unstable feature put the name of the feature as the reason, + /// e.g. `&["print-im-a-teapot"]`. + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self; +} + +impl ChannelChanger for &mut ProcessBuilder { + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self { + self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") + } +} + +impl ChannelChanger for snapbox::cmd::Command { + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self { + self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") + } +} + +/// Establish a process's test environment +pub trait TestEnv: Sized { + fn test_env(mut self) -> Self { + // In general just clear out all cargo-specific configuration already in the + // environment. Our tests all assume a "default configuration" unless + // specified otherwise. + for (k, _v) in env::vars() { + if k.starts_with("CARGO_") { + self = self.env_remove(&k); + } + } + if env::var_os("RUSTUP_TOOLCHAIN").is_some() { + // Override the PATH to avoid executing the rustup wrapper thousands + // of times. This makes the testsuite run substantially faster. + lazy_static::lazy_static! { + static ref RUSTC_DIR: PathBuf = { + match ProcessBuilder::new("rustup") + .args(&["which", "rustc"]) + .exec_with_output() + { + Ok(output) => { + let s = str::from_utf8(&output.stdout).expect("utf8").trim(); + let mut p = PathBuf::from(s); + p.pop(); + p + } + Err(e) => { + panic!("RUSTUP_TOOLCHAIN was set, but could not run rustup: {}", e); + } } - } - }; + }; + } + let path = env::var_os("PATH").unwrap_or_default(); + let paths = env::split_paths(&path); + let new_path = + env::join_paths(std::iter::once(RUSTC_DIR.clone()).chain(paths)).unwrap(); + self = self.env("PATH", new_path); + } + + self = self + .current_dir(&paths::root()) + .env("HOME", paths::home()) + .env("CARGO_HOME", paths::home().join(".cargo")) + .env("__CARGO_TEST_ROOT", paths::global_root()) + // 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") + // For now disable incremental by default as support hasn't ridden to the + // stable channel yet. Once incremental support hits the stable compiler we + // can switch this to one and then fix the tests. + .env("CARGO_INCREMENTAL", "0") + .env_remove("__CARGO_DEFAULT_LIB_METADATA") + .env_remove("RUSTC") + .env_remove("RUSTDOC") + .env_remove("RUSTC_WRAPPER") + .env_remove("RUSTFLAGS") + .env_remove("RUSTDOCFLAGS") + .env_remove("XDG_CONFIG_HOME") // see #2345 + .env("GIT_CONFIG_NOSYSTEM", "1") // keep trying to sandbox ourselves + .env_remove("EMAIL") + .env_remove("USER") // not set on some rust-lang docker images + .env_remove("MFLAGS") + .env_remove("MAKEFLAGS") + .env_remove("GIT_AUTHOR_NAME") + .env_remove("GIT_AUTHOR_EMAIL") + .env_remove("GIT_COMMITTER_NAME") + .env_remove("GIT_COMMITTER_EMAIL") + .env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows + if cfg!(target_os = "macos") { + // Work-around a bug in macOS 10.15, see `link_or_copy` for details. + self = self.env("__CARGO_COPY_DONT_LINK_DO_NOT_USE_THIS", "1"); } - let path = env::var_os("PATH").unwrap_or_default(); - let paths = env::split_paths(&path); - let new_path = env::join_paths(std::iter::once(RUSTC_DIR.clone()).chain(paths)).unwrap(); - p.env("PATH", new_path); - } - - p.cwd(&paths::root()) - .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 - // 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") - // For now disable incremental by default as support hasn't ridden to the - // stable channel yet. Once incremental support hits the stable compiler we - // can switch this to one and then fix the tests. - .env("CARGO_INCREMENTAL", "0") - .env_remove("__CARGO_DEFAULT_LIB_METADATA") - .env_remove("RUSTC") - .env_remove("RUSTDOC") - .env_remove("RUSTC_WRAPPER") - .env_remove("RUSTFLAGS") - .env_remove("RUSTDOCFLAGS") - .env_remove("XDG_CONFIG_HOME") // see #2345 - .env("GIT_CONFIG_NOSYSTEM", "1") // keep trying to sandbox ourselves - .env_remove("EMAIL") - .env_remove("USER") // not set on some rust-lang docker images - .env_remove("MFLAGS") - .env_remove("MAKEFLAGS") - .env_remove("GIT_AUTHOR_NAME") - .env_remove("GIT_AUTHOR_EMAIL") - .env_remove("GIT_COMMITTER_NAME") - .env_remove("GIT_COMMITTER_EMAIL") - .env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows - if cfg!(target_os = "macos") { - // Work-around a bug in macOS 10.15, see `link_or_copy` for details. - p.env("__CARGO_COPY_DONT_LINK_DO_NOT_USE_THIS", "1"); + self } - p + + fn current_dir>(self, path: S) -> Self; + fn env>(self, key: &str, value: S) -> Self; + fn env_remove(self, key: &str) -> Self; } -pub trait ChannelChanger: Sized { - fn masquerade_as_nightly_cargo(&mut self) -> &mut Self; +impl TestEnv for &mut ProcessBuilder { + fn current_dir>(self, path: S) -> Self { + let path = path.as_ref(); + self.cwd(path) + } + fn env>(self, key: &str, value: S) -> Self { + self.env(key, value) + } + fn env_remove(self, key: &str) -> Self { + self.env_remove(key) + } } -impl ChannelChanger for ProcessBuilder { - fn masquerade_as_nightly_cargo(&mut self) -> &mut Self { - self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") +impl TestEnv for snapbox::cmd::Command { + fn current_dir>(self, path: S) -> Self { + self.current_dir(path) + } + fn env>(self, key: &str, value: S) -> Self { + self.env(key, value) + } + fn env_remove(self, key: &str) -> Self { + self.env_remove(key) } } -fn split_and_add_args(p: &mut ProcessBuilder, s: &str) { - for mut arg in s.split_whitespace() { - if (arg.starts_with('"') && arg.ends_with('"')) - || (arg.starts_with('\'') && arg.ends_with('\'')) - { - arg = &arg[1..(arg.len() - 1).max(1)]; - } else if arg.contains(&['"', '\''][..]) { - panic!("shell-style argument parsing is not supported") +/// Test the cargo command +pub trait CargoCommand { + fn cargo_ui() -> Self; +} + +impl CargoCommand for snapbox::cmd::Command { + fn cargo_ui() -> Self { + Self::new(cargo_exe()) + .with_assert(compare::assert_ui()) + .test_env() + } +} + +/// Add a list of arguments as a line +pub trait ArgLine: Sized { + fn arg_line(mut self, s: &str) -> Self { + for mut arg in s.split_whitespace() { + if (arg.starts_with('"') && arg.ends_with('"')) + || (arg.starts_with('\'') && arg.ends_with('\'')) + { + arg = &arg[1..(arg.len() - 1).max(1)]; + } else if arg.contains(&['"', '\''][..]) { + panic!("shell-style argument parsing is not supported") + } + self = self.arg(arg); } - p.arg(arg); + self + } + + fn arg>(self, s: S) -> Self; +} + +impl ArgLine for &mut ProcessBuilder { + fn arg>(self, s: S) -> Self { + self.arg(s) + } +} + +impl ArgLine for snapbox::cmd::Command { + fn arg>(self, s: S) -> Self { + self.arg(s) } } pub fn cargo_process(s: &str) -> Execs { let mut p = process(&cargo_exe()); - split_and_add_args(&mut p, s); + p.arg_line(s); execs().with_process_builder(p) } pub fn git_process(s: &str) -> ProcessBuilder { let mut p = process("git"); - split_and_add_args(&mut p, s); + p.arg_line(s); p } @@ -1232,16 +1354,6 @@ Duration::from_secs(*SLOW_CPU_MULTIPLIER * main) } -pub fn command_is_available(cmd: &str) -> bool { - if let Err(e) = process(cmd).arg("-V").exec_with_output() { - eprintln!("{} not available, skipping tests", cmd); - eprintln!("{:?}", e); - false - } else { - true - } -} - #[cfg(windows)] pub fn symlink_supported() -> bool { if is_ci() { diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/paths.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/paths.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/paths.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/paths.rs 2022-10-20 06:00:42.000000000 +0000 @@ -287,3 +287,61 @@ let sysroot = String::from_utf8(output.stdout).unwrap(); sysroot.trim().to_string() } + +/// Returns true if names such as aux.* are allowed. +/// +/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved` +/// for a list). More recent versions of Windows have relaxed this restriction. This test +/// determines whether we are running in a mode that allows Windows reserved names. +#[cfg(windows)] +pub fn windows_reserved_names_are_allowed() -> bool { + use cargo_util::is_ci; + + // Ensure tests still run in CI until we need to migrate. + if is_ci() { + return false; + } + + use std::ffi::OsStr; + use std::os::windows::ffi::OsStrExt; + use std::ptr; + use winapi::um::fileapi::GetFullPathNameW; + + let test_file_name: Vec<_> = OsStr::new("aux.rs").encode_wide().collect(); + + let buffer_length = + unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) }; + + if buffer_length == 0 { + // This means the call failed, so we'll conservatively assume reserved names are not allowed. + return false; + } + + let mut buffer = vec![0u16; buffer_length as usize]; + + let result = unsafe { + GetFullPathNameW( + test_file_name.as_ptr(), + buffer_length, + buffer.as_mut_ptr(), + ptr::null_mut(), + ) + }; + + if result == 0 { + // Once again, conservatively assume reserved names are not allowed if the + // GetFullPathNameW call failed. + return false; + } + + // Under the old rules, a file name like aux.rs would get converted into \\.\aux, so + // we detect this case by checking if the string starts with \\.\ + // + // Otherwise, the filename will be something like C:\Users\Foo\Documents\aux.rs + let prefix: Vec<_> = OsStr::new("\\\\.\\").encode_wide().collect(); + if buffer.starts_with(&prefix) { + false + } else { + true + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/registry.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/registry.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/registry.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/registry.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,16 +1,14 @@ use crate::git::repo; use crate::paths; +use cargo_util::paths::append; use cargo_util::{registry::make_dep_path, Sha256}; use flate2::write::GzEncoder; use flate2::Compression; -use std::collections::BTreeMap; -use std::fmt::Write as _; +use std::collections::{BTreeMap, HashMap}; use std::fs::{self, File}; use std::io::{BufRead, BufReader, Write}; -use std::net::{SocketAddr, TcpListener}; +use std::net::{SocketAddr, TcpListener, TcpStream}; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; use std::thread; use tar::{Builder, Header}; use url::Url; @@ -21,228 +19,292 @@ pub fn registry_path() -> PathBuf { generate_path("registry") } -pub fn registry_url() -> Url { - generate_url("registry") -} /// 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 { generate_path("api") } -pub fn api_url() -> Url { - generate_url("api") -} /// 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 { +fn dl_path() -> PathBuf { generate_path("dl") } -pub fn dl_url() -> Url { - generate_url("dl") -} /// Gets the alternative-registry version of `registry_path`. -pub fn alt_registry_path() -> PathBuf { +fn alt_registry_path() -> PathBuf { generate_path("alternative-registry") } -pub fn alt_registry_url() -> Url { +/// Gets the alternative-registry version of `registry_url`. +fn alt_registry_url() -> Url { generate_url("alternative-registry") } /// Gets the alternative-registry version of `dl_path`. pub fn alt_dl_path() -> PathBuf { - generate_path("alt_dl") -} -pub fn alt_dl_url() -> String { - generate_alt_dl_url("alt_dl") + generate_path("alternative-dl") } /// Gets the alternative-registry version of `api_path`. pub fn alt_api_path() -> PathBuf { - generate_path("alt_api") -} -pub fn alt_api_url() -> Url { - generate_url("alt_api") + generate_path("alternative-api") } - -pub fn generate_path(name: &str) -> PathBuf { +fn generate_path(name: &str) -> PathBuf { paths::root().join(name) } -pub fn generate_url(name: &str) -> Url { +fn generate_url(name: &str) -> Url { Url::from_file_path(generate_path(name)).ok().unwrap() } -pub fn generate_alt_dl_url(name: &str) -> String { - let base = Url::from_file_path(generate_path(name)).ok().unwrap(); - format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base) -} /// A builder for initializing registries. pub struct RegistryBuilder { - /// If `true`, adds source replacement for crates.io to a registry on the filesystem. - replace_crates_io: bool, - /// If `true`, configures a registry named "alternative". - alternative: bool, - /// If set, sets the API url for the "alternative" registry. - /// This defaults to a directory on the filesystem. - alt_api_url: Option, - /// If `true`, configures `.cargo/credentials` with some tokens. - add_tokens: bool, + /// If set, configures an alternate registry with the given name. + alternative: Option, + /// If set, the authorization token for the registry. + token: Option, + /// If set, serves the index over http. + http_index: bool, + /// If set, serves the API over http. + http_api: bool, + /// If set, config.json includes 'api' + api: bool, + /// Write the token in the configuration. + configure_token: bool, + /// Write the registry in configuration. + configure_registry: bool, + /// API responders. + custom_responders: HashMap<&'static str, Box Response>>, +} + +pub struct TestRegistry { + _server: Option, + index_url: Url, + path: PathBuf, + api_url: Url, + dl_url: Url, + token: Option, +} + +impl TestRegistry { + pub fn index_url(&self) -> &Url { + &self.index_url + } + + pub fn api_url(&self) -> &Url { + &self.api_url + } + + pub fn token(&self) -> &str { + self.token + .as_deref() + .expect("registry was not configured with a token") + } } impl RegistryBuilder { + #[must_use] pub fn new() -> RegistryBuilder { RegistryBuilder { - replace_crates_io: true, - alternative: false, - alt_api_url: None, - add_tokens: true, + alternative: None, + token: Some("api-token".to_string()), + http_api: false, + http_index: false, + api: true, + configure_registry: true, + configure_token: true, + custom_responders: HashMap::new(), } } - /// Sets whether or not to replace crates.io with a registry on the filesystem. - /// Default is `true`. - pub fn replace_crates_io(&mut self, replace: bool) -> &mut Self { - self.replace_crates_io = replace; + /// Adds a custom HTTP response for a specific url + #[must_use] + pub fn add_responder Response>( + mut self, + url: &'static str, + responder: R, + ) -> Self { + self.custom_responders.insert(url, Box::new(responder)); + self + } + + /// Sets whether or not to initialize as an alternative registry. + #[must_use] + pub fn alternative_named(mut self, alt: &str) -> Self { + self.alternative = Some(alt.to_string()); + self + } + + /// Sets whether or not to initialize as an alternative registry. + #[must_use] + pub fn alternative(self) -> Self { + self.alternative_named("alternative") + } + + /// Prevents placing a token in the configuration + #[must_use] + pub fn no_configure_token(mut self) -> Self { + self.configure_token = false; self } - /// Sets whether or not to initialize an alternative registry named "alternative". - /// Default is `false`. - pub fn alternative(&mut self, alt: bool) -> &mut Self { - self.alternative = alt; + /// Prevents adding the registry to the configuration. + #[must_use] + pub fn no_configure_registry(mut self) -> Self { + self.configure_registry = false; self } - /// Sets the API url for the "alternative" registry. - /// Defaults to a path on the filesystem ([`alt_api_path`]). - pub fn alternative_api_url(&mut self, url: &str) -> &mut Self { - self.alternative = true; - self.alt_api_url = Some(url.to_string()); + /// Sets the token value + #[must_use] + pub fn token(mut self, token: &str) -> Self { + self.token = Some(token.to_string()); self } - /// Sets whether or not to initialize `.cargo/credentials` with some tokens. - /// Defaults to `true`. - pub fn add_tokens(&mut self, add: bool) -> &mut Self { - self.add_tokens = add; + /// Operate the index over http + #[must_use] + pub fn http_index(mut self) -> Self { + self.http_index = true; self } - /// Initializes the registries. - pub fn build(&self) { + /// Operate the api over http + #[must_use] + pub fn http_api(mut self) -> Self { + self.http_api = true; + self + } + + /// The registry has no api. + #[must_use] + pub fn no_api(mut self) -> Self { + self.api = false; + self + } + + /// Initializes the registry. + #[must_use] + pub fn build(self) -> TestRegistry { let config_path = paths::home().join(".cargo/config"); - if config_path.exists() { - panic!( - "{} already exists, the registry may only be initialized once, \ - and must be done before the config file is created", - config_path.display() - ); - } t!(fs::create_dir_all(config_path.parent().unwrap())); - let mut config = String::new(); - if self.replace_crates_io { - write!( - &mut config, - " + let prefix = if let Some(alternative) = &self.alternative { + format!("{alternative}-") + } else { + String::new() + }; + let registry_path = generate_path(&format!("{prefix}registry")); + let index_url = generate_url(&format!("{prefix}registry")); + let api_url = generate_url(&format!("{prefix}api")); + let dl_url = generate_url(&format!("{prefix}dl")); + let dl_path = generate_path(&format!("{prefix}dl")); + let api_path = generate_path(&format!("{prefix}api")); + + let (server, index_url, api_url, dl_url) = if !self.http_index && !self.http_api { + // No need to start the HTTP server. + (None, index_url, api_url, dl_url) + } else { + let server = HttpServer::new( + registry_path.clone(), + dl_path, + self.token.clone(), + self.custom_responders, + ); + let index_url = if self.http_index { + server.index_url() + } else { + index_url + }; + let api_url = if self.http_api { + server.api_url() + } else { + api_url + }; + let dl_url = server.dl_url(); + (Some(server), index_url, api_url, dl_url) + }; + + let registry = TestRegistry { + api_url, + index_url, + _server: server, + dl_url, + path: registry_path, + token: self.token, + }; + + if self.configure_registry { + if let Some(alternative) = &self.alternative { + append( + &config_path, + format!( + " + [registries.{alternative}] + index = '{}'", + registry.index_url + ) + .as_bytes(), + ) + .unwrap(); + } else { + append( + &config_path, + format!( + " [source.crates-io] replace-with = 'dummy-registry' [source.dummy-registry] - registry = '{}' - ", - registry_url() - ) - .unwrap(); - } - if self.alternative { - write!( - config, - " - [registries.alternative] - index = '{}' - ", - alt_registry_url() - ) - .unwrap(); + registry = '{}'", + registry.index_url + ) + .as_bytes(), + ) + .unwrap(); + } } - t!(fs::write(&config_path, config)); - if self.add_tokens { + if self.configure_token { + let token = registry.token.as_deref().unwrap(); let credentials = paths::home().join(".cargo/credentials"); - t!(fs::write( - &credentials, - r#" + if let Some(alternative) = &self.alternative { + append( + &credentials, + format!( + r#" + [registries.{alternative}] + token = "{token}" + "# + ) + .as_bytes(), + ) + .unwrap(); + } else { + append( + &credentials, + format!( + r#" [registry] - token = "api-token" - - [registries.alternative] - token = "api-token" + token = "{token}" "# - )); - } - - if self.replace_crates_io { - init_registry(registry_path(), dl_url().into(), api_url(), api_path()); - } - - if self.alternative { - init_registry( - alt_registry_path(), - alt_dl_url(), - self.alt_api_url - .as_ref() - .map_or_else(alt_api_url, |url| Url::parse(url).expect("valid url")), - alt_api_path(), - ); + ) + .as_bytes(), + ) + .unwrap(); + } } - } - - /// Initializes the registries, and sets up an HTTP server for the - /// "alternative" registry. - /// - /// The given callback takes a `Vec` of headers when a request comes in. - /// The first entry should be the HTTP command, such as - /// `PUT /api/v1/crates/new HTTP/1.1`. - /// - /// The callback should return the HTTP code for the response, and the - /// response body. - /// - /// This method returns a `JoinHandle` which you should call - /// `.join().unwrap()` on before exiting the test. - pub fn build_api_server<'a>( - &mut self, - handler: &'static (dyn (Fn(Vec) -> (u32, &'a dyn AsRef<[u8]>)) + Sync), - ) -> thread::JoinHandle<()> { - let server = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = server.local_addr().unwrap(); - let api_url = format!("http://{}", addr); - self.replace_crates_io(false) - .alternative_api_url(&api_url) - .build(); - - let t = thread::spawn(move || { - let mut conn = BufReader::new(server.accept().unwrap().0); - let headers: Vec<_> = (&mut conn) - .lines() - .map(|s| s.unwrap()) - .take_while(|s| s.len() > 2) - .map(|s| s.trim().to_string()) - .collect(); - let (code, response) = handler(headers); - let response = response.as_ref(); - let stream = conn.get_mut(); - write!( - stream, - "HTTP/1.1 {}\r\n\ - Content-Length: {}\r\n\ - \r\n", - code, - response.len() + let api = if self.api { + format!(r#","api":"{}""#, registry.api_url) + } else { + String::new() + }; + // Initialize a new registry. + repo(®istry.path) + .file( + "config.json", + &format!(r#"{{"dl":"{}"{api}}}"#, registry.dl_url), ) - .unwrap(); - stream.write_all(response).unwrap(); - }); + .build(); + fs::create_dir_all(api_path.join("api/v1/crates")).unwrap(); - t + registry } } @@ -357,195 +419,318 @@ /// Initializes the on-disk registry and sets up the config so that crates.io /// is replaced with the one on disk. -pub fn init() { - let config = paths::home().join(".cargo/config"); - if config.exists() { - return; - } - RegistryBuilder::new().build(); +pub fn init() -> TestRegistry { + RegistryBuilder::new().build() } -/// Variant of `init` that initializes the "alternative" registry. -pub fn alt_init() { - RegistryBuilder::new().alternative(true).build(); +/// Variant of `init` that initializes the "alternative" registry and crates.io +/// replacement. +pub fn alt_init() -> TestRegistry { + init(); + RegistryBuilder::new().alternative().build() } -pub struct RegistryServer { - done: Arc, - server: Option>, +pub struct HttpServerHandle { addr: SocketAddr, } -impl RegistryServer { - pub fn addr(&self) -> SocketAddr { - self.addr +impl HttpServerHandle { + pub fn index_url(&self) -> Url { + Url::parse(&format!("sparse+http://{}/index/", self.addr.to_string())).unwrap() + } + + pub fn api_url(&self) -> Url { + Url::parse(&format!("http://{}/", self.addr.to_string())).unwrap() + } + + pub fn dl_url(&self) -> Url { + Url::parse(&format!("http://{}/dl", self.addr.to_string())).unwrap() } } -impl Drop for RegistryServer { +impl Drop for HttpServerHandle { fn drop(&mut self) { - self.done.store(true, Ordering::SeqCst); - // NOTE: we can't actually await the server since it's blocked in accept() - let _ = self.server.take(); + if let Ok(mut stream) = TcpStream::connect(self.addr) { + // shutdown the server + let _ = stream.write_all(b"stop"); + let _ = stream.flush(); + } } } -#[must_use] -pub fn serve_registry(registry_path: PathBuf) -> RegistryServer { - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let addr = listener.local_addr().unwrap(); - let done = Arc::new(AtomicBool::new(false)); - let done2 = done.clone(); +/// Request to the test http server +#[derive(Debug)] +pub struct Request { + pub url: Url, + pub method: String, + pub authorization: Option, + pub if_modified_since: Option, + pub if_none_match: Option, +} + +/// Response from the test http server +pub struct Response { + pub code: u32, + pub headers: Vec, + pub body: Vec, +} + +struct HttpServer { + listener: TcpListener, + registry_path: PathBuf, + dl_path: PathBuf, + token: Option, + custom_responders: HashMap<&'static str, Box Response>>, +} + +impl HttpServer { + pub fn new( + registry_path: PathBuf, + dl_path: PathBuf, + token: Option, + api_responders: HashMap<&'static str, Box Response>>, + ) -> HttpServerHandle { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + let server = HttpServer { + listener, + registry_path, + dl_path, + token, + custom_responders: api_responders, + }; + thread::spawn(move || server.start()); + HttpServerHandle { addr } + } - let t = thread::spawn(move || { + fn start(&self) { let mut line = String::new(); - 'server: while !done2.load(Ordering::SeqCst) { - let (socket, _) = listener.accept().unwrap(); - // Let's implement a very naive static file HTTP server. + 'server: loop { + let (socket, _) = self.listener.accept().unwrap(); let mut buf = BufReader::new(socket); - - // First, the request line: - // GET /path HTTPVERSION line.clear(); if buf.read_line(&mut line).unwrap() == 0 { // Connection terminated. continue; } - - assert!(line.starts_with("GET "), "got non-GET request: {}", line); - let path = PathBuf::from( - line.split_whitespace() - .skip(1) - .next() - .unwrap() - .trim_start_matches('/'), + // Read the "GET path HTTP/1.1" line. + let mut parts = line.split_ascii_whitespace(); + let method = parts.next().unwrap().to_ascii_lowercase(); + if method == "stop" { + // Shutdown the server. + return; + } + let addr = self.listener.local_addr().unwrap(); + let url = format!( + "http://{}/{}", + addr, + parts.next().unwrap().trim_start_matches('/') ); + let url = Url::parse(&url).unwrap(); - let file = registry_path.join(path); - if file.exists() { - // Grab some other headers we may care about. - let mut if_modified_since = None; - let mut if_none_match = None; - loop { + // Grab headers we care about. + let mut if_modified_since = None; + let mut if_none_match = None; + let mut authorization = None; + loop { + line.clear(); + if buf.read_line(&mut line).unwrap() == 0 { + continue 'server; + } + if line == "\r\n" { + // End of headers. line.clear(); - if buf.read_line(&mut line).unwrap() == 0 { - continue 'server; - } - - if line == "\r\n" { - // End of headers. - line.clear(); - break; - } - - let value = line - .splitn(2, ':') - .skip(1) - .next() - .map(|v| v.trim()) - .unwrap(); - - if line.starts_with("If-Modified-Since:") { - if_modified_since = Some(value.to_owned()); - } else if line.starts_with("If-None-Match:") { - if_none_match = Some(value.trim_matches('"').to_owned()); - } + break; + } + let (name, value) = line.split_once(':').unwrap(); + let name = name.trim().to_ascii_lowercase(); + let value = value.trim().to_string(); + match name.as_str() { + "if-modified-since" => if_modified_since = Some(value), + "if-none-match" => if_none_match = Some(value), + "authorization" => authorization = Some(value), + _ => {} } + } + let req = Request { + authorization, + if_modified_since, + if_none_match, + method, + url, + }; + println!("req: {:#?}", req); + let response = self.route(&req); + let buf = buf.get_mut(); + write!(buf, "HTTP/1.1 {}\r\n", response.code).unwrap(); + write!(buf, "Content-Length: {}\r\n", response.body.len()).unwrap(); + for header in response.headers { + write!(buf, "{}\r\n", header).unwrap(); + } + write!(buf, "\r\n").unwrap(); + buf.write_all(&response.body).unwrap(); + buf.flush().unwrap(); + } + } - // Now grab info about the file. - let data = fs::read(&file).unwrap(); - let etag = Sha256::new().update(&data).finish_hex(); - let last_modified = format!("{:?}", file.metadata().unwrap().modified().unwrap()); - - // Start to construct our response: - let mut any_match = false; - let mut all_match = true; - if let Some(expected) = if_none_match { - if etag != expected { - all_match = false; - } else { - any_match = true; - } + /// Route the request + fn route(&self, req: &Request) -> Response { + let authorized = |mutatation: bool| { + if mutatation { + self.token == req.authorization + } else { + assert!(req.authorization.is_none(), "unexpected token"); + true + } + }; + + // Check for custom responder + if let Some(responder) = self.custom_responders.get(req.url.path()) { + return responder(&req); + } + let path: Vec<_> = req.url.path()[1..].split('/').collect(); + match (req.method.as_str(), path.as_slice()) { + ("get", ["index", ..]) => { + if !authorized(false) { + self.unauthorized(req) + } else { + self.index(&req) } - if let Some(expected) = if_modified_since { - // NOTE: Equality comparison is good enough for tests. - if last_modified != expected { - all_match = false; - } else { - any_match = true; - } + } + ("get", ["dl", ..]) => { + if !authorized(false) { + self.unauthorized(req) + } else { + self.dl(&req) } - - // Write out the main response line. - if any_match && all_match { - buf.get_mut() - .write_all(b"HTTP/1.1 304 Not Modified\r\n") - .unwrap(); + } + // The remainder of the operators in the test framework do nothing other than responding 'ok'. + // + // Note: We don't need to support anything real here because the testing framework publishes crates + // by writing directly to the filesystem instead. If the test framework is changed to publish + // via the HTTP API, then this should be made more complete. + + // publish + ("put", ["api", "v1", "crates", "new"]) + // yank + | ("delete", ["api", "v1", "crates", .., "yank"]) + // unyank + | ("put", ["api", "v1", "crates", .., "unyank"]) + // owners + | ("get" | "put" | "delete", ["api", "v1", "crates", .., "owners"]) => { + if !authorized(true) { + self.unauthorized(req) } else { - buf.get_mut().write_all(b"HTTP/1.1 200 OK\r\n").unwrap(); + self.ok(&req) } - // TODO: Support 451 for crate index deletions. + } + _ => self.not_found(&req), + } + } - // Write out other headers. - buf.get_mut() - .write_all(format!("Content-Length: {}\r\n", data.len()).as_bytes()) - .unwrap(); - buf.get_mut() - .write_all(format!("ETag: \"{}\"\r\n", etag).as_bytes()) - .unwrap(); - buf.get_mut() - .write_all(format!("Last-Modified: {}\r\n", last_modified).as_bytes()) - .unwrap(); - - // And finally, write out the body. - buf.get_mut().write_all(b"\r\n").unwrap(); - buf.get_mut().write_all(&data).unwrap(); - } else { - loop { - line.clear(); - if buf.read_line(&mut line).unwrap() == 0 { - // Connection terminated. - continue 'server; - } + /// Unauthorized response + fn unauthorized(&self, _req: &Request) -> Response { + Response { + code: 401, + headers: vec![], + body: b"Unauthorized message from server.".to_vec(), + } + } - if line == "\r\n" { - break; - } - } + /// Not found response + fn not_found(&self, _req: &Request) -> Response { + Response { + code: 404, + headers: vec![], + body: b"not found".to_vec(), + } + } - buf.get_mut() - .write_all(b"HTTP/1.1 404 Not Found\r\n\r\n") - .unwrap(); - buf.get_mut().write_all(b"\r\n").unwrap(); - } - buf.get_mut().flush().unwrap(); - } - }); - - RegistryServer { - addr, - server: Some(t), - done, + /// Respond OK without doing anything + fn ok(&self, _req: &Request) -> Response { + Response { + code: 200, + headers: vec![], + body: br#"{"ok": true, "msg": "completed!"}"#.to_vec(), + } } -} -/// Creates a new on-disk registry. -pub fn init_registry(registry_path: PathBuf, dl_url: String, api_url: Url, api_path: PathBuf) { - // Initialize a new registry. - repo(®istry_path) - .file( - "config.json", - &format!(r#"{{"dl":"{}","api":"{}"}}"#, dl_url, api_url), - ) - .build(); - fs::create_dir_all(api_path.join("api/v1/crates")).unwrap(); + /// Serve the download endpoint + fn dl(&self, req: &Request) -> Response { + let file = self + .dl_path + .join(req.url.path().strip_prefix("/dl/").unwrap()); + println!("{}", file.display()); + if !file.exists() { + return self.not_found(req); + } + return Response { + body: fs::read(&file).unwrap(), + code: 200, + headers: vec![], + }; + } + + /// Serve the registry index + fn index(&self, req: &Request) -> Response { + let file = self + .registry_path + .join(req.url.path().strip_prefix("/index/").unwrap()); + if !file.exists() { + return self.not_found(req); + } else { + // Now grab info about the file. + let data = fs::read(&file).unwrap(); + let etag = Sha256::new().update(&data).finish_hex(); + let last_modified = format!("{:?}", file.metadata().unwrap().modified().unwrap()); + + // Start to construct our response: + let mut any_match = false; + let mut all_match = true; + if let Some(expected) = &req.if_none_match { + if &etag != expected { + all_match = false; + } else { + any_match = true; + } + } + if let Some(expected) = &req.if_modified_since { + // NOTE: Equality comparison is good enough for tests. + if &last_modified != expected { + all_match = false; + } else { + any_match = true; + } + } + + if any_match && all_match { + return Response { + body: Vec::new(), + code: 304, + headers: vec![], + }; + } else { + return Response { + body: data, + code: 200, + headers: vec![ + format!("ETag: \"{}\"", etag), + format!("Last-Modified: {}", last_modified), + ], + }; + } + } + } } impl Package { /// Creates a new package builder. /// Call `publish()` to finalize and build the package. pub fn new(name: &str, vers: &str) -> Package { - init(); + let config = paths::home().join(".cargo/config"); + if !config.exists() { + init(); + } Package { name: name.to_string(), vers: vers.to_string(), @@ -951,7 +1136,7 @@ alt_dl_path() .join(&self.name) .join(&self.vers) - .join(&format!("{}-{}.crate", self.name, self.vers)) + .join("download") } else { dl_path().join(&self.name).join(&self.vers).join("download") } diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/tools.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/tools.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-test-support/src/tools.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-test-support/src/tools.rs 2022-10-20 06:00:42.000000000 +0000 @@ -24,8 +24,17 @@ .file( "src/main.rs", r#" + use std::fs::read_to_string; + use std::path::PathBuf; fn main() { - let args = std::env::args().collect::>(); + // Handle args from `@path` argfile for rustc + let args = std::env::args() + .flat_map(|p| if let Some(p) = p.strip_prefix("@") { + read_to_string(p).unwrap().lines().map(String::from).collect() + } else { + vec![p] + }) + .collect::>(); eprintln!("WRAPPER CALLED: {}", args[1..].join(" ")); let status = std::process::Command::new(&args[1]) .args(&args[2..]).status().unwrap(); diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-util/Cargo.toml cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/Cargo.toml --- cargo-0.62.0ubuntu0libgit2/crates/cargo-util/Cargo.toml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/Cargo.toml 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,6 @@ [package] name = "cargo-util" -version = "0.1.2" +version = "0.2.2" edition = "2021" license = "MIT OR Apache-2.0" homepage = "https://github.com/rust-lang/cargo" diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/paths.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/paths.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/paths.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/paths.rs 2022-10-20 06:00:42.000000000 +0000 @@ -250,7 +250,7 @@ // race with unlinking?). Regardless, if Cargo can't // read it, the build script probably can't either. log::debug!( - "failed to determine mtime while fetching symlink metdata of {}: {}", + "failed to determine mtime while fetching symlink metadata of {}: {}", e.path().display(), err ); @@ -541,7 +541,7 @@ if cfg!(target_os = "macos") { // This is a work-around for a bug on macos. There seems to be a race condition // with APFS when hard-linking binaries. Gatekeeper does not have signing or - // hash informations stored in kernel when running the process. Therefore killing it. + // hash information stored in kernel when running the process. Therefore killing it. // This problem does not appear when copying files as kernel has time to process it. // Note that: fs::copy on macos is using CopyOnWrite (syscall fclonefileat) which should be // as fast as hardlinking. @@ -632,7 +632,7 @@ let parent = path.parent().unwrap(); let base = path.file_name().unwrap(); create_dir_all(parent)?; - // We do this in two steps (first create a temporary directory and exlucde + // We do this in two steps (first create a temporary directory and exclude // it from backups, then rename it to the desired name. If we created the // directory directly where it should be and then excluded it from backups // we would risk a situation where cargo is interrupted right after the directory @@ -660,6 +660,15 @@ Ok(()) } +/// Mark an existing directory as excluded from backups and indexing. +/// +/// Errors in marking it are ignored. +pub fn exclude_from_backups_and_indexing(p: impl AsRef) { + let path = p.as_ref(); + exclude_from_backups(path); + exclude_from_content_indexing(path); +} + /// Marks the directory as excluded from archives/backups. /// /// This is recommended to prevent derived/temporary files from bloating backups. There are two diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/process_builder.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/process_builder.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/process_builder.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/process_builder.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,15 +1,19 @@ use crate::process_error::ProcessError; use crate::read2; + use anyhow::{bail, Context, Result}; use jobserver::Client; use shell_escape::escape; +use tempfile::NamedTempFile; + use std::collections::BTreeMap; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt; +use std::io::{self, Write}; use std::iter::once; use std::path::Path; -use std::process::{Command, Output, Stdio}; +use std::process::{Command, ExitStatus, Output, Stdio}; /// A builder object for an external process, similar to [`std::process::Command`]. #[derive(Clone, Debug)] @@ -22,6 +26,9 @@ env: BTreeMap>, /// The directory to run the program from. cwd: Option, + /// A list of wrappers that wrap the original program when calling + /// [`ProcessBuilder::wrapped`]. The last one is the outermost one. + wrappers: Vec, /// The `make` jobserver. See the [jobserver crate] for /// more information. /// @@ -29,6 +36,11 @@ jobserver: Option, /// `true` to include environment variable in display. display_env_vars: bool, + /// `true` to retry with an argfile if hitting "command line too big" error. + /// See [`ProcessBuilder::retry_with_argfile`] for more information. + retry_with_argfile: bool, + /// Data to write to stdin. + stdin: Option>, } impl fmt::Display for ProcessBuilder { @@ -48,9 +60,9 @@ } } - write!(f, "{}", self.program.to_string_lossy())?; + write!(f, "{}", self.get_program().to_string_lossy())?; - for arg in &self.args { + for arg in self.get_args() { write!(f, " {}", escape(arg.to_string_lossy()))?; } @@ -66,8 +78,11 @@ args: Vec::new(), cwd: None, env: BTreeMap::new(), + wrappers: Vec::new(), jobserver: None, display_env_vars: false, + retry_with_argfile: false, + stdin: None, } } @@ -92,6 +107,13 @@ /// (chainable) Replaces the args list with the given `args`. pub fn args_replace>(&mut self, args: &[T]) -> &mut ProcessBuilder { + if let Some(program) = self.wrappers.pop() { + // User intend to replace all args, so we + // - use the outermost wrapper as the main program, and + // - cleanup other inner wrappers. + self.program = program; + self.wrappers = Vec::new(); + } self.args = args.iter().map(|t| t.as_ref().to_os_string()).collect(); self } @@ -117,12 +139,17 @@ /// Gets the executable name. pub fn get_program(&self) -> &OsString { - &self.program + self.wrappers.last().unwrap_or(&self.program) } /// Gets the program arguments. - pub fn get_args(&self) -> &[OsString] { - &self.args + pub fn get_args(&self) -> impl Iterator { + self.wrappers + .iter() + .rev() + .chain(once(&self.program)) + .chain(self.args.iter()) + .skip(1) // Skip the main `program } /// Gets the current working directory for the process. @@ -161,13 +188,62 @@ self } + /// Enables retrying with an argfile if hitting "command line too big" error + /// + /// This is primarily for the `@path` arg of rustc and rustdoc, which treat + /// each line as an command-line argument, so `LF` and `CRLF` bytes are not + /// valid as an argument for argfile at this moment. + /// For example, `RUSTDOCFLAGS="--crate-version foo\nbar" cargo doc` is + /// valid when invoking from command-line but not from argfile. + /// + /// To sum up, the limitations of the argfile are: + /// + /// - Must be valid UTF-8 encoded. + /// - Must not contain any newlines in each argument. + /// + /// Ref: + /// + /// - https://doc.rust-lang.org/rustdoc/command-line-arguments.html#path-load-command-line-flags-from-a-path + /// - https://doc.rust-lang.org/rustc/command-line-arguments.html#path-load-command-line-flags-from-a-path> + pub fn retry_with_argfile(&mut self, enabled: bool) -> &mut Self { + self.retry_with_argfile = enabled; + self + } + + /// Sets a value that will be written to stdin of the process on launch. + pub fn stdin>>(&mut self, stdin: T) -> &mut Self { + self.stdin = Some(stdin.into()); + self + } + + fn should_retry_with_argfile(&self, err: &io::Error) -> bool { + self.retry_with_argfile && imp::command_line_too_big(err) + } + + /// Like [`Command::status`] but with a better error message. + pub fn status(&self) -> Result { + self._status() + .with_context(|| ProcessError::could_not_execute(self)) + } + + fn _status(&self) -> io::Result { + if !debug_force_argfile(self.retry_with_argfile) { + let mut cmd = self.build_command(); + match cmd.spawn() { + Err(ref e) if self.should_retry_with_argfile(e) => {} + Err(e) => return Err(e), + Ok(mut child) => return child.wait(), + } + } + let (mut cmd, argfile) = self.build_command_with_argfile()?; + let status = cmd.spawn()?.wait(); + close_tempfile_and_log_error(argfile); + status + } + /// Runs the process, waiting for completion, and mapping non-success exit codes to an error. pub fn exec(&self) -> Result<()> { - let mut command = self.build_command(); - let exit = command.status().with_context(|| { - ProcessError::new(&format!("could not execute process {}", self), None, None) - })?; - + let exit = self.status()?; if exit.success() { Ok(()) } else { @@ -199,14 +275,39 @@ imp::exec_replace(self) } - /// Executes the process, returning the stdio output, or an error if non-zero exit status. - pub fn exec_with_output(&self) -> Result { - let mut command = self.build_command(); + /// Like [`Command::output`] but with a better error message. + pub fn output(&self) -> Result { + self._output() + .with_context(|| ProcessError::could_not_execute(self)) + } - let output = command.output().with_context(|| { - ProcessError::new(&format!("could not execute process {}", self), None, None) - })?; + fn _output(&self) -> io::Result { + if !debug_force_argfile(self.retry_with_argfile) { + let mut cmd = self.build_command(); + match piped(&mut cmd, self.stdin.is_some()).spawn() { + Err(ref e) if self.should_retry_with_argfile(e) => {} + Err(e) => return Err(e), + Ok(mut child) => { + if let Some(stdin) = &self.stdin { + child.stdin.take().unwrap().write_all(stdin)?; + } + return child.wait_with_output(); + } + } + } + let (mut cmd, argfile) = self.build_command_with_argfile()?; + let mut child = piped(&mut cmd, self.stdin.is_some()).spawn()?; + if let Some(stdin) = &self.stdin { + child.stdin.take().unwrap().write_all(stdin)?; + } + let output = child.wait_with_output(); + close_tempfile_and_log_error(argfile); + output + } + /// Executes the process, returning the stdio output, or an error if non-zero exit status. + pub fn exec_with_output(&self) -> Result { + let output = self.output()?; if output.status.success() { Ok(output) } else { @@ -237,16 +338,25 @@ let mut stdout = Vec::new(); let mut stderr = Vec::new(); - let mut cmd = self.build_command(); - cmd.stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .stdin(Stdio::null()); - let mut callback_error = None; let mut stdout_pos = 0; let mut stderr_pos = 0; + + let spawn = |mut cmd| { + if !debug_force_argfile(self.retry_with_argfile) { + match piped(&mut cmd, false).spawn() { + Err(ref e) if self.should_retry_with_argfile(e) => {} + Err(e) => return Err(e), + Ok(child) => return Ok((child, None)), + } + } + let (mut cmd, argfile) = self.build_command_with_argfile()?; + Ok((piped(&mut cmd, false).spawn()?, Some(argfile))) + }; + let status = (|| { - let mut child = cmd.spawn()?; + let cmd = self.build_command(); + let (mut child, argfile) = spawn(cmd)?; let out = child.stdout.take().unwrap(); let err = child.stderr.take().unwrap(); read2(out, err, &mut |is_out, data, eof| { @@ -292,11 +402,13 @@ data.drain(..idx); *pos = 0; })?; - child.wait() + let status = child.wait(); + if let Some(argfile) = argfile { + close_tempfile_and_log_error(argfile); + } + status })() - .with_context(|| { - ProcessError::new(&format!("could not execute process {}", self), None, None) - })?; + .with_context(|| ProcessError::could_not_execute(self))?; let output = Output { status, stdout, @@ -324,16 +436,56 @@ Ok(output) } - /// 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); + /// Builds the command with an `@` argfile that contains all the + /// arguments. This is primarily served for rustc/rustdoc command family. + fn build_command_with_argfile(&self) -> io::Result<(Command, NamedTempFile)> { + use std::io::Write as _; + + let mut tmp = tempfile::Builder::new() + .prefix("cargo-argfile.") + .tempfile()?; + + let mut arg = OsString::from("@"); + arg.push(tmp.path()); + let mut cmd = self.build_command_without_args(); + cmd.arg(arg); + log::debug!("created argfile at {} for {self}", tmp.path().display()); + + let cap = self.get_args().map(|arg| arg.len() + 1).sum::(); + let mut buf = Vec::with_capacity(cap); + for arg in &self.args { + let arg = arg.to_str().ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + format!( + "argument for argfile contains invalid UTF-8 characters: `{}`", + arg.to_string_lossy() + ), + ) + })?; + if arg.contains('\n') { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("argument for argfile contains newlines: `{arg}`"), + )); + } + writeln!(buf, "{arg}")?; + } + tmp.write_all(&mut buf)?; + Ok((cmd, tmp)) + } + + /// Builds a command from `ProcessBuilder` for everything but not `args`. + fn build_command_without_args(&self) -> Command { + let mut command = { + let mut iter = self.wrappers.iter().rev().chain(once(&self.program)); + let mut cmd = Command::new(iter.next().expect("at least one `program` exists")); + cmd.args(iter); + cmd + }; if let Some(cwd) = self.get_cwd() { command.current_dir(cwd); } - for arg in &self.args { - command.arg(arg); - } for (k, v) in &self.env { match *v { Some(ref v) => { @@ -350,6 +502,19 @@ command } + /// Converts `ProcessBuilder` into a `std::process::Command`, and handles + /// the jobserver, if present. + /// + /// Note that this method doesn't take argfile fallback into account. The + /// caller should handle it by themselves. + pub fn build_command(&self) -> Command { + let mut command = self.build_command_without_args(); + for arg in &self.args { + command.arg(arg); + } + command + } + /// Wraps an existing command with the provided wrapper, if it is present and valid. /// /// # Examples @@ -363,46 +528,84 @@ /// let cmd = cmd.wrapped(Some("sccache")); /// ``` pub fn wrapped(mut self, wrapper: Option>) -> Self { - let wrapper = if let Some(wrapper) = wrapper.as_ref() { - wrapper.as_ref() - } else { - return self; - }; - - if wrapper.is_empty() { - return self; + if let Some(wrapper) = wrapper.as_ref() { + let wrapper = wrapper.as_ref(); + if !wrapper.is_empty() { + self.wrappers.push(wrapper.to_os_string()); + } } + self + } +} - let args = once(self.program).chain(self.args.into_iter()).collect(); +/// Forces the command to use `@path` argfile. +/// +/// You should set `__CARGO_TEST_FORCE_ARGFILE` to enable this. +fn debug_force_argfile(retry_enabled: bool) -> bool { + cfg!(debug_assertions) && env::var("__CARGO_TEST_FORCE_ARGFILE").is_ok() && retry_enabled +} - self.program = wrapper.to_os_string(); - self.args = args; +/// Creates new pipes for stderr, stdout, and optionally stdin. +fn piped(cmd: &mut Command, pipe_stdin: bool) -> &mut Command { + cmd.stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .stdin(if pipe_stdin { + Stdio::piped() + } else { + Stdio::null() + }) +} - self - } +fn close_tempfile_and_log_error(file: NamedTempFile) { + file.close().unwrap_or_else(|e| { + log::warn!("failed to close temporary file: {e}"); + }); } #[cfg(unix)] mod imp { - use super::{ProcessBuilder, ProcessError}; + use super::{close_tempfile_and_log_error, debug_force_argfile, ProcessBuilder, ProcessError}; use anyhow::Result; + use std::io; use std::os::unix::process::CommandExt; pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> { - let mut command = process_builder.build_command(); - let error = command.exec(); + let mut error; + let mut file = None; + if debug_force_argfile(process_builder.retry_with_argfile) { + let (mut command, argfile) = process_builder.build_command_with_argfile()?; + file = Some(argfile); + error = command.exec() + } else { + let mut command = process_builder.build_command(); + error = command.exec(); + if process_builder.should_retry_with_argfile(&error) { + let (mut command, argfile) = process_builder.build_command_with_argfile()?; + file = Some(argfile); + error = command.exec() + } + } + if let Some(file) = file { + close_tempfile_and_log_error(file); + } + Err(anyhow::Error::from(error).context(ProcessError::new( &format!("could not execute process {}", process_builder), None, None, ))) } + + pub fn command_line_too_big(err: &io::Error) -> bool { + err.raw_os_error() == Some(libc::E2BIG) + } } #[cfg(windows)] mod imp { use super::{ProcessBuilder, ProcessError}; use anyhow::Result; + use std::io; use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE}; use winapi::um::consoleapi::SetConsoleCtrlHandler; @@ -421,4 +624,66 @@ // Just execute the process as normal. process_builder.exec() } + + pub fn command_line_too_big(err: &io::Error) -> bool { + use winapi::shared::winerror::ERROR_FILENAME_EXCED_RANGE; + err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE as i32) + } +} + +#[cfg(test)] +mod tests { + use super::ProcessBuilder; + use std::fs; + + #[test] + fn argfile_build_succeeds() { + let mut cmd = ProcessBuilder::new("echo"); + cmd.args(["foo", "bar"].as_slice()); + let (cmd, argfile) = cmd.build_command_with_argfile().unwrap(); + + assert_eq!(cmd.get_program(), "echo"); + let cmd_args: Vec<_> = cmd.get_args().map(|s| s.to_str().unwrap()).collect(); + assert_eq!(cmd_args.len(), 1); + assert!(cmd_args[0].starts_with("@")); + assert!(cmd_args[0].contains("cargo-argfile.")); + + let buf = fs::read_to_string(argfile.path()).unwrap(); + assert_eq!(buf, "foo\nbar\n"); + } + + #[test] + fn argfile_build_fails_if_arg_contains_newline() { + let mut cmd = ProcessBuilder::new("echo"); + cmd.arg("foo\n"); + let err = cmd.build_command_with_argfile().unwrap_err(); + assert_eq!( + err.to_string(), + "argument for argfile contains newlines: `foo\n`" + ); + } + + #[test] + fn argfile_build_fails_if_arg_contains_invalid_utf8() { + let mut cmd = ProcessBuilder::new("echo"); + + #[cfg(windows)] + let invalid_arg = { + use std::os::windows::prelude::*; + std::ffi::OsString::from_wide(&[0x0066, 0x006f, 0xD800, 0x006f]) + }; + + #[cfg(unix)] + let invalid_arg = { + use std::os::unix::ffi::OsStrExt; + std::ffi::OsStr::from_bytes(&[0x66, 0x6f, 0x80, 0x6f]).to_os_string() + }; + + cmd.arg(invalid_arg); + let err = cmd.build_command_with_argfile().unwrap_err(); + assert_eq!( + err.to_string(), + "argument for argfile contains invalid UTF-8 characters: `fo�o`" + ); + } } diff -Nru cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/process_error.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/process_error.rs --- cargo-0.62.0ubuntu0libgit2/crates/cargo-util/src/process_error.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/cargo-util/src/process_error.rs 2022-10-20 06:00:42.000000000 +0000 @@ -95,6 +95,13 @@ stderr: stderr.map(|s| s.to_vec()), } } + + /// Creates a [`ProcessError`] with "could not execute process {cmd}". + /// + /// * `cmd` is usually but not limited to [`std::process::Command`]. + pub fn could_not_execute(cmd: impl fmt::Display) -> ProcessError { + ProcessError::new(&format!("could not execute process {cmd}"), None, None) + } } /// Converts an [`ExitStatus`] to a human-readable string suitable for diff -Nru cargo-0.62.0ubuntu0libgit2/crates/mdman/src/hbs.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/mdman/src/hbs.rs --- cargo-0.62.0ubuntu0libgit2/crates/mdman/src/hbs.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/mdman/src/hbs.rs 2022-10-20 06:00:42.000000000 +0000 @@ -7,7 +7,6 @@ RenderContext, RenderError, Renderable, }; use std::collections::HashMap; -use std::convert::TryFrom; use std::path::Path; type FormatterRef<'a> = &'a (dyn Formatter + Send + Sync); diff -Nru cargo-0.62.0ubuntu0libgit2/crates/resolver-tests/src/lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/crates/resolver-tests/src/lib.rs --- cargo-0.62.0ubuntu0libgit2/crates/resolver-tests/src/lib.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/crates/resolver-tests/src/lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -12,7 +12,7 @@ use cargo::core::dependency::DepKind; use cargo::core::resolver::{self, ResolveOpts, VersionPreferences}; -use cargo::core::source::{GitReference, SourceId}; +use cargo::core::source::{GitReference, QueryKind, SourceId}; use cargo::core::Resolve; use cargo::core::{Dependency, PackageId, Registry, Summary}; use cargo::util::{CargoResult, Config, Graph, IntoUrl}; @@ -128,11 +128,15 @@ fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll> { for summary in self.list.iter() { - if fuzzy || dep.matches(summary) { + let matched = match kind { + QueryKind::Exact => dep.matches(summary), + QueryKind::Fuzzy => true, + }; + if matched { self.used.insert(summary.package_id()); f(summary.clone()); } diff -Nru cargo-0.62.0ubuntu0libgit2/debian/bin/cargo cargo-0.66.0+ds0ubuntu0.libgit2/debian/bin/cargo --- cargo-0.62.0ubuntu0libgit2/debian/bin/cargo 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/bin/cargo 2023-01-17 12:21:18.000000000 +0000 @@ -96,8 +96,15 @@ for f in ldflags: rustflags.extend(["-C", "link-arg=%s" % f]) if link_from_system: - rustflags.extend(["--remap-path-prefix", "%s=%s/%s" % - (sourcepath(), SYSTEM_REGISTRY, cratespec.replace("_", "-"))]) + rustflags.extend([ + # Note that this order is important! Rust evaluates these options in + # priority of reverse order, so if the second option were in front, + # it would never be used, because any paths in registry_path are + # also in sourcepath(). + "--remap-path-prefix", "%s=%s/%s" % + (sourcepath(), SYSTEM_REGISTRY, cratespec.replace("_", "-")), + "--remap-path-prefix", "%s=%s" % (registry_path, SYSTEM_REGISTRY), + ]) rustflags.extend(extra_rustflags.split()) # TODO: we cannot enable this until dh_shlibdeps works correctly; atm we get: diff -Nru cargo-0.62.0ubuntu0libgit2/debian/changelog cargo-0.66.0+ds0ubuntu0.libgit2/debian/changelog --- cargo-0.62.0ubuntu0libgit2/debian/changelog 2022-09-19 12:36:42.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/changelog 2023-01-18 20:42:34.000000000 +0000 @@ -1,18 +1,134 @@ -cargo (0.62.0ubuntu0libgit2-0ubuntu0.18.04.1) bionic; urgency=medium +cargo (0.66.0+ds0ubuntu0.libgit2-0ubuntu0.18.04) bionic; urgency=medium - * Backport to Bionic (LP: #1986648) - - Relax debhelper requirements - * Re-enable libgit2 vendoring + * Backport to Bionic (LP: #2000839) + * Re-enable libgit2 vendoring: - d/control: remove libgit2-dev and libhttp-parser-dev from B-D + - include Rust provided patches to fix CVE-2022-46176 + * Remove the need of dh-cargo + * Downgrade the debhelper requirements - -- Simon Chopin Mon, 19 Sep 2022 14:36:42 +0200 + -- Zixing Liu Wed, 18 Jan 2023 13:42:34 -0700 -cargo (0.62.0ubuntu1-0ubuntu1) kinetic; urgency=medium +cargo (0.66.0+ds1-1ubuntu1) lunar; urgency=medium + + * Merge from Debian unstable (LP: #2000839): + Remaining changes: + - Add an explicit mechanism to customize the vendoring process + - d/p/proxy-skip-tests.patch: skip a test when there's a proxy configured + to accommodate Ubuntu autopkgtest setup + - d/p/i386-crossbuild-tests.patch: disable some failing tests for + cross-building from i386 + - d/p/remove-badges.patch: remove badges from documentation for privacy + reasons (refreshed) + - autopkgtests: test on all arches on Ubuntu + - d/control: update the Vcs fields to point to Launchpad + - make_orig_multi.sh: fix orig tarball compression to xz on Ubuntu + - Track vendored dependencies + - Bump the libgit2-related crates to get libgit2 1.5.0 bindings + - make_orig_multi.sh: only use xz for vendor orig tarball on Ubuntu + * Update vendored sources information + + -- Simon Chopin Tue, 17 Jan 2023 14:48:37 +0100 + +cargo (0.66.0+ds1-1) unstable; urgency=medium + + [ Fabian Grünbichler ] + * fix CVE-2022-46176 (Thanks Peter Green!) + * repack vendored sources with required libgit2-sys/git2/git2-curl versions + * update unsuspicious files + + -- Fabian Gruenbichler Wed, 11 Jan 2023 18:55:09 +0100 + +cargo (0.66.0-1) unstable; urgency=medium + + * new upstream version 0.66 + + [ Blair Noctis ] + * Update debcargo-conf.patch, unapply tempfile patch to match vendored + * Refresh patches and remove upstream applied CVE patches + * Patch test macro to work around qemu vfork bug when command not found + + [ Fabian Grünbichler ] + * no longer pin git2/libgit2-sys + * update debcargo-conf.patch (concolor, clap) + * update unsuspicious files + * d/control: depend on rustc 1.63 + * drop armel workaround + + [ Rob Shearman ] + * d/control: update minimum cargo, rustc and libstd-rust-dev versions + + -- Fabian Gruenbichler Sun, 08 Jan 2023 16:38:30 +0100 + +cargo (0.64.0ubuntu1-0ubuntu1) lunar; urgency=medium + + * New upstream release (LP: #1995096): + - Update vendored sources info + * Bump the libgit2-related crates to get libgit2 1.5.0 bindings + * make_orig_multi.sh: only use xz for vendor orig tarball on Ubuntu + + -- Simon Chopin Tue, 29 Nov 2022 15:05:19 +0100 + +cargo (0.63.1-3) unstable; urgency=medium + + * workaround armel breakage + + -- Fabian Gruenbichler Wed, 07 Dec 2022 14:58:58 +0100 + +cargo (0.63.1-2ubuntu1) lunar; urgency=medium + + * Merge from Debian unstable. + Remaining changes: + - Add an explicit mechanism to customize the vendoring process + - d/p/proxy-skip-tests.patch: skip a test when there's a proxy configured + to accommodate Ubuntu autopkgtest setup + - d/p/i386-crossbuild-tests.patch: disable some failing tests for + cross-building from i386 + - d/p/remove-badges.patch: remove badges from documentation for privacy + reasons + - autopkgtests: test on all arches on Ubuntu + - d/control: update the Vcs fields to point to Launchpad + - make_orig_multi.sh: fix orig tarball compression to xz on Ubuntu + - Track vendored dependencies + + -- Simon Chopin Fri, 25 Nov 2022 16:42:43 +0100 + +cargo (0.63.1-2) unstable; urgency=medium + + [ Ryan Gonzalez ] + * Fix path remapping for crate dependencies + + [ Fabian Grünbichler ] + * disable utf-8 fs-specific test + * fix i386 build / cross tests + + -- Fabian Gruenbichler Sat, 19 Nov 2022 10:48:29 +0100 + +cargo (0.63.1-1) unstable; urgency=medium + + * New upstream release + * switch to libgit2-1.5 (Closes: #1021504, #1017828) + * Update guess-crate-copyright to handle missing authors field gracefully + * Update audit-vendor-source to handle ZFS and similar file systems + * silence GZIP deprecation warning + * fix CVE-2022-36113/CVE-2022-36114 (Closes: #1021142) + + [ Helmut Grohne ] + * Fix FTCBFS: Missing Build-Depends: zlib1g-dev:native. (Closes: #1019491) + + -- Fabian Gruenbichler Sat, 17 Sep 2022 22:25:02 +0200 + +cargo (0.62.0ubuntu1-0ubuntu2) kinetic; urgency=medium - * New upstream release (LP: #1986648) * d/p/i386-crossbuild-tests.patch: disable some failing tests for cross-building from i386 + -- Simon Chopin Mon, 19 Sep 2022 14:59:42 +0200 + +cargo (0.62.0ubuntu1-0ubuntu1) kinetic; urgency=medium + + * New upstream release (LP: #1986648) + -- Simon Chopin Thu, 08 Sep 2022 11:44:51 +0200 cargo (0.60.0ubuntu2-0ubuntu1) kinetic; urgency=medium @@ -23,7 +139,7 @@ * d/p/remove-badges.patch: remove badges from documentation for privacy reasons * d/p/proxy-skip-tests.patch: skip a test when there's a proxy configured - to accomodate Ubuntu autopkgtest setup + to accommodate Ubuntu autopkgtest setup -- Simon Chopin Fri, 24 Jun 2022 11:17:27 +0200 @@ -76,6 +192,47 @@ -- Michael Hudson-Doyle Thu, 16 Dec 2021 10:39:46 +1300 +cargo (0.57.0-7) unstable; urgency=medium + + * Team upload. + * Upload to unstable. + + -- Peter Michael Green Mon, 02 May 2022 20:57:46 +0000 + +cargo (0.57.0-6) experimental; urgency=medium + + * Team upload. + * Fix debian cargo wrapper to stop looking for subcommands once it finds one + so that it is possible to test features whose name matches a subcommand. + * Limit autopkgtest to architectures where it does not run out of disk space. + * Remove patches for libgit2 1.1.x and adjust dependency for 0.3.x + (Closes: 1009015) + * Remove build-dependency on cmake (Closes: 981256) + + -- Peter Michael Green Sun, 10 Apr 2022 00:10:04 +0000 + +cargo (0.57.0-5) unstable; urgency=medium + + [ Simon Chopin ] + * Disable cross-build tests in autopkgtests + * d/p/0001-Change-test-to-not-trigger-emoji-error.patch: + Cherry-picked from upstream to fix testsuite against rustc 1.57 + * d/p/0002-Remove-eacces-test.patch: Cherry-picked from upstream as + cargo doesn't seem to trigger the error with recent Rust + + -- Ximin Luo Wed, 09 Mar 2022 13:52:14 +0000 + +cargo (0.57.0-4) unstable; urgency=medium + + [ Simon Chopin ] + * Add an autopkgtest for cargo to build itself + * Disable cross-build tests in autopkgtests + + [ Ximin Luo ] + * Fix FTBFS on x32. + + -- Ximin Luo Mon, 07 Mar 2022 20:35:00 +0000 + cargo (0.57.0-3) unstable; urgency=medium * Actually fix failing tests. @@ -1034,25 +1191,6 @@ -- Vasudev Kamath Sat, 21 Apr 2018 20:59:39 +0530 -cargo (0.25.0-3) unstable; urgency=medium - - [ Ximin Luo ] - * Update Vcs-* fields to salsa - - [ Vasudev Kamath ] - * Add patch to prevent incremental builds on sparc64. - Closes: bug#895300, Thanks to John Paul Adrian Glaubitz. - - -- Vasudev Kamath Sun, 15 Apr 2018 12:28:29 +0530 - -cargo (0.25.0-2) unstable; urgency=medium - - [ Ximin Luo ] - * Depend on rustc 1.24 or later. - * Backport a patch to not require dev-dependencies when not needed. - - -- Vasudev Kamath Thu, 22 Mar 2018 20:08:17 +0530 - cargo (0.26.0-0ubuntu2) bionic; urgency=medium * Fix missing quotes in debian/rules, which resulted in all test failures @@ -1085,6 +1223,25 @@ -- Chris Coulson Fri, 13 Apr 2018 18:52:29 +0100 +cargo (0.25.0-3) unstable; urgency=medium + + [ Ximin Luo ] + * Update Vcs-* fields to salsa + + [ Vasudev Kamath ] + * Add patch to prevent incremental builds on sparc64. + Closes: bug#895300, Thanks to John Paul Adrian Glaubitz. + + -- Vasudev Kamath Sun, 15 Apr 2018 12:28:29 +0530 + +cargo (0.25.0-2) unstable; urgency=medium + + [ Ximin Luo ] + * Depend on rustc 1.24 or later. + * Backport a patch to not require dev-dependencies when not needed. + + -- Vasudev Kamath Thu, 22 Mar 2018 20:08:17 +0530 + cargo (0.25.0-1ubuntu1) bionic; urgency=medium [ Rico Tzschichholz ] @@ -1224,6 +1381,28 @@ -- Vasudev Kamath Tue, 05 Dec 2017 22:03:49 +0530 +cargo (0.23.0-0ubuntu1) bionic; urgency=medium + + * Update to 0.23.0 + + * Refresh patches + - update debian/patches/2004_clean-cargo-deps.patch + * Drop patches that are fixed upstream + - remove debian/patches/1001_fix_spelling_errors.patch + - update debian/patches/series + * Don't strip libgit2 from the tarball + - update debian/vendor-tarball-filter.txt + - remove debian/libgit2 + - update debian/rules + - update debian/copyright + - update debian/README.source + * Don't depend on mdbook when generating the documentation, as nothing in + the archive provides it and it isn't needed + - add debian/patches/dont-depend-on-mdbook.patch + - update debian/patches/series + + -- Chris Coulson Thu, 30 Nov 2017 16:22:38 +0000 + cargo (0.22.0-1~exp1) experimental; urgency=medium * New upstream release. @@ -1251,34 +1430,6 @@ -- Vasudev Kamath Sun, 29 Oct 2017 19:50:42 +0530 -cargo (0.21.1-2) unstable; urgency=medium - - * Upload to unstable. - - -- Ximin Luo Wed, 25 Oct 2017 23:30:46 +0200 - -cargo (0.23.0-0ubuntu1) bionic; urgency=medium - - * Update to 0.23.0 - - * Refresh patches - - update debian/patches/2004_clean-cargo-deps.patch - * Drop patches that are fixed upstream - - remove debian/patches/1001_fix_spelling_errors.patch - - update debian/patches/series - * Don't strip libgit2 from the tarball - - update debian/vendor-tarball-filter.txt - - remove debian/libgit2 - - update debian/rules - - update debian/copyright - - update debian/README.source - * Don't depend on mdbook when generating the documentation, as nothing in - the archive provides it and it isn't needed - - add debian/patches/dont-depend-on-mdbook.patch - - update debian/patches/series - - -- Chris Coulson Thu, 30 Nov 2017 16:22:38 +0000 - cargo (0.22.0-0ubuntu1) bionic; urgency=medium * Update to 0.22.0 @@ -1289,6 +1440,12 @@ -- Chris Coulson Thu, 26 Oct 2017 17:09:43 +0100 +cargo (0.21.1-2) unstable; urgency=medium + + * Upload to unstable. + + -- Ximin Luo Wed, 25 Oct 2017 23:30:46 +0200 + cargo (0.21.1-1ubuntu1) artful; urgency=medium * Merge from Debian, remaining changes: diff -Nru cargo-0.62.0ubuntu0libgit2/debian/control cargo-0.66.0+ds0ubuntu0.libgit2/debian/control --- cargo-0.62.0ubuntu0libgit2/debian/control 2022-09-16 15:27:41.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/control 2023-01-18 20:42:34.000000000 +0000 @@ -11,22 +11,25 @@ Build-Depends: debhelper (>= 11~), dpkg-dev (>= 1.17.14), - cargo:native (>= 0.17.0), - rustc:native (>= 1.16), - libstd-rust-dev (>= 1.16), + cargo:native (>= 0.56.0), + rustc:native (>= 1.63), + libstd-rust-dev (>= 1.63), pkg-config, - cmake, bash-completion, python3:native, libcurl4-gnutls-dev | libcurl4-openssl-dev, libssh2-1-dev, libssl-dev, zlib1g-dev, + zlib1g-dev:native, git Homepage: https://crates.io/ Standards-Version: 4.2.1 -Vcs-Git: https://salsa.debian.org/rust-team/cargo.git -Vcs-Browser: https://salsa.debian.org/rust-team/cargo +XSBC-Original-Vcs-Git: https://salsa.debian.org/rust-team/cargo.git +XSBC-Original-Vcs-Browser: https://salsa.debian.org/rust-team/cargo +Vcs-Git: https://git.launchpad.net/~canonical-foundations/ubuntu/+source/cargo +Vcs-Browser: https://git.launchpad.net/~canonical-foundations/ubuntu/+source/cargo +XS-Vendored-Sources-Rust: adler@1.0.2, aho-corasick@0.7.20, anyhow@1.0.68, arrayvec@0.5.2, atty@0.2.14, autocfg@1.1.0, base64@0.13.1, bitflags@1.3.2, bitmaps@2.1.0, block-buffer@0.10.3, bstr@0.2.17, bstr@1.1.0, bytes@1.3.0, bytesize@1.1.0, cc@1.0.78, cfg-if@1.0.0, clap@3.2.23, clap_lex@0.2.4, combine@4.6.6, commoncrypto-sys@0.2.0, commoncrypto@0.2.0, concolor-query@0.0.5, concolor@0.0.8, content_inspector@0.2.4, core-foundation-sys@0.8.3, core-foundation@0.9.3, cpufeatures@0.2.5, crc32fast@1.3.2, crypto-common@0.1.6, crypto-hash@0.3.4, curl-sys@0.4.59+curl-7.86.0, curl@0.4.44, digest@0.10.6, dunce@1.0.3, either@1.8.0, env_logger@0.7.1, env_logger@0.9.3, fastrand@1.8.0, filetime@0.2.19, flate2@1.0.25, fnv@1.0.7, foreign-types-shared@0.1.1, foreign-types@0.3.2, form_urlencoded@1.1.0, fwdansi@1.1.0, generic-array@0.14.6, git2-curl@0.17.0, git2@0.16.0, glob@0.3.1, globset@0.4.10, hashbrown@0.12.3, hex@0.4.3, hmac@0.12.1, home@0.5.4, humantime@1.3.0, humantime@2.1.0, idna@0.3.0, ignore@0.4.19, im-rc@15.1.0, indexmap@1.9.2, itertools@0.10.5, itoa@1.0.5, jobserver@0.1.25, kstring@2.0.0, lazy_static@1.4.0, lazycell@1.3.0, libc@0.2.139, libgit2-sys@0.14.1+1.5.0, libnghttp2-sys@0.1.7+1.45.0, libssh2-sys@0.2.23, libz-sys@1.1.8, log@0.4.17, memchr@2.5.0, miniz_oxide@0.6.2, miow@0.3.7, normalize-line-endings@0.3.0, once_cell@1.17.0, opener@0.5.0, openssl-macros@0.1.0, openssl-probe@0.1.5, openssl-sys@0.9.80, openssl@0.10.45, os_info@3.5.1, os_str_bytes@6.4.1, pathdiff@0.2.1, percent-encoding@2.2.0, pkg-config@0.3.26, pretty_env_logger@0.4.0, proc-macro2@1.0.49, quick-error@1.2.3, quote@1.0.23, rand_core@0.6.4, rand_xoshiro@0.6.0, redox_syscall@0.2.16, regex-automata@0.1.10, regex-syntax@0.6.28, regex@1.7.0, remove_dir_all@0.5.3, rustc-workspace-hack@1.0.0, rustfix@0.6.1, ryu@1.0.12, same-file@1.0.6, schannel@0.1.19, semver@1.0.16, serde@1.0.152, serde_derive@1.0.152, serde_ignored@0.1.7, serde_json@1.0.91, sha1@0.10.5, shell-escape@0.1.5, similar@2.2.1, sized-chunks@0.6.5, snapbox-macros@0.3.1, snapbox@0.3.3, socket2@0.4.7, static_assertions@1.1.0, strip-ansi-escapes@0.1.1, strsim@0.10.0, subtle@2.4.1, syn@1.0.107, tar@0.4.38, tempfile@3.3.0, termcolor@1.1.3, textwrap@0.16.0, thread_local@1.1.4, tinyvec@1.6.0, tinyvec_macros@0.1.0, toml_edit@0.14.4, typenum@1.16.0, unicode-bidi@0.3.8, unicode-ident@1.0.6, unicode-normalization@0.1.22, unicode-width@0.1.10, unicode-xid@0.2.4, url@2.3.1, utf8parse@0.2.0, vcpkg@0.2.15, version_check@0.9.4, vte@0.10.1, vte_generate_state_changes@0.1.1, walkdir@2.3.2, winapi-i686-pc-windows-gnu@0.4.0, winapi-util@0.1.5, winapi-x86_64-pc-windows-gnu@0.4.0, winapi@0.3.9, yansi@0.5.1 Package: cargo Architecture: any diff -Nru cargo-0.62.0ubuntu0libgit2/debian/copyright cargo-0.66.0+ds0ubuntu0.libgit2/debian/copyright --- cargo-0.62.0ubuntu0libgit2/debian/copyright 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/copyright 2023-01-17 14:05:25.000000000 +0000 @@ -1,16 +1,12 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: cargo Source: https://github.com/rust-lang/cargo -Files-Excluded: -# We exclude the bench workspaces as they are full projects with their own -# copyright issues - benches/workspaces/* Files: + benches/* crates/* src/* tests/* - benches/* .* build.rs Cargo.* @@ -79,29 +75,27 @@ 2019-2020 The Rand Project Developers 2010-2020 The Rust Project Developers License: MIT or Apache-2.0 -Comment: - see https://github.com/rust-random/rand +Comment: see https://github.com/rust-random/rand Files: vendor/aho-corasick/* - vendor/memchr/* - vendor/termcolor/* + vendor/bytesize/* vendor/globset/* vendor/ignore/* + vendor/memchr/* vendor/same-file/* + vendor/termcolor/* vendor/walkdir/* vendor/winapi-util/* - vendor/bytesize/* Copyright: 2015-2018 Andrew Gallant License: MIT or Unlicense Comment: see upstream projects, - * https://github.com/docopt/docopt.rs * https://github.com/BurntSushi/aho-corasick - * https://github.com/BurntSushi/rust-memchr - * https://github.com/BurntSushi/ripgrep/tree/master/termcolor * https://github.com/BurntSushi/ripgrep/tree/master/globset * https://github.com/BurntSushi/ripgrep/tree/master/ignore + * https://github.com/BurntSushi/rust-memchr * https://github.com/BurntSushi/same-file + * https://github.com/BurntSushi/ripgrep/tree/master/termcolor * https://github.com/BurntSushi/walkdir * https://github.com/BurntSushi/winapi-util @@ -126,13 +120,25 @@ see https://github.com/bluss/either see https://github.com/rust-itertools/itertools +Files: vendor/base64/* +Copyright: 2015-2023 Alice Maz + 2015-2023 Marshall Pierce +License: MIT or Apache-2.0 +Comment: see https://github.com/marshallpierce/rust-base64 + Files: vendor/bitmaps/* Copyright: 2019-2020 Bodil Stokke License: MPL-2.0+ Comment: see https://github.com/bodil/bitmaps -Files: +Files: vendor/block-buffer/* +Copyright: 2016-2023 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/utils + +Files: vendor/bstr/* + vendor/bstr-*/* Copyright: 2015-2019 Andrew Gallant License: MIT or Apache-2.0 Comment: @@ -148,11 +154,34 @@ License: Apache-2.0 or MIT Comment: see https://github.com/cuviper/autocfg +Files: vendor/bytes/* +Copyright: 2015-2019 Carl Lerche +License: MIT +Comment: see https://github.com/carllerche/bytes + Files: vendor/clap/* vendor/clap_lex/* -Copyright: 2015-2016, Kevin B. Knapp +Copyright: 2015-2022, Kevin B. Knapp + 2015-2022, Clap Contributors +License: MIT or Apache-2.0 +Comment: see https://github.com/clap-rs/clap + +Files: vendor/combine/* +Copyright: 2015-2022 Markus Westerlind License: MIT +Comment: see https://github.com/Marwes/combine + +Files: vendor/concolor/* + vendor/concolor-query/* +Copyright: 2021-2022 Ed Page +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-cli/concolor + +Files: vendor/content_inspector/* +Copyright: 2018-2018 David Peter +License: MIT or Apache-2.0 +Comment: see https://github.com/sharkdp/content_inspector Files: vendor/core-foundation/* vendor/core-foundation-sys/* @@ -161,17 +190,26 @@ License: MIT or Apache-2.0 Comment: see https://github.com/servo/core-foundation-rs +Files: vendor/cpufeatures/* +Copyright: 2016-2023 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/utils + Files: vendor/crc32fast/* Copyright: 2018, Sam Rijs 2018, Alex Crichton License: MIT or Apache-2.0 -Files: - vendor/crossbeam-utils/* +Files: vendor/crossbeam-utils/* Copyright: 2017-2018 The Crossbeam Project Developers License: MIT or Apache-2.0 Comment: see https://github.com/crossbeam-rs +Files: vendor/crypto-common/* +Copyright: 2017-2023 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/traits + Files: vendor/commoncrypto/* vendor/commoncrypto-sys/* vendor/crypto-hash/* @@ -188,18 +226,44 @@ License: MIT Comment: see https://github.com/alexcrichton/curl-rust +Files: vendor/digest/* +Copyright: 2017-2023 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/traits + +Files: vendor/dunce/* +Copyright: 2017-2021 Kornel +License: CC0-1.0 +Comment: see https://gitlab.com/kornelski/dunce + Files: vendor/fastrand/* -Copyright: 2020 Stjepan Glavina -License: MIT or Apache-2.0 +Copyright: 2020-2022 Stjepan Glavina +License: Apache-2.0 OR MIT +Comment: see https://github.com/smol-rs/fastrand -Files: - vendor/hex/* +Files: vendor/generic-array/* +Copyright: 2015-2022 Bartłomiej Kamiński + 2015-2022 Aaron Trent +License: MIT +Comment: see https://github.com/fizyk20/generic-array.git + +Files: vendor/hashbrown/* +Copyright: 2018-2022 Amanieu d'Antras +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-lang/hashbrown + +Files: vendor/hex/* Copyright: 2015-2019 KokaKiwi 2015-2019 rust-hex Developers License: MIT or Apache-2.0 Comment: see https://github.com/KokaKiwi/rust-hex +Files: vendor/hmac/* +Copyright: 2017-2023 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/MACs + Files: vendor/home/* Copyright: Brian Anderson License: MIT or Apache-2.0 @@ -225,6 +289,13 @@ see https://github.com/bodil/im-rs see https://github.com/bodil/sized-chunks +Files: vendor/indexmap/* +Copyright: + 2016-2021 bluss + 2017-2022 Josh Stone +License: Apache-2.0 OR MIT +Comment: see https://github.com/bluss/indexmap + Files: vendor/itoa/* vendor/quote/* Copyright: 2016-2017 David Tolnay @@ -248,6 +319,11 @@ 1991-2015 Unicode, Inc License: MIT or Apache-2.0 +Files: vendor/kstring/* +Copyright: 2014-2022 Ed Page +License: MIT OR Apache-2.0 +Comment: see https://github.com/cobalt-org/kstring + Files: vendor/lazycell/* Copyright: 20014, The Rust Project Developers 2016-2017, Nikita Pekin and lazycell contributors @@ -264,11 +340,14 @@ License: MIT Comment: see https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide -Files: vendor/bytes/* -Copyright: - Carl Lerche , - Sean McArthur -License: MIT +Files: vendor/normalize-line-endings/* +Copyright: 2016-2018 Richard Dodd +License: Apache-2.0 +Comment: see https://github.com/derekdreery/normalize-line-endings + +Files: vendor/num_cpus/* +Copyright: 2015, Sean McArthur +License: MIT or Apache-2.0 Files: vendor/once_cell/* Copyright: 2018-2021 Aleksey Kladov @@ -281,26 +360,37 @@ Comment: see https://github.com/Seeker14491/opener Files: vendor/openssl/* -Copyright: 2013-2015 Steven Fackler +Copyright: 2013-2022 Steven Fackler 2013 Jack Lloyd 2011 Google Inc. License: Apache-2.0 +Files: vendor/openssl-macros/* +Copyright: 2022 Steven Fackler +License: MIT or Apache-2.0 +Comment: see https://github.com/sfackler/rust-openssl + Files: vendor/openssl-sys/* Copyright: 2015 Steven Fackler 2015 Alex Crichton License: MIT Comment: see https://github.com/sfackler/rust-openssl -Files: vendor/openssl-macros/* -Copyright: 2015 Steven Fackler -License: MIT or Apache-2.0 - Files: vendor/os_info/* -Copyright: - 2017-2020 Jan Schulte - 2017-2022 Stanislav Tkach +Copyright: 2015-2022 Jan Schulte + 2015-2022 Stanislav Tkach License: MIT +Comment: see https://github.com/stanislav-tkach/os_info + +Files: vendor/os_str_bytes/* +Copyright: 2019-2022 Dylan Iuzzolino +License: MIT OR Apache-2.0 +Comment: see https://github.com/dylni/os_str_bytes + +Files: vendor/pathdiff/* +Copyright: 2017-2021 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/Manishearth/pathdiff Files: vendor/pretty_env_logger/* Copyright: 2016-2019 Sean McArthur @@ -349,6 +439,29 @@ Comment: see https://github.com/serde-rs see https://github.com/dtolnay/serde-ignored +Files: vendor/sha1/* +Copyright: 2016-2022 RustCrypto Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/RustCrypto/hashes + +Files: vendor/similar/* +Copyright: 2021-2022 Armin Ronacher + 2021-2022 Pierre-Étienne Meunier + 2021-2022 Brandon Williams +License: Apache-2.0 +Comment: see https://github.com/mitsuhiko/similar + +Files: vendor/snapbox/* + vendor/snapbox-macros/* +Copyright: 2015-2022 The assert_cli Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/assert-rs/trycmd/ + +Files: vendor/static_assertions/* +Copyright: 2017-2020 Nikolai Vazquez +License: MIT OR Apache-2.0 +Comment: see https://github.com/nvzqz/static-assertions-rs + Files: vendor/strip-ansi-escapes/* Copyright: 2017-2018 Ted Mielczarek License: Apache-2.0 or MIT @@ -359,6 +472,12 @@ License: MIT Comment: see https://github.com/dguo/strsim-rs +Files: vendor/subtle/* +Copyright: 2017-2021 Isis Lovecruft + 2017-2021 Henry de Valence +License: BSD-3-Clause +Comment: see https://github.com/dalek-cryptography/subtle + Files: vendor/syn/* Copyright: 2016-2017 David Tolnay License: MIT or Apache-2.0 @@ -372,9 +491,7 @@ Copyright: 2015, Steven Allen License: MIT or Apache-2.0 -Files: - vendor/thread_local/* - vendor/hashbrown/* +Files: vendor/thread_local/* Copyright: 2016 Amanieu d'Antras License: MIT or Apache-2.0 Comment: see https://github.com/Amanieu/thread_local-rs @@ -389,6 +506,12 @@ License: MIT OR Apache-2.0 OR Zlib Comment: see https://github.com/Soveu/tinyvec_macros +Files: vendor/toml_edit/* +Copyright: 2017-2022 Andronik Ordian + 2017-2022 Ed Page +License: MIT or Apache-2.0 +Comment: see https://github.com/ordian/toml_edit + Files: vendor/typenum/* Copyright: 2015-2018 Paho Lurie-Gregg 2015-2018 Andre Bogus @@ -400,6 +523,11 @@ License: MIT or Apache-2.0 Comment: see https://github.com/servo/unicode-bidi +Files: vendor/unicode-ident/* +Copyright: 2022-2022 David Tolnay +License: (MIT OR Apache-2.0) AND Unicode-DFS-2016 +Comment: see https://github.com/dtolnay/unicode-ident + Files: vendor/unicode-normalization/* Copyright: 2016 kwantam License: MIT or Apache-2.0 @@ -410,6 +538,11 @@ License: MIT or Apache-2.0 Comment: see https://github.com/unicode-rs/unicode-xid +Files: vendor/yansi/* +Copyright: 2017-2022 Sergio Benitez +License: MIT or Apache-2.0 +Comment: see https://github.com/SergioBenitez/yansi + Files: vendor/form_urlencoded/* vendor/url/* @@ -459,48 +592,6 @@ License: MIT or Apache-2.0 Comment: see https://github.com/retep998/winapi-rs -Files: - vendor/windows_aarch64_msvc/* - vendor/windows_i686_gnu/* - vendor/windows_i686_msvc/* - vendor/windows_x86_64_msvc/* - vendor/windows_x86_64_gnu/* - vendor/windows-sys/* -Copyright: Microsoft -License: MIT OR Apache-2.0 - -Files: vendor/unicode-ident/* -Copyright: David Tolnay -License: MIT or Apache-2.0 - -Files: vendor/unicode-ident/src/tables.rs -Copyright: - Unicode, Inc, - David Tolnay -License: Unicode-DFS-2016 - -Files: - vendor/toml_edit/* - vendor/kstring/* -Copyright: - Andronik Ordian , - Ed Page -License: MIT or Apache-2.0 - -Files: vendor/indexmap/* -Copyright: - bluss, - Josh Stone -License: MIT or Apache-2.0 - -Files: vendor/os_str_bytes/* -Copyright: dylni -License: MIT or Apache-2.0 - -Files: vendor/combine/* -Copyright: Markus Westerlind -License: MIT - Files: debian/* Copyright: 2016-2019 Ximin Luo @@ -573,6 +664,10 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +License: CC0-1.0 + On Debian systems, see /usr/share/common-licenses/CC0-1.0 for + the full text of the CC0 1.0 Universal license. + License: ISC Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff -Nru cargo-0.62.0ubuntu0libgit2/debian/debcargo-conf.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-conf.patch --- cargo-0.62.0ubuntu0libgit2/debian/debcargo-conf.patch 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-conf.patch 2023-01-17 13:25:36.000000000 +0000 @@ -7,10 +7,298 @@ even un-re-written ones that were published to crates.io. The patch below rewrites our existing patches so they work against the un-re-written ones. -- our patch to miniz_oxide replaces the adler dep for the adler32 dep. This - interferes with our primitive logic in debian-cargo-vendor, so we have to - undo that here. +- unicode-normalization, vte, tempfile: have dependency relaxation that applies, + but doesn't match the vendored copy +- concolor: more recent version in debcargo-conf, can be dropped once cargo + upstream updates + +- clap: clap is v4 in debcargo-conf, patches from clap-3 temporarily patched in + until we update to a cargo version using clap 4.x + +diff --git a/src/clap/debian/patches/disable-derive-deprecated.patch b/src/clap/debian/patches/disable-derive-deprecated.patch +new file mode 100644 +index 000000000..6ed82171f +--- /dev/null ++++ b/src/clap/debian/patches/disable-derive-deprecated.patch +@@ -0,0 +1,11 @@ ++--- a/Cargo.toml +++++ b/Cargo.toml ++@@ -418,7 +418,7 @@ ++ "color", ++ "suggestions", ++ ] ++-deprecated = ["clap_derive/deprecated"] +++deprecated = [] ++ derive = [ ++ "clap_derive", ++ "once_cell", +diff --git a/src/clap/debian/patches/disable-snapbox.patch b/src/clap/debian/patches/disable-snapbox.patch +index a6fbd083a..9335518c4 100644 +--- a/src/clap/debian/patches/disable-snapbox.patch ++++ b/src/clap/debian/patches/disable-snapbox.patch +@@ -1,6 +1,12 @@ + --- a/Cargo.toml + +++ b/Cargo.toml +-@@ -400,3 +399,0 @@ ++@@ -397,9 +397,6 @@ ++ [dev-dependencies.shlex] ++ version = "1.1.0" ++ + -[dev-dependencies.snapbox] +--version = "0.4" ++-version = "0.2.9" + - ++ [dev-dependencies.static_assertions] ++ version = "1.1.0" ++ +diff --git a/src/clap/debian/patches/disable-trycmd.diff b/src/clap/debian/patches/disable-trycmd.diff +index aeb0bbad4..053bf14f9 100644 +--- a/src/clap/debian/patches/disable-trycmd.diff ++++ b/src/clap/debian/patches/disable-trycmd.diff +@@ -1,8 +1,11 @@ + --- a/Cargo.toml + +++ b/Cargo.toml +-@@ -413,9 +412,0 @@ ++@@ -410,15 +410,6 @@ ++ [dev-dependencies.trybuild] ++ version = "1.0.18" ++ + -[dev-dependencies.trycmd] +--version = "0.14.3" ++-version = "0.13" + -features = [ + - "color-auto", + - "diff", +@@ -10,3 +13,6 @@ + -] + -default-features = false + - ++ [features] ++ cargo = ["once_cell"] ++ color = [ +diff --git a/src/clap/debian/patches/disable-unic-emoji-char.patch b/src/clap/debian/patches/disable-unic-emoji-char.patch +deleted file mode 100644 +index 97aa25af0..000000000 +--- a/src/clap/debian/patches/disable-unic-emoji-char.patch ++++ /dev/null +@@ -1,36 +0,0 @@ +-Index: clap/Cargo.toml +-=================================================================== +---- clap.orig/Cargo.toml +-+++ clap/Cargo.toml +-@@ -408,9 +408,6 @@ version = "1.1.0" +- [dev-dependencies.trybuild] +- version = "1.0.71" +- +--[dev-dependencies.unic-emoji-char] +--version = "0.9.0" +-- +- [features] +- cargo = ["dep:once_cell"] +- color = [ +-Index: clap/src/output/textwrap/core.rs +-=================================================================== +---- clap.orig/src/output/textwrap/core.rs +-+++ clap/src/output/textwrap/core.rs +-@@ -90,7 +90,7 @@ mod tests { +- #[cfg(feature = "unicode")] +- use unicode_width::UnicodeWidthChar; +- +-- #[test] +-+ /*#[test] +- fn emojis_have_correct_width() { +- use unic_emoji_char::is_emoji; +- +-@@ -129,7 +129,7 @@ mod tests { +- +- // The remaining planes contain almost no assigned code points +- // and thus also no emojis. +-- } +-+ }*/ +- +- #[test] +- #[cfg(feature = "unicode")] +diff --git a/src/clap/debian/patches/disable-unstable-doc.patch b/src/clap/debian/patches/disable-unstable-doc.patch +index 00de9ce79..404f1d9cf 100644 +--- a/src/clap/debian/patches/disable-unstable-doc.patch ++++ b/src/clap/debian/patches/disable-unstable-doc.patch +@@ -1,25 +1,38 @@ + --- a/Cargo.toml + +++ b/Cargo.toml +-@@ -39,3 +39,2 @@ ++@@ -37,7 +37,6 @@ ++ repository = "https://github.com/clap-rs/clap" ++ + [package.metadata.docs.rs] + -features = ["unstable-doc"] + rustdoc-args = [ +-@@ -49,5 +48,2 @@ ++ "--cfg", ++ "docsrs", ++@@ -47,9 +46,6 @@ ++ "-Zrustdoc-scrape-examples=examples", ++ ] + + -[package.metadata.playground] + -features = ["unstable-doc"] + - + [package.metadata.release] +-@@ -439,12 +435,2 @@ ++ shared-version = true ++ tag-name = "v{{version}}" ++@@ -437,17 +433,6 @@ ++ "textwrap/unicode-width", ++ "unicase", + ] + -unstable-doc = [ + - "derive", + - "cargo", + - "wrap_help", ++- "yaml", + - "env", + - "unicode", +-- "string", ++- "regex", + - "unstable-replace", + - "unstable-grouped", + -] + unstable-grouped = [] ++ unstable-replace = [] ++ unstable-v4 = [ +diff --git a/src/clap/debian/patches/disable-unstable-v4.patch b/src/clap/debian/patches/disable-unstable-v4.patch +new file mode 100644 +index 000000000..2993a959a +--- /dev/null ++++ b/src/clap/debian/patches/disable-unstable-v4.patch +@@ -0,0 +1,13 @@ ++--- a/Cargo.toml +++++ b/Cargo.toml ++@@ -435,10 +435,6 @@ ++ ] ++ unstable-grouped = [] ++ unstable-replace = [] ++-unstable-v4 = [ ++- "clap_derive/unstable-v4", ++- "deprecated", ++-] ++ wrap_help = [ ++ "terminal_size", ++ "textwrap/terminal_size", +diff --git a/src/clap/debian/patches/disable-unstable-v5.patch b/src/clap/debian/patches/disable-unstable-v5.patch +deleted file mode 100644 +index 5c2a59a30..000000000 +--- a/src/clap/debian/patches/disable-unstable-v5.patch ++++ /dev/null +@@ -1,7 +0,0 @@ +---- a/Cargo.toml +-+++ b/Cargo.toml +-@@ -438,4 +437,0 @@ +--unstable-v5 = [ +-- "clap_derive?/unstable-v5", +-- "deprecated", +--] +diff --git a/src/clap/debian/patches/once-cell-non-optional.patch b/src/clap/debian/patches/once-cell-non-optional.patch +new file mode 100644 +index 000000000..0e6692e81 +--- /dev/null ++++ b/src/clap/debian/patches/once-cell-non-optional.patch +@@ -0,0 +1,29 @@ ++--- a/Cargo.toml +++++ b/Cargo.toml ++@@ -354,7 +354,6 @@ ++ ++ [dependencies.once_cell] ++ version = "1.12.0" ++-optional = true ++ ++ [dependencies.regex] ++ version = "1.0" ++@@ -404,7 +403,7 @@ ++ version = "1.0.18" ++ ++ [features] ++-cargo = ["once_cell"] +++cargo = [] ++ color = [ ++ "atty", ++ "termcolor", ++@@ -420,8 +419,7 @@ ++ ] ++ deprecated = [] ++ derive = [ ++- "clap_derive", ++- "once_cell", +++ "clap_derive" ++ ] ++ env = [] ++ std = ["indexmap/std"] +diff --git a/src/clap/debian/patches/revert-switch-to-is-terminal.patch b/src/clap/debian/patches/revert-switch-to-is-terminal.patch +deleted file mode 100644 +index 425ff3aca..000000000 +--- a/src/clap/debian/patches/revert-switch-to-is-terminal.patch ++++ /dev/null +@@ -1,44 +0,0 @@ +-Index: clap/src/output/fmt.rs +-=================================================================== +---- clap.orig/src/output/fmt.rs +-+++ clap/src/output/fmt.rs +-@@ -82,9 +82,10 @@ impl std::fmt::Display for Colorizer { +- +- #[cfg(feature = "color")] +- fn is_a_tty(stream: Stream) -> bool { +-- use is_terminal::IsTerminal; +-- match stream { +-- Stream::Stdout => std::io::stdout().is_terminal(), +-- Stream::Stderr => std::io::stderr().is_terminal(), +-- } +-+ let stream = match stream { +-+ Stream::Stdout => atty::Stream::Stdout, +-+ Stream::Stderr => atty::Stream::Stderr, +-+ }; +-+ +-+ atty::is(stream) +- } +-Index: clap/Cargo.toml +-=================================================================== +---- clap.orig/Cargo.toml +-+++ clap/Cargo.toml +-@@ -365,8 +365,8 @@ optional = true +- [dependencies.clap_lex] +- version = "0.3.0" +- +--[dependencies.is-terminal] +--version = "0.4.1" +-+[dependencies.atty] +-+version = "0.2" +- optional = true +- +- [dependencies.once_cell] +-@@ -414,7 +414,7 @@ version = "0.9.0" +- [features] +- cargo = ["dep:once_cell"] +- color = [ +-- "dep:is-terminal", +-+ "dep:atty", +- "dep:termcolor", +- ] +- debug = [ +diff --git a/src/clap/debian/patches/series b/src/clap/debian/patches/series +index 137658685..47bdb2c6b 100644 +--- a/src/clap/debian/patches/series ++++ b/src/clap/debian/patches/series +@@ -1,6 +1,6 @@ + disable-trycmd.diff + disable-unstable-doc.patch +-disable-unstable-v5.patch ++disable-unstable-v4.patch + disable-snapbox.patch +-revert-switch-to-is-terminal.patch +-disable-unic-emoji-char.patch ++disable-derive-deprecated.patch ++once-cell-non-optional.patch +diff --git a/src/commoncrypto-sys/debian/patches/no-clippy.patch b/src/commoncrypto-sys/debian/patches/no-clippy.patch +index 3e4c8850e..93789f3b8 100644 --- a/src/commoncrypto-sys/debian/patches/no-clippy.patch +++ b/src/commoncrypto-sys/debian/patches/no-clippy.patch @@ -1,17 +1,16 @@ @@ -42,6 +330,8 @@ +- + [dev-dependencies] + hex = "0.2" +diff --git a/src/commoncrypto/debian/patches/no-clippy.patch b/src/commoncrypto/debian/patches/no-clippy.patch +index 38d9c9255..b21a7cae5 100644 --- a/src/commoncrypto/debian/patches/no-clippy.patch +++ b/src/commoncrypto/debian/patches/no-clippy.patch @@ -1,17 +1,16 @@ @@ -73,9 +363,204 @@ +- + [dev-dependencies] + hex = "0.2" ---- a/src/miniz_oxide/debian/patches/series -+++ b/src/miniz_oxide/debian/patches/series -@@ -1,3 +1,2 @@ - remove-rustc-dep-of-std-etc.patch - remove-compiler-builtins.patch --use-adler32.patch +diff --git a/src/concolor/debian/patches/series b/src/concolor/debian/patches/series +index cdf075927..942673b44 100644 +--- a/src/concolor/debian/patches/series ++++ b/src/concolor/debian/patches/series +@@ -1,2 +1,2 @@ + avoid-doctest-breakage.patch +-switch-back-to-atty.patch ++#switch-back-to-atty.patch +diff --git a/src/tempfile/debian/patches/series b/src/tempfile/debian/patches/series +index 75abb7f14..2378a84ba 100644 +--- a/src/tempfile/debian/patches/series ++++ b/src/tempfile/debian/patches/series +@@ -1 +1 @@ +-relax-dep.diff ++#relax-dep.diff +diff --git a/src/unicode-normalization/debian/patches/series b/src/unicode-normalization/debian/patches/series +index 2c1db10bd..39fe7a4da 100644 +--- a/src/unicode-normalization/debian/patches/series ++++ b/src/unicode-normalization/debian/patches/series +@@ -1,2 +1 @@ + disable-tests-missing-testdata.patch +-switch-back-to-smallvec.patch +diff --git a/src/unicode-normalization/debian/patches/switch-back-to-smallvec.patch b/src/unicode-normalization/debian/patches/switch-back-to-smallvec.patch +deleted file mode 100644 +index 06e816ca7..000000000 +--- a/src/unicode-normalization/debian/patches/switch-back-to-smallvec.patch ++++ /dev/null +@@ -1,134 +0,0 @@ +-This patch switches back to using smallvec as we do not have tinyvec in Debian. +-It is based on a revert of upstream commit d6abe8e5148c2c513cb65f487a037c7600de2498 +-adapted by Peter Michael Green for use in the Debian package. +- +-Index: unicode-normalization/src/decompose.rs +-=================================================================== +---- unicode-normalization.orig/src/decompose.rs +-+++ unicode-normalization/src/decompose.rs +-@@ -10,7 +10,7 @@ +- use core::fmt::{self, Write}; +- use core::iter::Fuse; +- use core::ops::Range; +--use tinyvec::TinyVec; +-+use smallvec::SmallVec; +- +- #[derive(Clone)] +- enum DecompositionType { +-@@ -32,7 +32,7 @@ pub struct Decompositions { +- // 2) "Ready" characters which are sorted and ready to emit on demand; +- // 3) A "pending" block which stills needs more characters for us to be able +- // to sort in canonical order and is not safe to emit. +-- buffer: TinyVec<[(u8, char); 4]>, +-+ buffer: SmallVec<[(u8, char); 4]>, +- ready: Range, +- } +- +-@@ -41,7 +41,7 @@ pub fn new_canonical { +- iter: Decompositions, +- state: RecompositionState, +-- buffer: TinyVec<[char; 4]>, +-+ buffer: SmallVec<[char; 4]>, +- composee: Option, +- last_ccc: Option, +- } +-@@ -34,7 +34,7 @@ pub fn new_canonical> Iterator +- match self.iter.next() { +- Some(ch) => { +- // At this time, the longest replacement sequence has length 2. +-- let mut buffer = ArrayVec::<[char; 2]>::new(); +-+ let mut buffer = SmallVec::<[char; 2]>::new(); +- super::char::decompose_cjk_compat_variants(ch, |d| buffer.push(d)); +- self.buffer = buffer.get(1).copied(); +- Some(buffer[0]) +diff --git a/src/vte/debian/patches/arrayvec.diff b/src/vte/debian/patches/arrayvec.diff +deleted file mode 100644 +index 1923f9577..000000000 +--- a/src/vte/debian/patches/arrayvec.diff ++++ /dev/null +@@ -1,26 +0,0 @@ +-Index: vte/Cargo.toml +-=================================================================== +---- vte.orig/Cargo.toml +-+++ vte/Cargo.toml +-@@ -24,7 +24,7 @@ categories = ["parsing", "no-std"] +- license = "Apache-2.0 OR MIT" +- repository = "https://github.com/alacritty/vte" +- [dependencies.arrayvec] +--version = "0.5.1" +-+version = "0.7" +- optional = true +- default-features = false +- +-Index: vte/src/lib.rs +-=================================================================== +---- vte.orig/src/lib.rs +-+++ vte/src/lib.rs +-@@ -78,7 +78,7 @@ pub struct Parser { +- params: Params, +- param: u16, +- #[cfg(feature = "no_std")] +-- osc_raw: ArrayVec<[u8; MAX_OSC_RAW]>, +-+ osc_raw: ArrayVec, +- #[cfg(not(feature = "no_std"))] +- osc_raw: Vec, +- osc_params: [(usize, usize); MAX_OSC_PARAMS], +diff --git a/src/vte/debian/patches/series b/src/vte/debian/patches/series +index 011b1a629..203bdd762 100644 +--- a/src/vte/debian/patches/series ++++ b/src/vte/debian/patches/series +@@ -1,2 +1 @@ + 00-remove-nightly-feature +-arrayvec.diff diff -Nru cargo-0.62.0ubuntu0libgit2/debian/debcargo-ubuntu/0001-libgit2-re-enable-the-C-library-vendoring.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-ubuntu/0001-libgit2-re-enable-the-C-library-vendoring.patch --- cargo-0.62.0ubuntu0libgit2/debian/debcargo-ubuntu/0001-libgit2-re-enable-the-C-library-vendoring.patch 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-ubuntu/0001-libgit2-re-enable-the-C-library-vendoring.patch 2023-01-18 20:42:34.000000000 +0000 @@ -13,7 +13,7 @@ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libgit2-sys/debian/debcargo.toml b/src/libgit2-sys/debian/debcargo.toml -index 75f4d6ae1..9cb954489 100644 +index 0d1188a48..b8de81ac0 100644 --- a/src/libgit2-sys/debian/debcargo.toml +++ b/src/libgit2-sys/debian/debcargo.toml @@ -1,6 +1,5 @@ @@ -24,11 +24,10 @@ [packages.lib] diff --git a/src/libgit2-sys/debian/patches/series b/src/libgit2-sys/debian/patches/series -index 6eaa45026..f1b8f3d85 100644 +index 90136830c..4ffa526de 100644 --- a/src/libgit2-sys/debian/patches/series +++ b/src/libgit2-sys/debian/patches/series -@@ -1,3 +1,3 @@ - no-special-snowflake-env.patch +@@ -1,2 +1,2 @@ remove-zlib-ng-compat.patch -disable-vendor.patch +# disable-vendor.patch diff -Nru cargo-0.62.0ubuntu0libgit2/debian/debcargo-ubuntu/series cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-ubuntu/series --- cargo-0.62.0ubuntu0libgit2/debian/debcargo-ubuntu/series 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/debcargo-ubuntu/series 2023-01-18 20:42:34.000000000 +0000 @@ -1 +1 @@ -# 0001-libgit2-re-enable-the-C-library-vendoring.patch +0001-libgit2-re-enable-the-C-library-vendoring.patch diff -Nru cargo-0.62.0ubuntu0libgit2/debian/gbp.conf cargo-0.66.0+ds0ubuntu0.libgit2/debian/gbp.conf --- cargo-0.62.0ubuntu0libgit2/debian/gbp.conf 2022-06-08 08:41:49.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/gbp.conf 2022-12-01 12:18:16.000000000 +0000 @@ -10,6 +10,6 @@ ignore-branch = True sign-tags = True -# [import-orig] -# upstream-vcs-tag = %(version)s -# debian-branch = debian/experimental +[import-orig] +upstream-vcs-tag = %(version)s +debian-branch = debian/experimental diff -Nru cargo-0.62.0ubuntu0libgit2/debian/lintian-to-copyright.sh cargo-0.66.0+ds0ubuntu0.libgit2/debian/lintian-to-copyright.sh --- cargo-0.62.0ubuntu0libgit2/debian/lintian-to-copyright.sh 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/lintian-to-copyright.sh 2023-01-17 12:21:18.000000000 +0000 @@ -1,5 +1,5 @@ #!/bin/sh # Pipe the output of lintian into this. -sed -ne 's,.* file-without-copyright-information debian/copyright ,,p' | cut -d/ -f1-2 | sort -u | while read x; do +sed -ne 's,.* file-without-copyright-information ,,p' | cut -d/ -f1-2 | sort -u | while read x; do /usr/share/cargo/scripts/guess-crate-copyright "$x" done diff -Nru cargo-0.62.0ubuntu0libgit2/debian/make_orig_multi-pre-vendor.sh cargo-0.66.0+ds0ubuntu0.libgit2/debian/make_orig_multi-pre-vendor.sh --- cargo-0.62.0ubuntu0libgit2/debian/make_orig_multi-pre-vendor.sh 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/make_orig_multi-pre-vendor.sh 2023-01-18 20:42:34.000000000 +0000 @@ -15,9 +15,14 @@ # Drop the "vendored" feature since we patch it out of debcargo sed -i /vendored/d Cargo.toml -# Downgrade the git2-rs crates. Cannot be done via cargo update because it spans -# multiple crates -sed -i 's/git2 = "0.14.2"/git2 = "0.13.25"/' Cargo.toml -sed -i 's/libgit2-sys = ".*"/libgit2-sys = "^0.12"/' Cargo.toml -sed -i 's/git2-curl = ".*"/git2-curl = "^0.14.1"/' Cargo.toml -sed -i 's/git2 = "0.14.2"/git2 = "0.13.25"/' crates/cargo-test-support/Cargo.toml +# avoid pulling in windows-sys for now +cargo update -p schannel --precise 0.1.19 + +# pin the dependencies as Debian intended +cargo update -p ignore --precise 0.4.19 +cargo update -p regex --precise 1.7.0 +cargo update -p proc-macro2 --precise 1.0.49 +cargo update -p termcolor --precise 1.1.3 +cargo update -p git2 --precise 0.16.0 +cargo update -p libgit2-sys --precise 0.14.1+1.5.0 +cargo update -p unicode-bidi --precise 0.3.8 diff -Nru cargo-0.62.0ubuntu0libgit2/debian/make_orig_multi.sh cargo-0.66.0+ds0ubuntu0.libgit2/debian/make_orig_multi.sh --- cargo-0.62.0ubuntu0libgit2/debian/make_orig_multi.sh 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/make_orig_multi.sh 2023-01-17 14:08:25.000000000 +0000 @@ -31,9 +31,17 @@ # Extract cargo source cd "${TMPDIR}" mkdir cargo -tar -xaf "${TMPDIR}/cargo_${CARGO_VER}.orig.tar.xz" -C cargo --strip-components=1 +tar -xaf "${TMPDIR}/cargo_${CARGO_VER}.orig.tar.gz" -C cargo --strip-components=1 cd cargo +# special patch for CVE fix - we want to vendor the updated/fixed dependencies! +echo "Applying CVE-2022-46176 patches"; +for p in "${SRCDIR}/debian/patches/cve/"*.patch; do + echo "$(basename "$p")" + patch -p1 < "$p" + echo "$p" >> .cve-patches +done + # Download build-deps via cargo-vendor export GIT_AUTHOR_NAME="deb-build" export GIT_AUTHOR_EMAIL="<>" @@ -55,16 +63,25 @@ rm -rf vendor-scan +# special patch for CVE fix - unapply to keep orig.tar.gz pristine +echo "Unapplying CVE-2022-46176 patches"; +tac .cve-patches | while read p; do + echo "$(basename "$p")" + patch -Rp1 < "$p" +done +rm .cve-patches + # Pack it up, reproducibly -GZIP=-9n tar --sort=name \ +tar --sort=name \ + --auto-compress \ --mtime="./Cargo.lock" \ --owner=root --group=root \ - -czf "${TMPDIR}/cargo_${CARGO_VER}.orig-vendor.tar.gz" vendor + -cf "${TMPDIR}/cargo_${CARGO_VER}.orig-vendor.tar.xz" vendor # All is good, we are done! echo "Your files are available at:" -echo "${TMPDIR}/cargo_${CARGO_VER}.orig.tar.xz \\" -echo "${TMPDIR}/cargo_${CARGO_VER}.orig-vendor.tar.gz" +echo "${TMPDIR}/cargo_${CARGO_VER}.orig.tar.gz \\" +echo "${TMPDIR}/cargo_${CARGO_VER}.orig-vendor.tar.xz" echo "" echo "Unpacked cargo sources are available under:" echo "${TMPDIR}/cargo/" diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/0001-Force-back-the-git2-rs-crates.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/0001-Force-back-the-git2-rs-crates.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/0001-Force-back-the-git2-rs-crates.patch 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/0001-Force-back-the-git2-rs-crates.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -From e7e72a39a6ca3099c9a0acb587ab0d2e4d4e9646 Mon Sep 17 00:00:00 2001 -From: Simon Chopin -Date: Fri, 9 Sep 2022 17:42:44 +0200 -Subject: [PATCH] Force back the git2-rs crates - ---- - Cargo.toml | 6 +++--- - crates/cargo-test-support/Cargo.toml | 2 +- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index ee1ce8155..383c19693 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -29,8 +29,8 @@ pretty_env_logger = { version = "0.4", optional = true } - anyhow = "1.0" - filetime = "0.2.9" - flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } --git2 = "0.14.2" --git2-curl = "0.15.0" -+git2 = "0.13.25" -+git2-curl = "0.14.1" - glob = "0.3.0" - hex = "0.4" - home = "0.5" -@@ -41,7 +41,7 @@ jobserver = "0.1.24" - lazycell = "1.2.0" - libc = "0.2" - log = "0.4.6" --libgit2-sys = "0.13.2" -+libgit2-sys = "0.12.26+1.3.0" - memchr = "2.1.3" - opener = "0.5" - os_info = "3.0.7" -diff --git a/crates/cargo-test-support/Cargo.toml b/crates/cargo-test-support/Cargo.toml -index c5e65d14b..1b4da5a18 100644 ---- a/crates/cargo-test-support/Cargo.toml -+++ b/crates/cargo-test-support/Cargo.toml -@@ -13,7 +13,7 @@ cargo-test-macro = { path = "../cargo-test-macro" } - cargo-util = { path = "../cargo-util" } - filetime = "0.2" - flate2 = { version = "1.0", default-features = false, features = ["zlib"] } --git2 = "0.14.2" -+git2 = "0.13.25" - glob = "0.3" - itertools = "0.10.0" - lazy_static = "1.0" --- -2.34.1 - diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/0003-tests-add-missing-cross-disabled-checks.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/0003-tests-add-missing-cross-disabled-checks.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/0003-tests-add-missing-cross-disabled-checks.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/0003-tests-add-missing-cross-disabled-checks.patch 2023-01-17 12:21:18.000000000 +0000 @@ -0,0 +1,46 @@ +From 981279ccd8f7855faaed010bff0891afff588210 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= + +Date: Sat, 19 Nov 2022 10:24:08 +0100 +Subject: [PATCH] tests: add missing cross disabled checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cross_conmpile::alternate states it should only be used in test cases +after checking cross_compile::disabled(), which is missing here. these +tests fail despite setting CFG_DISABLE_CROSS_TESTS on i386, since both +the host and the alternate cross target would be i686 in that case. + +Signed-off-by: Fabian Grünbichler +--- + tests/testsuite/build_script.rs | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs +index 902364dff..e458b3262 100644 +--- a/tests/testsuite/build_script.rs ++++ b/tests/testsuite/build_script.rs +@@ -585,6 +585,9 @@ fn custom_build_linker_bad_host_with_arch() { + #[cargo_test] + fn custom_build_env_var_rustc_linker_cross_arch_host() { + let target = rustc_host(); ++ if cross_compile::disabled() { ++ return; ++ } + let cross_target = cross_compile::alternate(); + let p = project() + .file( +@@ -623,6 +626,9 @@ fn custom_build_env_var_rustc_linker_cross_arch_host() { + #[cargo_test] + fn custom_build_linker_bad_cross_arch_host() { + let target = rustc_host(); ++ if cross_compile::disabled() { ++ return; ++ } + let cross_target = cross_compile::alternate(); + let p = project() + .file( +-- +2.38.1 + diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/2002_disable-net-tests.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2002_disable-net-tests.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/2002_disable-net-tests.patch 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2002_disable-net-tests.patch 2023-01-17 13:46:33.000000000 +0000 @@ -45,12 +45,12 @@ .file( --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs -@@ -1642,7 +1642,7 @@ - t.join().unwrap(); +@@ -1584,7 +1584,7 @@ + .run(); } -#[cargo_test] +#[allow(dead_code)] fn api_curl_error() { // Registry has a network error. - let t = registry::RegistryBuilder::new().build_api_server(&|_headers| panic!("broke!")); + let _registry = registry::RegistryBuilder::new() diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/2003-workaround-qemu-vfork-command-not-found.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2003-workaround-qemu-vfork-command-not-found.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/2003-workaround-qemu-vfork-command-not-found.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2003-workaround-qemu-vfork-command-not-found.patch 2023-01-17 13:25:36.000000000 +0000 @@ -0,0 +1,17 @@ +--- a/crates/cargo-test-macro/src/lib.rs ++++ b/crates/cargo-test-macro/src/lib.rs +@@ -203,6 +203,14 @@ + } + }; + if !output.status.success() { ++ // Debian specific patch, upstream wontfix: ++ // qemu has a faulty vfork where it fails to fail if a command is not ++ // found, with a unix_wait_status of 32512, or 0x7f00, 7f meaning ++ // exit code 127. See https://github.com/rust-lang/rust/issues/90825 ++ use std::os::unix::process::ExitStatusExt; ++ if output.status.into_raw() == 0x7f00 { ++ return false; ++ } + panic!( + "expected command `{}` to be runnable, got error {}:\n\ + stderr:{}\n\ diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/2112-handle-4-siphasher-algorithms.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2112-handle-4-siphasher-algorithms.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/2112-handle-4-siphasher-algorithms.patch 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2112-handle-4-siphasher-algorithms.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -Bug: https://github.com/rust-lang/cargo/issues/10004 - ---- a/src/cargo/core/source/source_id.rs -+++ b/src/cargo/core/source/source_id.rs -@@ -621,7 +621,13 @@ - fn test_cratesio_hash() { - let config = Config::default().unwrap(); - let crates_io = SourceId::crates_io(&config).unwrap(); -- assert_eq!(crate::util::hex::short_hash(&crates_io), "1ecc6299db9ec823"); -+ assert!([ -+ "1ecc6299db9ec823", // 64 LE -+ "1285ae84e5963aae", // 32 LE -+ "eae4ba8cbf2ce1c7", // 64 BE -+ "b420f105fcaca6de", // 32 BE -+ ] -+ .contains(&crate::util::hex::short_hash(&crates_io).as_str())); - } - - /// A `Display`able view into a `SourceId` that will write it as a url diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/2200-workaround-x32-test.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2200-workaround-x32-test.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/2200-workaround-x32-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/2200-workaround-x32-test.patch 2023-01-17 12:21:18.000000000 +0000 @@ -0,0 +1,13 @@ +Bug: https://github.com/rust-lang/cargo/issues/10005 + +--- a/tests/testsuite/cfg.rs ++++ b/tests/testsuite/cfg.rs +@@ -272,7 +272,7 @@ + + // https://github.com/rust-lang/cargo/issues/5313 + #[cargo_test] +-#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))] ++#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu", target_pointer_width = "64"))] + fn cfg_looks_at_rustflags_for_target() { + let p = project() + .file( diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-01-validate-ssh-host.keys.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-01-validate-ssh-host.keys.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-01-validate-ssh-host.keys.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-01-validate-ssh-host.keys.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,586 @@ +This patch is based on the upstream commit described below, adapted for use +in the Debian package by Peter Michael Green. + +commit 1387fd4105b242fa2d24ad99d10a5b1af23f293e +Author: Eric Huss +Date: Wed Dec 7 18:52:00 2022 -0800 + + Validate SSH host keys + +Index: cargo/src/cargo/sources/git/known_hosts.rs +=================================================================== +--- /dev/null ++++ cargo/src/cargo/sources/git/known_hosts.rs +@@ -0,0 +1,439 @@ ++//! SSH host key validation support. ++//! ++//! A primary goal with this implementation is to provide user-friendly error ++//! messages, guiding them to understand the issue and how to resolve it. ++//! ++//! Note that there are a lot of limitations here. This reads OpenSSH ++//! known_hosts files from well-known locations, but it does not read OpenSSH ++//! config files. The config file can change the behavior of how OpenSSH ++//! handles known_hosts files. For example, some things we don't handle: ++//! ++//! - `GlobalKnownHostsFile` — Changes the location of the global host file. ++//! - `UserKnownHostsFile` — Changes the location of the user's host file. ++//! - `KnownHostsCommand` — A command to fetch known hosts. ++//! - `CheckHostIP` — DNS spoofing checks. ++//! - `VisualHostKey` — Shows a visual ascii-art key. ++//! - `VerifyHostKeyDNS` — Uses SSHFP DNS records to fetch a host key. ++//! ++//! There's also a number of things that aren't supported but could be easily ++//! added (it just adds a little complexity). For example, hashed hostnames, ++//! hostname patterns, and revoked markers. See "FIXME" comments littered in ++//! this file. ++ ++use git2::cert::Cert; ++use git2::CertificateCheckStatus; ++use std::collections::HashSet; ++use std::fmt::Write; ++use std::path::{Path, PathBuf}; ++ ++/// These are host keys that are hard-coded in cargo to provide convenience. ++/// ++/// If GitHub ever publishes new keys, the user can add them to their own ++/// configuration file to use those instead. ++/// ++/// The GitHub keys are sourced from or ++/// . ++/// ++/// These will be ignored if the user adds their own entries for `github.com`, ++/// which can be useful if GitHub ever revokes their old keys. ++static BUNDLED_KEYS: &[(&str, &str, &str)] = &[ ++ ("github.com", "ssh-ed25519", "AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl"), ++ ("github.com", "ecdsa-sha2-nistp256", "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg="), ++ ("github.com", "ssh-rsa", "AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="), ++]; ++ ++enum KnownHostError { ++ /// Some general error happened while validating the known hosts. ++ CheckError(anyhow::Error), ++ /// The host key was not found. ++ HostKeyNotFound { ++ hostname: String, ++ key_type: git2::cert::SshHostKeyType, ++ remote_host_key: String, ++ remote_fingerprint: String, ++ other_hosts: Vec, ++ }, ++ /// The host key was found, but does not match the remote's key. ++ HostKeyHasChanged { ++ hostname: String, ++ key_type: git2::cert::SshHostKeyType, ++ old_known_host: KnownHost, ++ remote_host_key: String, ++ remote_fingerprint: String, ++ }, ++} ++ ++impl From for KnownHostError { ++ fn from(err: anyhow::Error) -> KnownHostError { ++ KnownHostError::CheckError(err.into()) ++ } ++} ++ ++/// The location where a host key was located. ++#[derive(Clone)] ++enum KnownHostLocation { ++ /// Loaded from a file from disk. ++ File { path: PathBuf, lineno: u32 }, ++ /// Part of the hard-coded bundled keys in Cargo. ++ Bundled, ++} ++ ++/// The git2 callback used to validate a certificate (only ssh known hosts are validated). ++pub fn certificate_check( ++ cert: &Cert<'_>, ++ host: &str, ++ port: Option, ++) -> Result { ++ let Some(host_key) = cert.as_hostkey() else { ++ // Return passthrough for TLS X509 certificates to use whatever validation ++ // was done in git2. ++ return Ok(CertificateCheckStatus::CertificatePassthrough) ++ }; ++ // If a nonstandard port is in use, check for that first. ++ // The fallback to check without a port is handled in the HostKeyNotFound handler. ++ let host_maybe_port = match port { ++ Some(port) if port != 22 => format!("[{host}]:{port}"), ++ _ => host.to_string(), ++ }; ++ // The error message must be constructed as a string to pass through the libgit2 C API. ++ let err_msg = match check_ssh_known_hosts(host_key, &host_maybe_port) { ++ Ok(()) => { ++ return Ok(CertificateCheckStatus::CertificateOk); ++ } ++ Err(KnownHostError::CheckError(e)) => { ++ format!("error: failed to validate host key:\n{:#}", e) ++ } ++ Err(KnownHostError::HostKeyNotFound { ++ hostname, ++ key_type, ++ remote_host_key, ++ remote_fingerprint, ++ other_hosts, ++ }) => { ++ // Try checking without the port. ++ if port.is_some() ++ && !matches!(port, Some(22)) ++ && check_ssh_known_hosts(host_key, host).is_ok() ++ { ++ return Ok(CertificateCheckStatus::CertificateOk); ++ } ++ let key_type_short_name = key_type.short_name(); ++ let key_type_name = key_type.name(); ++ let known_hosts_location = user_known_host_location_to_add(); ++ let other_hosts_message = if other_hosts.is_empty() { ++ String::new() ++ } else { ++ let mut msg = String::from( ++ "Note: This host key was found, \ ++ but is associated with a different host:\n", ++ ); ++ for known_host in other_hosts { ++ let loc = match known_host.location { ++ KnownHostLocation::File { path, lineno } => { ++ format!("{} line {lineno}", path.display()) ++ } ++ KnownHostLocation::Bundled => format!("bundled with cargo"), ++ }; ++ write!(msg, " {loc}: {}\n", known_host.patterns).unwrap(); ++ } ++ msg ++ }; ++ format!("error: unknown SSH host key\n\ ++ The SSH host key for `{hostname}` is not known and cannot be validated.\n\ ++ \n\ ++ To resolve this issue, add the host key to {known_hosts_location}\n\ ++ \n\ ++ The key to add is:\n\ ++ \n\ ++ {hostname} {key_type_name} {remote_host_key}\n\ ++ \n\ ++ The {key_type_short_name} key fingerprint is: SHA256:{remote_fingerprint}\n\ ++ This fingerprint should be validated with the server administrator that it is correct.\n\ ++ {other_hosts_message}\n\ ++ See https://doc.rust-lang.org/nightly/cargo/appendix/git-authentication.html#ssh-known-hosts \ ++ for more information.\n\ ++ ") ++ } ++ Err(KnownHostError::HostKeyHasChanged { ++ hostname, ++ key_type, ++ old_known_host, ++ remote_host_key, ++ remote_fingerprint, ++ }) => { ++ let key_type_short_name = key_type.short_name(); ++ let key_type_name = key_type.name(); ++ let known_hosts_location = user_known_host_location_to_add(); ++ let old_key_resolution = match old_known_host.location { ++ KnownHostLocation::File { path, lineno } => { ++ let old_key_location = path.display(); ++ format!( ++ "removing the old {key_type_name} key for `{hostname}` \ ++ located at {old_key_location} line {lineno}, \ ++ and adding the new key to {known_hosts_location}", ++ ) ++ } ++ KnownHostLocation::Bundled => { ++ format!( ++ "adding the new key to {known_hosts_location}\n\ ++ The current host key is bundled as part of Cargo." ++ ) ++ } ++ }; ++ format!("error: SSH host key has changed for `{hostname}`\n\ ++ *********************************\n\ ++ * WARNING: HOST KEY HAS CHANGED *\n\ ++ *********************************\n\ ++ This may be caused by a man-in-the-middle attack, or the \ ++ server may have changed its host key.\n\ ++ \n\ ++ The {key_type_short_name} fingerprint for the key from the remote host is:\n\ ++ SHA256:{remote_fingerprint}\n\ ++ \n\ ++ You are strongly encouraged to contact the server \ ++ administrator for `{hostname}` to verify that this new key is \ ++ correct.\n\ ++ \n\ ++ If you can verify that the server has a new key, you can \ ++ resolve this error by {old_key_resolution}\n\ ++ \n\ ++ The key provided by the remote host is:\n\ ++ \n\ ++ {hostname} {key_type_name} {remote_host_key}\n\ ++ \n\ ++ See https://doc.rust-lang.org/nightly/cargo/appendix/git-authentication.html#ssh-known-hosts \ ++ for more information.\n\ ++ ") ++ } ++ }; ++ Err(git2::Error::new( ++ git2::ErrorCode::GenericError, ++ git2::ErrorClass::Callback, ++ err_msg, ++ )) ++} ++ ++/// Checks if the given host/host key pair is known. ++fn check_ssh_known_hosts( ++ cert_host_key: &git2::cert::CertHostkey<'_>, ++ host: &str, ++) -> Result<(), KnownHostError> { ++ let Some(remote_host_key) = cert_host_key.hostkey() else { ++ return Err(anyhow::format_err!("remote host key is not available").into()); ++ }; ++ let remote_key_type = cert_host_key.hostkey_type().unwrap(); ++ // `changed_key` keeps track of any entries where the key has changed. ++ let mut changed_key = None; ++ // `other_hosts` keeps track of any entries that have an identical key, ++ // but a different hostname. ++ let mut other_hosts = Vec::new(); ++ ++ // Collect all the known host entries from disk. ++ let mut known_hosts = Vec::new(); ++ for path in known_host_files() { ++ if !path.exists() { ++ continue; ++ } ++ let hosts = load_hostfile(&path)?; ++ known_hosts.extend(hosts); ++ } ++ // Load the bundled keys. Don't add keys for hosts that the user has ++ // configured, which gives them the option to override them. This could be ++ // useful if the keys are ever revoked. ++ let configured_hosts: HashSet<_> = known_hosts ++ .iter() ++ .flat_map(|known_host| { ++ known_host ++ .patterns ++ .split(',') ++ .map(|pattern| pattern.to_lowercase()) ++ }) ++ .collect(); ++ for (patterns, key_type, key) in BUNDLED_KEYS { ++ if !configured_hosts.contains(*patterns) { ++ let key = base64::decode(key).unwrap(); ++ known_hosts.push(KnownHost { ++ location: KnownHostLocation::Bundled, ++ patterns: patterns.to_string(), ++ key_type: key_type.to_string(), ++ key, ++ }); ++ } ++ } ++ ++ for known_host in known_hosts { ++ // The key type from libgit2 needs to match the key type from the host file. ++ if known_host.key_type != remote_key_type.name() { ++ continue; ++ } ++ let key_matches = known_host.key == remote_host_key; ++ if !known_host.host_matches(host) { ++ // `name` can be None for hashed hostnames (which libgit2 does not expose). ++ if key_matches { ++ other_hosts.push(known_host.clone()); ++ } ++ continue; ++ } ++ if key_matches { ++ return Ok(()); ++ } ++ // The host and key type matched, but the key itself did not. ++ // This indicates the key has changed. ++ // This is only reported as an error if no subsequent lines have a ++ // correct key. ++ changed_key = Some(known_host.clone()); ++ } ++ // Older versions of OpenSSH (before 6.8, March 2015) showed MD5 ++ // fingerprints (see FingerprintHash ssh config option). Here we only ++ // support SHA256. ++ let mut remote_fingerprint = cargo_util::Sha256::new(); ++ remote_fingerprint.update(remote_host_key); ++ let remote_fingerprint = ++ base64::encode_config(remote_fingerprint.finish(), base64::STANDARD_NO_PAD); ++ let remote_host_key = base64::encode(remote_host_key); ++ // FIXME: Ideally the error message should include the IP address of the ++ // remote host (to help the user validate that they are connecting to the ++ // host they were expecting to). However, I don't see a way to obtain that ++ // information from libgit2. ++ match changed_key { ++ Some(old_known_host) => Err(KnownHostError::HostKeyHasChanged { ++ hostname: host.to_string(), ++ key_type: remote_key_type, ++ old_known_host, ++ remote_host_key, ++ remote_fingerprint, ++ }), ++ None => Err(KnownHostError::HostKeyNotFound { ++ hostname: host.to_string(), ++ key_type: remote_key_type, ++ remote_host_key, ++ remote_fingerprint, ++ other_hosts, ++ }), ++ } ++} ++ ++/// Returns a list of files to try loading OpenSSH-formatted known hosts. ++fn known_host_files() -> Vec { ++ let mut result = Vec::new(); ++ if cfg!(unix) { ++ result.push(PathBuf::from("/etc/ssh/ssh_known_hosts")); ++ } else if cfg!(windows) { ++ // The msys/cygwin version of OpenSSH uses `/etc` from the posix root ++ // filesystem there (such as `C:\msys64\etc\ssh\ssh_known_hosts`). ++ // However, I do not know of a way to obtain that location from ++ // Windows-land. The ProgramData version here is what the PowerShell ++ // port of OpenSSH does. ++ if let Some(progdata) = std::env::var_os("ProgramData") { ++ let mut progdata = PathBuf::from(progdata); ++ progdata.push("ssh"); ++ progdata.push("ssh_known_hosts"); ++ result.push(progdata) ++ } ++ } ++ result.extend(user_known_host_location()); ++ result ++} ++ ++/// The location of the user's known_hosts file. ++fn user_known_host_location() -> Option { ++ // NOTE: This is a potentially inaccurate prediction of what the user ++ // actually wants. The actual location depends on several factors: ++ // ++ // - Windows OpenSSH Powershell version: I believe this looks up the home ++ // directory via ProfileImagePath in the registry, falling back to ++ // `GetWindowsDirectoryW` if that fails. ++ // - OpenSSH Portable (under msys): This is very complicated. I got lost ++ // after following it through some ldap/active directory stuff. ++ // - OpenSSH (most unix platforms): Uses `pw->pw_dir` from `getpwuid()`. ++ // ++ // This doesn't do anything close to that. home_dir's behavior is: ++ // - Windows: $USERPROFILE, or SHGetFolderPathW() ++ // - Unix: $HOME, or getpwuid_r() ++ // ++ // Since there is a mismatch here, the location returned here might be ++ // different than what the user's `ssh` CLI command uses. We may want to ++ // consider trying to align it better. ++ home::home_dir().map(|mut home| { ++ home.push(".ssh"); ++ home.push("known_hosts"); ++ home ++ }) ++} ++ ++/// The location to display in an error message instructing the user where to ++/// add the new key. ++fn user_known_host_location_to_add() -> String { ++ // Note that we don't bother with the legacy known_hosts2 files. ++ match user_known_host_location() { ++ Some(path) => path.to_str().expect("utf-8 home").to_string(), ++ None => "~/.ssh/known_hosts".to_string(), ++ } ++} ++ ++/// A single known host entry. ++#[derive(Clone)] ++struct KnownHost { ++ location: KnownHostLocation, ++ /// The hostname. May be comma separated to match multiple hosts. ++ patterns: String, ++ key_type: String, ++ key: Vec, ++} ++ ++impl KnownHost { ++ /// Returns whether or not the given host matches this known host entry. ++ fn host_matches(&self, host: &str) -> bool { ++ let mut match_found = false; ++ let host = host.to_lowercase(); ++ // FIXME: support hashed hostnames ++ for pattern in self.patterns.split(',') { ++ let pattern = pattern.to_lowercase(); ++ // FIXME: support * and ? wildcards ++ if let Some(pattern) = pattern.strip_prefix('!') { ++ if pattern == host { ++ return false; ++ } ++ } else { ++ match_found = pattern == host; ++ } ++ } ++ match_found ++ } ++} ++ ++/// Loads an OpenSSH known_hosts file. ++fn load_hostfile(path: &Path) -> Result, anyhow::Error> { ++ let contents = cargo_util::paths::read(path)?; ++ let entries = contents ++ .lines() ++ .enumerate() ++ .filter_map(|(lineno, line)| { ++ let location = KnownHostLocation::File { ++ path: path.to_path_buf(), ++ lineno: lineno as u32 + 1, ++ }; ++ parse_known_hosts_line(line, location) ++ }) ++ .collect(); ++ Ok(entries) ++} ++ ++fn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option { ++ let line = line.trim(); ++ // FIXME: @revoked and @cert-authority is currently not supported. ++ if line.is_empty() || line.starts_with('#') || line.starts_with('@') { ++ return None; ++ } ++ let mut parts = line.split([' ', '\t']).filter(|s| !s.is_empty()); ++ let Some(patterns) = parts.next() else { return None }; ++ let Some(key_type) = parts.next() else { return None }; ++ let Some(key) = parts.next() else { return None }; ++ let Ok(key) = base64::decode(key) else { return None }; ++ Some(KnownHost { ++ location, ++ patterns: patterns.to_string(), ++ key_type: key_type.to_string(), ++ key, ++ }) ++} +Index: cargo/src/cargo/sources/git/mod.rs +=================================================================== +--- cargo.orig/src/cargo/sources/git/mod.rs ++++ cargo/src/cargo/sources/git/mod.rs +@@ -1,4 +1,5 @@ + pub use self::source::GitSource; + pub use self::utils::{fetch, GitCheckout, GitDatabase, GitRemote}; ++mod known_hosts; + mod source; + mod utils; +Index: cargo/src/cargo/sources/git/utils.rs +=================================================================== +--- cargo.orig/src/cargo/sources/git/utils.rs ++++ cargo/src/cargo/sources/git/utils.rs +@@ -647,7 +647,6 @@ where + | ErrorClass::Submodule + | ErrorClass::FetchHead + | ErrorClass::Ssh +- | ErrorClass::Callback + | ErrorClass::Http => { + let mut msg = "network failure seems to have happened\n".to_string(); + msg.push_str( +@@ -658,6 +657,13 @@ where + ); + err = err.context(msg); + } ++ ErrorClass::Callback => { ++ // This unwraps the git2 error. We're using the callback error ++ // specifically to convey errors from Rust land through the C ++ // callback interface. We don't need the `; class=Callback ++ // (26)` that gets tacked on to the git2 error message. ++ err = anyhow::format_err!("{}", e.message()); ++ } + _ => {} + } + } +@@ -686,12 +692,16 @@ pub fn with_fetch_options( + let mut progress = Progress::new("Fetch", config); + network::with_retry(config, || { + with_authentication(url, git_config, |f| { ++ let port = Url::parse(url).ok().and_then(|url| url.port()); + let mut last_update = Instant::now(); + let mut rcb = git2::RemoteCallbacks::new(); + // We choose `N=10` here to make a `300ms * 10slots ~= 3000ms` + // sliding window for tracking the data transfer rate (in bytes/s). + let mut counter = MetricsCounter::<10>::new(0, last_update); + rcb.credentials(f); ++ rcb.certificate_check(|cert, host| { ++ super::known_hosts::certificate_check(cert, host, port) ++ }); + rcb.transfer_progress(|stats| { + let indexed_deltas = stats.indexed_deltas(); + let msg = if indexed_deltas > 0 { +Index: cargo/src/doc/src/appendix/git-authentication.md +=================================================================== +--- cargo.orig/src/doc/src/appendix/git-authentication.md ++++ cargo/src/doc/src/appendix/git-authentication.md +@@ -58,9 +58,32 @@ on how to start `ssh-agent` and to add k + > used by Cargo's built-in SSH library. More advanced requirements should use + > [`net.git-fetch-with-cli`]. + ++### SSH Known Hosts ++ ++When connecting to an SSH host, Cargo must verify the identity of the host ++using "known hosts", which are a list of host keys. Cargo can look for these ++known hosts in OpenSSH-style `known_hosts` files located in their standard ++locations (`.ssh/known_hosts` in your home directory, or ++`/etc/ssh/ssh_known_hosts` on Unix-like platforms or ++`%PROGRAMDATA%\ssh\ssh_known_hosts` on Windows). More information about these ++files can be found in the [sshd man page]. ++ ++When connecting to an SSH host before the known hosts has been configured, ++Cargo will display an error message instructing you how to add the host key. ++This also includes a "fingerprint", which is a smaller hash of the host key, ++which should be easier to visually verify. The server administrator can get ++the fingerprint by running `ssh-keygen` against the public key (for example, ++`ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub`). Well-known sites may ++publish their fingerprints on the web; for example GitHub posts theirs at ++. ++ ++Cargo comes with the host keys for [github.com](https://github.com) built-in. ++If those ever change, you can add the new keys to your known_hosts file. ++ + [`credential.helper`]: https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage + [`net.git-fetch-with-cli`]: ../reference/config.md#netgit-fetch-with-cli + [GCM]: https://github.com/microsoft/Git-Credential-Manager-Core/ + [PuTTY]: https://www.chiark.greenend.org.uk/~sgtatham/putty/ + [Microsoft installation documentation]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse + [key management]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement ++[sshd man page]: https://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT +--- rust-cargo-0.66.0.orig/Cargo.toml ++++ rust-cargo-0.66.0/Cargo.toml +@@ -17,6 +17,7 @@ path = "src/cargo/lib.rs" + + [dependencies] + atty = "0.2" ++base64 = "0.13" + bytesize = "1.0" + cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } + cargo-util = { path = "crates/cargo-util", version = "0.2.1" } +@@ -28,8 +29,8 @@ pretty_env_logger = { version = "0.4", o + anyhow = "1.0" + filetime = "0.2.9" + flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } +-git2 = "0.15.0" +-git2-curl = "0.16.0" ++git2 = "0.16.0" ++git2-curl = "0.17.0" + glob = "0.3.0" + hex = "0.4" + home = "0.5" +@@ -41,7 +42,7 @@ jobserver = "0.1.24" + lazycell = "1.2.0" + libc = "0.2" + log = "0.4.6" +-libgit2-sys = "0.14.0" ++libgit2-sys = "0.14.1" + memchr = "2.1.3" + opener = "0.5" + os_info = "3.5.0" + +--- cargo-0.66/crates/cargo-test-support/Cargo.toml.orig 2023-01-11 11:33:00.584077593 +0100 ++++ cargo-0.66/crates/cargo-test-support/Cargo.toml 2023-01-11 11:33:12.564917363 +0100 +@@ -14,7 +14,7 @@ cargo-util = { path = "../cargo-util" } + snapbox = { version = "0.3.0", features = ["diff", "path"] } + filetime = "0.2" + flate2 = { version = "1.0", default-features = false, features = ["zlib"] } +-git2 = "0.15.0" ++git2 = "0.16.0" + glob = "0.3" + itertools = "0.10.0" + lazy_static = "1.0" + diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-02-add-support-for-deserializing-vec-value-string.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-02-add-support-for-deserializing-vec-value-string.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-02-add-support-for-deserializing-vec-value-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-02-add-support-for-deserializing-vec-value-string.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,157 @@ +commit 9f62f8440e9e542f27d60c75be38ac51186c6c32 +Author: Eric Huss +Date: Fri Dec 9 20:03:27 2022 -0800 + + Add support for deserializing Vec> in config. + + This adds the ability to track the definition location of a string + in a TOML array. + +diff --git a/src/cargo/util/config/de.rs b/src/cargo/util/config/de.rs +index 6fddc7e71f..1408f15b57 100644 +--- a/src/cargo/util/config/de.rs ++++ b/src/cargo/util/config/de.rs +@@ -384,7 +384,12 @@ impl<'de> de::SeqAccess<'de> for ConfigSeqAccess { + { + match self.list_iter.next() { + // TODO: add `def` to error? +- Some((value, _def)) => seed.deserialize(value.into_deserializer()).map(Some), ++ Some((value, def)) => { ++ // This might be a String or a Value. ++ // ValueDeserializer will handle figuring out which one it is. ++ let maybe_value_de = ValueDeserializer::new_with_string(value, def); ++ seed.deserialize(maybe_value_de).map(Some) ++ } + None => Ok(None), + } + } +@@ -400,7 +405,17 @@ impl<'de> de::SeqAccess<'de> for ConfigSeqAccess { + struct ValueDeserializer<'config> { + hits: u32, + definition: Definition, +- de: Deserializer<'config>, ++ /// The deserializer, used to actually deserialize a Value struct. ++ /// This is `None` if deserializing a string. ++ de: Option>, ++ /// A string value to deserialize. ++ /// ++ /// This is used for situations where you can't address a string via a ++ /// TOML key, such as a string inside an array. The `ConfigSeqAccess` ++ /// doesn't know if the type it should deserialize to is a `String` or ++ /// `Value`, so `ValueDeserializer` needs to be able to handle ++ /// both. ++ str_value: Option, + } + + impl<'config> ValueDeserializer<'config> { +@@ -428,9 +443,19 @@ impl<'config> ValueDeserializer<'config> { + Ok(ValueDeserializer { + hits: 0, + definition, +- de, ++ de: Some(de), ++ str_value: None, + }) + } ++ ++ fn new_with_string(s: String, definition: Definition) -> ValueDeserializer<'config> { ++ ValueDeserializer { ++ hits: 0, ++ definition, ++ de: None, ++ str_value: Some(s), ++ } ++ } + } + + impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> { +@@ -459,9 +484,14 @@ impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> { + // If this is the first time around we deserialize the `value` field + // which is the actual deserializer + if self.hits == 1 { +- return seed +- .deserialize(self.de.clone()) +- .map_err(|e| e.with_key_context(&self.de.key, self.definition.clone())); ++ if let Some(de) = &self.de { ++ return seed ++ .deserialize(de.clone()) ++ .map_err(|e| e.with_key_context(&de.key, self.definition.clone())); ++ } else { ++ return seed ++ .deserialize(self.str_value.as_ref().unwrap().clone().into_deserializer()); ++ } + } + + // ... otherwise we're deserializing the `definition` field, so we need +@@ -484,6 +514,71 @@ impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> { + } + } + ++// Deserializer is only implemented to handle deserializing a String inside a ++// sequence (like `Vec` or `Vec>`). `Value` is ++// handled by deserialize_struct, and the plain `String` is handled by all the ++// other functions here. ++impl<'de, 'config> de::Deserializer<'de> for ValueDeserializer<'config> { ++ type Error = ConfigError; ++ ++ fn deserialize_str(self, visitor: V) -> Result ++ where ++ V: de::Visitor<'de>, ++ { ++ visitor.visit_str(&self.str_value.expect("string expected")) ++ } ++ ++ fn deserialize_string(self, visitor: V) -> Result ++ where ++ V: de::Visitor<'de>, ++ { ++ visitor.visit_string(self.str_value.expect("string expected")) ++ } ++ ++ fn deserialize_struct( ++ self, ++ name: &'static str, ++ fields: &'static [&'static str], ++ visitor: V, ++ ) -> Result ++ where ++ V: de::Visitor<'de>, ++ { ++ // Match on the magical struct name/field names that are passed in to ++ // detect when we're deserializing `Value`. ++ // ++ // See more comments in `value.rs` for the protocol used here. ++ if name == value::NAME && fields == value::FIELDS { ++ return visitor.visit_map(self); ++ } ++ unimplemented!("only strings and Value can be deserialized from a sequence"); ++ } ++ ++ fn deserialize_any(self, visitor: V) -> Result ++ where ++ V: de::Visitor<'de>, ++ { ++ visitor.visit_string(self.str_value.expect("string expected")) ++ } ++ ++ fn deserialize_ignored_any(self, visitor: V) -> Result ++ where ++ V: de::Visitor<'de>, ++ { ++ visitor.visit_unit() ++ } ++ ++ serde::forward_to_deserialize_any! { ++ i8 i16 i32 i64 ++ u8 u16 u32 u64 ++ option ++ newtype_struct seq tuple tuple_struct map enum bool ++ f32 f64 char bytes ++ byte_buf unit unit_struct ++ identifier ++ } ++} ++ + /// A deserializer which takes two values and deserializes into a tuple of those + /// two values. This is similar to types like `StrDeserializer` in upstream + /// serde itself. diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-03-support-configuring-ssh-known-hosts.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-03-support-configuring-ssh-known-hosts.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-03-support-configuring-ssh-known-hosts.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-03-support-configuring-ssh-known-hosts.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,299 @@ +commit 026bda3fb5eddac0df111ee150706f756558a7b3 +Author: Eric Huss +Date: Fri Dec 9 20:38:12 2022 -0800 + + Support configuring ssh known-hosts via cargo config. + +diff --git a/src/cargo/sources/git/known_hosts.rs b/src/cargo/sources/git/known_hosts.rs +index 875dcf63f3..7efea43c3b 100644 +--- a/src/cargo/sources/git/known_hosts.rs ++++ b/src/cargo/sources/git/known_hosts.rs +@@ -20,6 +20,7 @@ + //! hostname patterns, and revoked markers. See "FIXME" comments littered in + //! this file. + ++use crate::util::config::{Definition, Value}; + use git2::cert::Cert; + use git2::CertificateCheckStatus; + use std::collections::HashSet; +@@ -74,6 +75,8 @@ impl From for KnownHostError { + enum KnownHostLocation { + /// Loaded from a file from disk. + File { path: PathBuf, lineno: u32 }, ++ /// Loaded from cargo's config system. ++ Config { definition: Definition }, + /// Part of the hard-coded bundled keys in Cargo. + Bundled, + } +@@ -83,6 +86,8 @@ pub fn certificate_check( + cert: &Cert<'_>, + host: &str, + port: Option, ++ config_known_hosts: Option<&Vec>>, ++ diagnostic_home_config: &str, + ) -> Result { + let Some(host_key) = cert.as_hostkey() else { + // Return passthrough for TLS X509 certificates to use whatever validation +@@ -96,7 +101,7 @@ pub fn certificate_check( + _ => host.to_string(), + }; + // The error message must be constructed as a string to pass through the libgit2 C API. +- let err_msg = match check_ssh_known_hosts(host_key, &host_maybe_port) { ++ let err_msg = match check_ssh_known_hosts(host_key, &host_maybe_port, config_known_hosts) { + Ok(()) => { + return Ok(CertificateCheckStatus::CertificateOk); + } +@@ -113,13 +118,13 @@ pub fn certificate_check( + // Try checking without the port. + if port.is_some() + && !matches!(port, Some(22)) +- && check_ssh_known_hosts(host_key, host).is_ok() ++ && check_ssh_known_hosts(host_key, host, config_known_hosts).is_ok() + { + return Ok(CertificateCheckStatus::CertificateOk); + } + let key_type_short_name = key_type.short_name(); + let key_type_name = key_type.name(); +- let known_hosts_location = user_known_host_location_to_add(); ++ let known_hosts_location = user_known_host_location_to_add(diagnostic_home_config); + let other_hosts_message = if other_hosts.is_empty() { + String::new() + } else { +@@ -132,6 +137,9 @@ pub fn certificate_check( + KnownHostLocation::File { path, lineno } => { + format!("{} line {lineno}", path.display()) + } ++ KnownHostLocation::Config { definition } => { ++ format!("config value from {definition}") ++ } + KnownHostLocation::Bundled => format!("bundled with cargo"), + }; + write!(msg, " {loc}: {}\n", known_host.patterns).unwrap(); +@@ -163,7 +171,7 @@ pub fn certificate_check( + }) => { + let key_type_short_name = key_type.short_name(); + let key_type_name = key_type.name(); +- let known_hosts_location = user_known_host_location_to_add(); ++ let known_hosts_location = user_known_host_location_to_add(diagnostic_home_config); + let old_key_resolution = match old_known_host.location { + KnownHostLocation::File { path, lineno } => { + let old_key_location = path.display(); +@@ -173,6 +181,13 @@ pub fn certificate_check( + and adding the new key to {known_hosts_location}", + ) + } ++ KnownHostLocation::Config { definition } => { ++ format!( ++ "removing the old {key_type_name} key for `{hostname}` \ ++ loaded from Cargo's config at {definition}, \ ++ and adding the new key to {known_hosts_location}" ++ ) ++ } + KnownHostLocation::Bundled => { + format!( + "adding the new key to {known_hosts_location}\n\ +@@ -217,6 +232,7 @@ pub fn certificate_check( + fn check_ssh_known_hosts( + cert_host_key: &git2::cert::CertHostkey<'_>, + host: &str, ++ config_known_hosts: Option<&Vec>>, + ) -> Result<(), KnownHostError> { + let Some(remote_host_key) = cert_host_key.hostkey() else { + return Err(anyhow::format_err!("remote host key is not available").into()); +@@ -237,6 +253,23 @@ fn check_ssh_known_hosts( + let hosts = load_hostfile(&path)?; + known_hosts.extend(hosts); + } ++ if let Some(config_known_hosts) = config_known_hosts { ++ // Format errors aren't an error in case the format needs to change in ++ // the future, to retain forwards compatibility. ++ for line_value in config_known_hosts { ++ let location = KnownHostLocation::Config { ++ definition: line_value.definition.clone(), ++ }; ++ match parse_known_hosts_line(&line_value.val, location) { ++ Some(known_host) => known_hosts.push(known_host), ++ None => log::warn!( ++ "failed to parse known host {} from {}", ++ line_value.val, ++ line_value.definition ++ ), ++ } ++ } ++ } + // Load the bundled keys. Don't add keys for hosts that the user has + // configured, which gives them the option to override them. This could be + // useful if the keys are ever revoked. +@@ -363,12 +396,18 @@ fn user_known_host_location() -> Option { + + /// The location to display in an error message instructing the user where to + /// add the new key. +-fn user_known_host_location_to_add() -> String { ++fn user_known_host_location_to_add(diagnostic_home_config: &str) -> String { + // Note that we don't bother with the legacy known_hosts2 files. +- match user_known_host_location() { +- Some(path) => path.to_str().expect("utf-8 home").to_string(), +- None => "~/.ssh/known_hosts".to_string(), +- } ++ let user = user_known_host_location(); ++ let openssh_loc = match &user { ++ Some(path) => path.to_str().expect("utf-8 home"), ++ None => "~/.ssh/known_hosts", ++ }; ++ format!( ++ "the `net.ssh.known-hosts` array in your Cargo configuration \ ++ (such as {diagnostic_home_config}) \ ++ or in your OpenSSH known_hosts file at {openssh_loc}" ++ ) + } + + /// A single known host entry. +diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs +index 831c43be6b..457c97c5bb 100644 +--- a/src/cargo/sources/git/utils.rs ++++ b/src/cargo/sources/git/utils.rs +@@ -726,6 +726,9 @@ pub fn with_fetch_options( + cb: &mut dyn FnMut(git2::FetchOptions<'_>) -> CargoResult<()>, + ) -> CargoResult<()> { + let mut progress = Progress::new("Fetch", config); ++ let ssh_config = config.net_config()?.ssh.as_ref(); ++ let config_known_hosts = ssh_config.and_then(|ssh| ssh.known_hosts.as_ref()); ++ let diagnostic_home_config = config.diagnostic_home_config(); + network::with_retry(config, || { + with_authentication(url, git_config, |f| { + let port = Url::parse(url).ok().and_then(|url| url.port()); +@@ -736,7 +739,13 @@ pub fn with_fetch_options( + let mut counter = MetricsCounter::<10>::new(0, last_update); + rcb.credentials(f); + rcb.certificate_check(|cert, host| { +- super::known_hosts::certificate_check(cert, host, port) ++ super::known_hosts::certificate_check( ++ cert, ++ host, ++ port, ++ config_known_hosts, ++ &diagnostic_home_config, ++ ) + }); + rcb.transfer_progress(|stats| { + let indexed_deltas = stats.indexed_deltas(); +diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs +index d30e094413..d9ab142c4e 100644 +--- a/src/cargo/util/config/mod.rs ++++ b/src/cargo/util/config/mod.rs +@@ -356,6 +356,18 @@ impl Config { + &self.home_path + } + ++ /// Returns a path to display to the user with the location of their home ++ /// config file (to only be used for displaying a diagnostics suggestion, ++ /// such as recommending where to add a config value). ++ pub fn diagnostic_home_config(&self) -> String { ++ let home = self.home_path.as_path_unlocked(); ++ let path = match self.get_file_path(home, "config", false) { ++ Ok(Some(existing_path)) => existing_path, ++ _ => home.join("config.toml"), ++ }; ++ path.to_string_lossy().to_string() ++ } ++ + /// Gets the Cargo Git directory (`/git`). + pub fn git_path(&self) -> Filesystem { + self.home_path.join("git") +@@ -2356,6 +2368,13 @@ pub struct CargoNetConfig { + pub retry: Option, + pub offline: Option, + pub git_fetch_with_cli: Option, ++ pub ssh: Option, ++} ++ ++#[derive(Debug, Deserialize)] ++#[serde(rename_all = "kebab-case")] ++pub struct CargoSshConfig { ++ pub known_hosts: Option>>, + } + + #[derive(Debug, Deserialize)] +diff --git a/src/doc/src/appendix/git-authentication.md b/src/doc/src/appendix/git-authentication.md +index a7db1ac7f1..f46a6535c6 100644 +--- a/src/doc/src/appendix/git-authentication.md ++++ b/src/doc/src/appendix/git-authentication.md +@@ -66,7 +66,8 @@ known hosts in OpenSSH-style `known_hosts` files located in their standard + locations (`.ssh/known_hosts` in your home directory, or + `/etc/ssh/ssh_known_hosts` on Unix-like platforms or + `%PROGRAMDATA%\ssh\ssh_known_hosts` on Windows). More information about these +-files can be found in the [sshd man page]. ++files can be found in the [sshd man page]. Alternatively, keys may be ++configured in a Cargo configuration file with [`net.ssh.known-hosts`]. + + When connecting to an SSH host before the known hosts has been configured, + Cargo will display an error message instructing you how to add the host key. +@@ -78,10 +79,11 @@ publish their fingerprints on the web; for example GitHub posts theirs at + . + + Cargo comes with the host keys for [github.com](https://github.com) built-in. +-If those ever change, you can add the new keys to your known_hosts file. ++If those ever change, you can add the new keys to the config or known_hosts file. + + [`credential.helper`]: https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage + [`net.git-fetch-with-cli`]: ../reference/config.md#netgit-fetch-with-cli ++[`net.ssh.known-hosts`]: ../reference/config.md#netsshknown-hosts + [GCM]: https://github.com/microsoft/Git-Credential-Manager-Core/ + [PuTTY]: https://www.chiark.greenend.org.uk/~sgtatham/putty/ + [Microsoft installation documentation]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse +diff --git a/src/doc/src/reference/config.md b/src/doc/src/reference/config.md +index 1e50648797..f804ceebea 100644 +--- a/src/doc/src/reference/config.md ++++ b/src/doc/src/reference/config.md +@@ -114,6 +114,9 @@ retry = 2 # network retries + git-fetch-with-cli = true # use the `git` executable for git operations + offline = true # do not access the network + ++[net.ssh] ++known-hosts = ["..."] # known SSH host keys ++ + [patch.] + # Same keys as for [patch] in Cargo.toml + +@@ -750,6 +753,41 @@ needed, and generate an error if it encounters a network error. + + Can be overridden with the `--offline` command-line option. + ++##### `net.ssh` ++ ++The `[net.ssh]` table contains settings for SSH connections. ++ ++##### `net.ssh.known-hosts` ++* Type: array of strings ++* Default: see description ++* Environment: not supported ++ ++The `known-hosts` array contains a list of SSH host keys that should be ++accepted as valid when connecting to an SSH server (such as for SSH git ++dependencies). Each entry should be a string in a format similar to OpenSSH ++`known_hosts` files. Each string should start with one or more hostnames ++separated by commas, a space, the key type name, a space, and the ++base64-encoded key. For example: ++ ++```toml ++[net.ssh] ++known-hosts = [ ++ "example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFO4Q5T0UV0SQevair9PFwoxY9dl4pQl3u5phoqJH3cF" ++] ++``` ++ ++Cargo will attempt to load known hosts keys from common locations supported in ++OpenSSH, and will join those with any listed in a Cargo configuration file. ++If any matching entry has the correct key, the connection will be allowed. ++ ++Cargo comes with the host keys for [github.com][github-keys] built-in. If ++those ever change, you can add the new keys to the config or known_hosts file. ++ ++See [Git Authentication](../appendix/git-authentication.md#ssh-known-hosts) ++for more details. ++ ++[github-keys]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints ++ + #### `[patch]` + + Just as you can override dependencies using [`[patch]` in diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-04-add-some-known-hosts-tests-and-fix-comma-bug.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-04-add-some-known-hosts-tests-and-fix-comma-bug.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-04-add-some-known-hosts-tests-and-fix-comma-bug.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-04-add-some-known-hosts-tests-and-fix-comma-bug.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,244 @@ +commit 302a543ddf3b7621c2f10623862029d35fae7e3c +Author: Eric Huss +Date: Mon Dec 12 20:14:23 2022 -0800 + + Add some known_hosts tests. + + This also fixes a bug with the host matching when there are comma-separated hosts. + +diff --git a/src/cargo/sources/git/known_hosts.rs b/src/cargo/sources/git/known_hosts.rs +index 7efea43c3b..58e64e7913 100644 +--- a/src/cargo/sources/git/known_hosts.rs ++++ b/src/cargo/sources/git/known_hosts.rs +@@ -21,7 +21,7 @@ + //! this file. + + use crate::util::config::{Definition, Value}; +-use git2::cert::Cert; ++use git2::cert::{Cert, SshHostKeyType}; + use git2::CertificateCheckStatus; + use std::collections::HashSet; + use std::fmt::Write; +@@ -49,7 +49,7 @@ enum KnownHostError { + /// The host key was not found. + HostKeyNotFound { + hostname: String, +- key_type: git2::cert::SshHostKeyType, ++ key_type: SshHostKeyType, + remote_host_key: String, + remote_fingerprint: String, + other_hosts: Vec, +@@ -57,7 +57,7 @@ enum KnownHostError { + /// The host key was found, but does not match the remote's key. + HostKeyHasChanged { + hostname: String, +- key_type: git2::cert::SshHostKeyType, ++ key_type: SshHostKeyType, + old_known_host: KnownHost, + remote_host_key: String, + remote_fingerprint: String, +@@ -238,11 +238,6 @@ fn check_ssh_known_hosts( + return Err(anyhow::format_err!("remote host key is not available").into()); + }; + let remote_key_type = cert_host_key.hostkey_type().unwrap(); +- // `changed_key` keeps track of any entries where the key has changed. +- let mut changed_key = None; +- // `other_hosts` keeps track of any entries that have an identical key, +- // but a different hostname. +- let mut other_hosts = Vec::new(); + + // Collect all the known host entries from disk. + let mut known_hosts = Vec::new(); +@@ -293,6 +288,21 @@ fn check_ssh_known_hosts( + }); + } + } ++ check_ssh_known_hosts_loaded(&known_hosts, host, remote_key_type, remote_host_key) ++} ++ ++/// Checks a host key against a loaded set of known hosts. ++fn check_ssh_known_hosts_loaded( ++ known_hosts: &[KnownHost], ++ host: &str, ++ remote_key_type: SshHostKeyType, ++ remote_host_key: &[u8], ++) -> Result<(), KnownHostError> { ++ // `changed_key` keeps track of any entries where the key has changed. ++ let mut changed_key = None; ++ // `other_hosts` keeps track of any entries that have an identical key, ++ // but a different hostname. ++ let mut other_hosts = Vec::new(); + + for known_host in known_hosts { + // The key type from libgit2 needs to match the key type from the host file. +@@ -301,7 +311,6 @@ fn check_ssh_known_hosts( + } + let key_matches = known_host.key == remote_host_key; + if !known_host.host_matches(host) { +- // `name` can be None for hashed hostnames (which libgit2 does not expose). + if key_matches { + other_hosts.push(known_host.clone()); + } +@@ -434,7 +443,7 @@ impl KnownHost { + return false; + } + } else { +- match_found = pattern == host; ++ match_found |= pattern == host; + } + } + match_found +@@ -444,6 +453,10 @@ impl KnownHost { + /// Loads an OpenSSH known_hosts file. + fn load_hostfile(path: &Path) -> Result, anyhow::Error> { + let contents = cargo_util::paths::read(path)?; ++ Ok(load_hostfile_contents(path, &contents)) ++} ++ ++fn load_hostfile_contents(path: &Path, contents: &str) -> Vec { + let entries = contents + .lines() + .enumerate() +@@ -455,13 +468,13 @@ fn load_hostfile(path: &Path) -> Result, anyhow::Error> { + parse_known_hosts_line(line, location) + }) + .collect(); +- Ok(entries) ++ entries + } + + fn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option { + let line = line.trim(); + // FIXME: @revoked and @cert-authority is currently not supported. +- if line.is_empty() || line.starts_with('#') || line.starts_with('@') { ++ if line.is_empty() || line.starts_with(['#', '@', '|']) { + return None; + } + let mut parts = line.split([' ', '\t']).filter(|s| !s.is_empty()); +@@ -476,3 +489,126 @@ fn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option { ++ assert_eq!(path, kh_path); ++ assert_eq!(*lineno, 4); ++ } ++ _ => panic!("unexpected"), ++ } ++ assert_eq!(khs[0].patterns, "example.com,rust-lang.org"); ++ assert_eq!(khs[0].key_type, "ssh-rsa"); ++ assert_eq!(khs[0].key.len(), 407); ++ assert_eq!(&khs[0].key[..30], b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x03\x01\x00\x01\x00\x00\x01\x81\x00\xb935\x88\xa5\x9c)"); ++ match &khs[1].location { ++ KnownHostLocation::File { path, lineno } => { ++ assert_eq!(path, kh_path); ++ assert_eq!(*lineno, 5); ++ } ++ _ => panic!("unexpected"), ++ } ++ assert_eq!(khs[2].patterns, "[example.net]:2222"); ++ assert_eq!(khs[3].patterns, "nistp256.example.org"); ++ assert_eq!(khs[7].patterns, "192.168.42.12"); ++ } ++ ++ #[test] ++ fn host_matches() { ++ let kh_path = Path::new("/home/abc/.known_hosts"); ++ let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS); ++ assert!(khs[0].host_matches("example.com")); ++ assert!(khs[0].host_matches("rust-lang.org")); ++ assert!(khs[0].host_matches("EXAMPLE.COM")); ++ assert!(khs[1].host_matches("example.net")); ++ assert!(!khs[0].host_matches("example.net")); ++ assert!(khs[2].host_matches("[example.net]:2222")); ++ assert!(!khs[2].host_matches("example.net")); ++ assert!(!khs[8].host_matches("neg.example.com")); ++ } ++ ++ #[test] ++ fn check_match() { ++ let kh_path = Path::new("/home/abc/.known_hosts"); ++ let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS); ++ ++ assert!(check_ssh_known_hosts_loaded( ++ &khs, ++ "example.com", ++ SshHostKeyType::Rsa, ++ &khs[0].key ++ ) ++ .is_ok()); ++ ++ match check_ssh_known_hosts_loaded(&khs, "example.com", SshHostKeyType::Dss, &khs[0].key) { ++ Err(KnownHostError::HostKeyNotFound { ++ hostname, ++ remote_fingerprint, ++ other_hosts, ++ .. ++ }) => { ++ assert_eq!( ++ remote_fingerprint, ++ "yn+pONDn0EcgdOCVptgB4RZd/wqmsVKrPnQMLtrvhw8" ++ ); ++ assert_eq!(hostname, "example.com"); ++ assert_eq!(other_hosts.len(), 0); ++ } ++ _ => panic!("unexpected"), ++ } ++ ++ match check_ssh_known_hosts_loaded( ++ &khs, ++ "foo.example.com", ++ SshHostKeyType::Rsa, ++ &khs[0].key, ++ ) { ++ Err(KnownHostError::HostKeyNotFound { other_hosts, .. }) => { ++ assert_eq!(other_hosts.len(), 1); ++ assert_eq!(other_hosts[0].patterns, "example.com,rust-lang.org"); ++ } ++ _ => panic!("unexpected"), ++ } ++ ++ let mut modified_key = khs[0].key.clone(); ++ modified_key[0] = 1; ++ match check_ssh_known_hosts_loaded(&khs, "example.com", SshHostKeyType::Rsa, &modified_key) ++ { ++ Err(KnownHostError::HostKeyHasChanged { old_known_host, .. }) => { ++ assert!(matches!( ++ old_known_host.location, ++ KnownHostLocation::File { lineno: 4, .. } ++ )); ++ } ++ _ => panic!("unexpected"), ++ } ++ } ++} diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-05-remove-let-else.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-05-remove-let-else.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-05-remove-let-else.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-05-remove-let-else.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,26 @@ +commit cf716fc3c2b0785013b321f08d6cf9e277f89c84 +Author: Eric Huss +Date: Tue Dec 13 08:14:59 2022 -0800 + + Remove let-else, just use ? propagation. + + Co-authored-by: Weihang Lo + +diff --git a/src/cargo/sources/git/known_hosts.rs b/src/cargo/sources/git/known_hosts.rs +index 58e64e7913..f272195306 100644 +--- a/src/cargo/sources/git/known_hosts.rs ++++ b/src/cargo/sources/git/known_hosts.rs +@@ -478,10 +478,9 @@ fn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option +Date: Wed Dec 14 19:01:40 2022 -0800 + + Add test for config Value in TOML array. + +diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs +index b1d07bb405..d1487833f7 100644 +--- a/tests/testsuite/config.rs ++++ b/tests/testsuite/config.rs +@@ -1,7 +1,7 @@ + //! Tests for config settings. + + use cargo::core::{PackageIdSpec, Shell}; +-use cargo::util::config::{self, Config, SslVersionConfig, StringList}; ++use cargo::util::config::{self, Config, Definition, SslVersionConfig, StringList}; + use cargo::util::interning::InternedString; + use cargo::util::toml::{self, VecStringOrBool as VSOB}; + use cargo::CargoResult; +@@ -1508,3 +1508,59 @@ fn all_profile_options() { + let roundtrip_toml = toml_edit::easy::to_string(&roundtrip).unwrap(); + compare::assert_match_exact(&profile_toml, &roundtrip_toml); + } ++ ++#[cargo_test] ++fn value_in_array() { ++ // Value in an array should work ++ let root_path = paths::root().join(".cargo/config.toml"); ++ write_config_at( ++ &root_path, ++ "\ ++[net.ssh] ++known-hosts = [ ++ \"example.com ...\", ++ \"example.net ...\", ++] ++", ++ ); ++ ++ let foo_path = paths::root().join("foo/.cargo/config.toml"); ++ write_config_at( ++ &foo_path, ++ "\ ++[net.ssh] ++known-hosts = [ ++ \"example.org ...\", ++] ++", ++ ); ++ ++ let config = ConfigBuilder::new() ++ .cwd("foo") ++ // environment variables don't actually work for known-hosts due to ++ // space splitting, but this is included here just to validate that ++ // they work (particularly if other Vec config vars are added ++ // in the future). ++ .env("CARGO_NET_SSH_KNOWN_HOSTS", "env-example") ++ .build(); ++ let net_config = config.net_config().unwrap(); ++ let kh = net_config ++ .ssh ++ .as_ref() ++ .unwrap() ++ .known_hosts ++ .as_ref() ++ .unwrap(); ++ assert_eq!(kh.len(), 4); ++ assert_eq!(kh[0].val, "example.org ..."); ++ assert_eq!(kh[0].definition, Definition::Path(foo_path.clone())); ++ assert_eq!(kh[1].val, "example.com ..."); ++ assert_eq!(kh[1].definition, Definition::Path(root_path.clone())); ++ assert_eq!(kh[2].val, "example.net ..."); ++ assert_eq!(kh[2].definition, Definition::Path(root_path.clone())); ++ assert_eq!(kh[3].val, "env-example"); ++ assert_eq!( ++ kh[3].definition, ++ Definition::Environment("CARGO_NET_SSH_KNOWN_HOSTS".to_string()) ++ ); ++} diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-07-support-hashed-hostnames.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-07-support-hashed-hostnames.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-07-support-hashed-hostnames.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-07-support-hashed-hostnames.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,125 @@ +This patch is based on the upstream commit described below, adapted for use +in the Debian package by Peter Michael Green. + +commit 67ae2dcafea5955824b1f390568a5fa109424987 +Author: Eric Huss +Date: Wed Dec 28 15:52:10 2022 -0800 + + ssh known_hosts: support hashed hostnames + +Index: cargo/src/cargo/sources/git/known_hosts.rs +=================================================================== +--- cargo.orig/src/cargo/sources/git/known_hosts.rs ++++ cargo/src/cargo/sources/git/known_hosts.rs +@@ -16,13 +16,13 @@ + //! - `VerifyHostKeyDNS` — Uses SSHFP DNS records to fetch a host key. + //! + //! There's also a number of things that aren't supported but could be easily +-//! added (it just adds a little complexity). For example, hashed hostnames, +-//! hostname patterns, and revoked markers. See "FIXME" comments littered in +-//! this file. ++//! added (it just adds a little complexity). For example, hostname patterns, ++//! and revoked markers. See "FIXME" comments littered in this file. + + use crate::util::config::{Definition, Value}; + use git2::cert::{Cert, SshHostKeyType}; + use git2::CertificateCheckStatus; ++use hmac::Mac; + use std::collections::HashSet; + use std::fmt::Write; + use std::path::{Path, PathBuf}; +@@ -419,6 +419,8 @@ fn user_known_host_location_to_add(diagn + ) + } + ++const HASH_HOSTNAME_PREFIX: &str = "|1|"; ++ + /// A single known host entry. + #[derive(Clone)] + struct KnownHost { +@@ -434,7 +436,9 @@ impl KnownHost { + fn host_matches(&self, host: &str) -> bool { + let mut match_found = false; + let host = host.to_lowercase(); +- // FIXME: support hashed hostnames ++ if let Some(hashed) = self.patterns.strip_prefix(HASH_HOSTNAME_PREFIX) { ++ return hashed_hostname_matches(&host, hashed); ++ } + for pattern in self.patterns.split(',') { + let pattern = pattern.to_lowercase(); + // FIXME: support * and ? wildcards +@@ -450,6 +454,16 @@ impl KnownHost { + } + } + ++fn hashed_hostname_matches(host: &str, hashed: &str) -> bool { ++ let Some((b64_salt, b64_host)) = hashed.split_once('|') else { return false; }; ++ let Ok(salt) = base64::decode(b64_salt) else { return false; }; ++ let Ok(hashed_host) = base64::decode(b64_host) else { return false; }; ++ let Ok(mut mac) = hmac::Hmac::::new_from_slice(&salt) else { return false; }; ++ mac.update(host.as_bytes()); ++ let result = mac.finalize().into_bytes(); ++ hashed_host == &result[..] ++} ++ + /// Loads an OpenSSH known_hosts file. + fn load_hostfile(path: &Path) -> Result, anyhow::Error> { + let contents = cargo_util::paths::read(path)?; +@@ -474,7 +488,7 @@ fn load_hostfile_contents(path: &Path, c + fn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option { + let line = line.trim(); + // FIXME: @revoked and @cert-authority is currently not supported. +- if line.is_empty() || line.starts_with(['#', '@', '|']) { ++ if line.is_empty() || line.starts_with(['#', '@']) { + return None; + } + let mut parts = line.split([' ', '\t']).filter(|s| !s.is_empty()); +@@ -506,8 +520,7 @@ mod tests { + @revoked * ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKtQsi+KPYispwm2rkMidQf30fG1Niy8XNkvASfePoca eric@host + example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAWkjI6XT2SZh3xNk5NhisA3o3sGzWR+VAKMSqHtI0aY eric@host + 192.168.42.12 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR eric@host +- # Hash not yet supported. +- |1|7CMSYgzdwruFLRhwowMtKx0maIE=|Tlff1GFqc3Ao+fUWxMEVG8mJiyk= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHgN3O21U4LWtP5OzjTzPnUnSDmCNDvyvlaj6Hi65JC eric@host ++ |1|QxzZoTXIWLhUsuHAXjuDMIV3FjQ=|M6NCOIkjiWdCWqkh5+Q+/uFLGjs= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHgN3O21U4LWtP5OzjTzPnUnSDmCNDvyvlaj6Hi65JC eric@host + # Negation isn't terribly useful without globs. + neg.example.com,!neg.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOXfUnaAHTlo1Qi//rNk26OcmHikmkns1Z6WW/UuuS3K eric@host + "#; +@@ -516,7 +529,7 @@ mod tests { + fn known_hosts_parse() { + let kh_path = Path::new("/home/abc/.known_hosts"); + let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS); +- assert_eq!(khs.len(), 9); ++ assert_eq!(khs.len(), 10); + match &khs[0].location { + KnownHostLocation::File { path, lineno } => { + assert_eq!(path, kh_path); +@@ -551,7 +564,9 @@ mod tests { + assert!(!khs[0].host_matches("example.net")); + assert!(khs[2].host_matches("[example.net]:2222")); + assert!(!khs[2].host_matches("example.net")); +- assert!(!khs[8].host_matches("neg.example.com")); ++ assert!(khs[8].host_matches("hashed.example.com")); ++ assert!(!khs[8].host_matches("example.com")); ++ assert!(!khs[9].host_matches("neg.example.com")); + } + + #[test] +--- rust-cargo-0.66.0.orig/Cargo.toml ++++ rust-cargo-0.66.0/Cargo.toml +@@ -33,6 +33,7 @@ git2 = "0.16.0" + git2-curl = "0.17.0" + glob = "0.3.0" + hex = "0.4" ++hmac = "0.12.1" + home = "0.5" + humantime = "2.0.0" + indexmap = "1" +@@ -53,6 +54,7 @@ semver = { version = "1.0.3", features = + serde = { version = "1.0.123", features = ["derive"] } + serde_ignored = "0.1.0" + serde_json = { version = "1.0.30", features = ["raw_value"] } ++sha1 = "0.10.1" + shell-escape = "0.1.4" + strip-ansi-escapes = "0.1.0" + tar = { version = "0.4.38", default-features = false } + diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-08-eliminate-let-else.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-08-eliminate-let-else.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/cve/CVE-2022-46176-08-eliminate-let-else.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/cve/CVE-2022-46176-08-eliminate-let-else.patch 2023-01-17 14:05:25.000000000 +0000 @@ -0,0 +1,61 @@ +This patch eliminates let-else usage in the code introduced +to fix CVE-2022-46176 as that construct is not stabalised in +the version of rustc currently in Debian. + +It was written specifical for Debian by Peter Michael Green. + +Index: cargo/src/cargo/sources/git/known_hosts.rs +=================================================================== +--- cargo.orig/src/cargo/sources/git/known_hosts.rs ++++ cargo/src/cargo/sources/git/known_hosts.rs +@@ -89,11 +89,13 @@ pub fn certificate_check( + config_known_hosts: Option<&Vec>>, + diagnostic_home_config: &str, + ) -> Result { +- let Some(host_key) = cert.as_hostkey() else { ++ let host_key = cert.as_hostkey(); ++ if host_key.is_none() { + // Return passthrough for TLS X509 certificates to use whatever validation + // was done in git2. + return Ok(CertificateCheckStatus::CertificatePassthrough) + }; ++ let host_key = host_key.unwrap(); + // If a nonstandard port is in use, check for that first. + // The fallback to check without a port is handled in the HostKeyNotFound handler. + let host_maybe_port = match port { +@@ -234,9 +236,11 @@ fn check_ssh_known_hosts( + host: &str, + config_known_hosts: Option<&Vec>>, + ) -> Result<(), KnownHostError> { +- let Some(remote_host_key) = cert_host_key.hostkey() else { ++ let remote_host_key = cert_host_key.hostkey(); ++ if remote_host_key.is_none() { + return Err(anyhow::format_err!("remote host key is not available").into()); + }; ++ let remote_host_key = remote_host_key.unwrap(); + let remote_key_type = cert_host_key.hostkey_type().unwrap(); + + // Collect all the known host entries from disk. +@@ -455,10 +459,18 @@ impl KnownHost { + } + + fn hashed_hostname_matches(host: &str, hashed: &str) -> bool { +- let Some((b64_salt, b64_host)) = hashed.split_once('|') else { return false; }; +- let Ok(salt) = base64::decode(b64_salt) else { return false; }; +- let Ok(hashed_host) = base64::decode(b64_host) else { return false; }; +- let Ok(mut mac) = hmac::Hmac::::new_from_slice(&salt) else { return false; }; ++ let hostandsalt = hashed.split_once('|'); ++ if hostandsalt.is_none() { return false; }; ++ let (b64_salt, b64_host) = hostandsalt.unwrap(); ++ let salt = base64::decode(b64_salt); ++ if salt.is_err() { return false; }; ++ let salt = salt.unwrap(); ++ let hashed_host = base64::decode(b64_host); ++ if hashed_host.is_err() { return false; }; ++ let hashed_host = hashed_host.unwrap(); ++ let mac = hmac::Hmac::::new_from_slice(&salt); ++ if mac.is_err() { return false; }; ++ let mut mac = mac.unwrap(); + mac.update(host.as_bytes()); + let result = mac.finalize().into_bytes(); + hashed_host == &result[..] diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/disable-fs-specific-test.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/disable-fs-specific-test.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/disable-fs-specific-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/disable-fs-specific-test.patch 2023-01-17 12:21:18.000000000 +0000 @@ -0,0 +1,13 @@ +Index: cargo/tests/testsuite/metadata.rs +=================================================================== +--- cargo.orig/tests/testsuite/metadata.rs ++++ cargo/tests/testsuite/metadata.rs +@@ -3728,7 +3728,7 @@ fn dep_kinds_workspace() { + // Creating non-utf8 path is an OS-specific pain, so let's run this only on + // linux, where arbitrary bytes work. + #[cfg(target_os = "linux")] +-#[cargo_test] ++#[allow(dead_code)] + fn cargo_metadata_non_utf8() { + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/libgit2-sys-remove-zlib-ng-compat.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/libgit2-sys-remove-zlib-ng-compat.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/libgit2-sys-remove-zlib-ng-compat.patch 2022-09-16 15:25:23.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/libgit2-sys-remove-zlib-ng-compat.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ ---- a/vendor/libgit2-sys/Cargo.toml -+++ b/vendor/libgit2-sys/Cargo.toml -@@ -48,10 +48,6 @@ - ssh_key_from_memory = [] - vendored = [] - vendored-openssl = ["openssl-sys/vendored"] --zlib-ng-compat = [ -- "libz-sys/zlib-ng", -- "libssh2-sys?/zlib-ng-compat", --] - - [target."cfg(unix)".dependencies.openssl-sys] - version = "0.9" diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/remove-badges.patch cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/remove-badges.patch --- cargo-0.62.0ubuntu0libgit2/debian/patches/remove-badges.patch 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/remove-badges.patch 2023-01-17 14:08:25.000000000 +0000 @@ -6,7 +6,7 @@ -[github](https://github.com/dtolnay/proc-macro2) -[crates.io](https://crates.io/crates/proc-macro2) -[docs.rs](https://docs.rs/proc-macro2) --[build status](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster) +-[build status](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster) - A wrapper around the procedural macro API of the compiler's `proc_macro` crate. This library serves two purposes: @@ -20,7 +20,7 @@ -[github](https://github.com/dtolnay/quote) -[crates.io](https://crates.io/crates/quote) -[docs.rs](https://docs.rs/quote) --[build status](https://github.com/dtolnay/quote/actions?query=branch%3Amaster) +-[build status](https://github.com/dtolnay/quote/actions?query=branch%3Amaster) - This crate provides the [`quote!`] macro for turning Rust syntax tree data structures into tokens of source code. @@ -34,7 +34,7 @@ -[github](https://github.com/dtolnay/syn) -[crates.io](https://crates.io/crates/syn) -[docs.rs](https://docs.rs/syn) --[build status](https://github.com/dtolnay/syn/actions?query=branch%3Amaster) +-[build status](https://github.com/dtolnay/syn/actions?query=branch%3Amaster) - Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code. @@ -84,7 +84,7 @@ -[github](https://github.com/dtolnay/unicode-ident) -[crates.io](https://crates.io/crates/unicode-ident) -[docs.rs](https://docs.rs/unicode-ident) --[build status](https://github.com/dtolnay/unicode-ident/actions?query=branch%3Amaster) +-[build status](https://github.com/dtolnay/unicode-ident/actions?query=branch%3Amaster) - Implementation of [Unicode Standard Annex #31][tr31] for determining which `char` values are valid in programming language identifiers. diff -Nru cargo-0.62.0ubuntu0libgit2/debian/patches/series cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/series --- cargo-0.62.0ubuntu0libgit2/debian/patches/series 2022-09-16 15:27:41.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/patches/series 2023-01-18 20:42:34.000000000 +0000 @@ -1,7 +1,19 @@ -# 0001-Force-back-the-git2-rs-crates.patch 2002_disable-net-tests.patch -2112-handle-4-siphasher-algorithms.patch +2003-workaround-qemu-vfork-command-not-found.patch + +2200-workaround-x32-test.patch +disable-fs-specific-test.patch +0003-tests-add-missing-cross-disabled-checks.patch + +cve/CVE-2022-46176-01-validate-ssh-host.keys.patch +cve/CVE-2022-46176-02-add-support-for-deserializing-vec-value-string.patch +cve/CVE-2022-46176-03-support-configuring-ssh-known-hosts.patch +cve/CVE-2022-46176-04-add-some-known-hosts-tests-and-fix-comma-bug.patch +cve/CVE-2022-46176-05-remove-let-else.patch +cve/CVE-2022-46176-06-add-test-for-config-value-in-toml-array.patch +cve/CVE-2022-46176-07-support-hashed-hostnames.patch +cve/CVE-2022-46176-08-eliminate-let-else.patch + remove-badges.patch proxy-skip-tests.patch i386-crossbuild-tests.patch -libgit2-sys-remove-zlib-ng-compat.patch diff -Nru cargo-0.62.0ubuntu0libgit2/debian/README.source cargo-0.66.0+ds0ubuntu0.libgit2/debian/README.source --- cargo-0.62.0ubuntu0libgit2/debian/README.source 2022-06-21 08:31:31.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/README.source 2023-01-17 12:21:18.000000000 +0000 @@ -10,6 +10,10 @@ patches for yet, downgrade them by tweaking d/make_orig_multi-pre-vendor.sh e.g. cargo update -p tempfile --precise 3.1.0 + + You will need to have cargo-lock available + $ cargo install cargo-lock --features=cli + 2. Verify the -vendor component tarball to make sure it looks good. If not, edit d/make_orig_multi.sh and the surrounding files (such as patches and exclude files) and repeat the above until it looks good. diff -Nru cargo-0.62.0ubuntu0libgit2/debian/scripts/audit-vendor-source cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/audit-vendor-source --- cargo-0.62.0ubuntu0libgit2/debian/scripts/audit-vendor-source 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/audit-vendor-source 2023-01-17 12:21:18.000000000 +0000 @@ -14,7 +14,7 @@ shift 2 # everything else is args to suspicious-source # Remove tiny files 4 bytes or less -find . -type f -size -4c -delete +find . -size -4c -type f -delete # Remove non-suspicious files, warning on patterns that match nothing echo "Excluding (i.e. removing) whitelisted files..." grep -v '^#' "$whitelist" | xargs -I% sh -c 'rm -r ./% || true' diff -Nru cargo-0.62.0ubuntu0libgit2/debian/scripts/debian-cargo-vendor cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/debian-cargo-vendor --- cargo-0.62.0ubuntu0libgit2/debian/scripts/debian-cargo-vendor 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/debian-cargo-vendor 2023-01-17 14:05:25.000000000 +0000 @@ -141,8 +141,6 @@ # TODO: rm special logic from debcargo and put into debcargo-conf instead echo >&2 "$0: removing winapi archives" rm -rf vendor/winapi-*-pc-windows-gnu/lib/*.a -rm -rf vendor/windows_*/lib/*.a -rm -rf vendor/windows_*/lib/*.lib echo >&2 "$0: pruning all checksums.." for i in vendor/*; do ${SCRIPTDIR}/prune-checksums "$i"; done diff -Nru cargo-0.62.0ubuntu0libgit2/debian/scripts/guess-crate-copyright cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/guess-crate-copyright --- cargo-0.62.0ubuntu0libgit2/debian/scripts/guess-crate-copyright 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/scripts/guess-crate-copyright 2023-01-17 12:21:18.000000000 +0000 @@ -30,13 +30,16 @@ else: first_year = "20XX" last_year = this_year + + authors = data["package"].get("authors", ["UNKNOWN AUTHORS"]) + print("""Files: {0} Copyright: {1} License: {2} Comment: see {3} """.format( os.path.join(crate, "*"), - "\n ".join("%s-%s %s" % (first_year, last_year, a.replace(" <>", "")) for a in data ["package"]["authors"]), + "\n ".join("%s-%s %s" % (first_year, last_year, a.replace(" <>", "")) for a in authors), data["package"].get("license", "???").replace("/", " or "), repo or "???" )) diff -Nru cargo-0.62.0ubuntu0libgit2/debian/tests/control cargo-0.66.0+ds0ubuntu0.libgit2/debian/tests/control --- cargo-0.62.0ubuntu0libgit2/debian/tests/control 2022-09-16 13:57:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/tests/control 2023-01-17 14:05:25.000000000 +0000 @@ -1,3 +1,5 @@ Tests: self-build Restrictions: rw-build-tree, allow-stderr +# Ubuntu: we don't have the disk space problem on Ubuntu +# Architecture: amd64, armhf, i386, s390x #arm64 and ppc64el run out of disk space when running this test Depends: @builddeps@ diff -Nru cargo-0.62.0ubuntu0libgit2/debian/vendor-tarball-unsuspicious.txt cargo-0.66.0+ds0ubuntu0.libgit2/debian/vendor-tarball-unsuspicious.txt --- cargo-0.62.0ubuntu0libgit2/debian/vendor-tarball-unsuspicious.txt 2022-06-01 13:24:10.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/debian/vendor-tarball-unsuspicious.txt 2023-01-17 14:05:25.000000000 +0000 @@ -2,63 +2,111 @@ # "suspicious files" scanner. DO NOT ADD STUFF HERE WITHOUT UNDERSTANDING WHY. # docs -clap/SPONSORS.md -failure/book/src/bail-and-ensure.md -failure/CODE_OF_CONDUCT.md */CHANGELOG.md -*/CONTRIBUTORS.md */LICENSE */LICENSE.md */README.md */Cargo.toml +base64/RELEASE-NOTES.md + +# ignore +base64/icon_CLion.svg # test data bstr/src/unicode/data/*Test.txt +combine/benches/data.json +combine/benches/http-requests.txt +content_inspector/testdata/* flate2/tests/ -idna/tests/punycode_tests.json -idna/tests/IdnaTest.txt +hmac/tests/data/*.blb idna/tests/IdnaTestV2.txt +idna/tests/punycode_tests.json im-rc/proptest-regressions/ itertools/examples/iris.data -openssl/test/ memchr/src/tests/x86_64-soft_float.json -miniz_oxide/tests/test_data/* -regex/src/testdata/basic.dat -regex/tests/ +openssl/test/ regex-automata/data/fowler-tests/* regex-automata/data/tests/fowler/* -schannel/test/* -toml/tests/ +regex/src/testdata/basic.dat +regex/tests/ +schannel/test/identity.p12 +schannel/test/key.key +schannel/test/self-signed.badssl.com.cer +schannel/test/cert.der +schannel/test/cert.pem +schannel/test/key_wrong_header.pem +sha1/tests/data/*.blb +toml_edit/tests/fixtures/* +unicode-ident/tests/fst/*.fst url/tests/*.json vcpkg/test-data/*/installed/vcpkg/updates/* vte/tests/demo.vte # ideally should be autogenerated, but too difficult today bstr/src/unicode/fsm/*.dfa +bstr-0.2.17/src/unicode/fsm/*.dfa regex-syntax/src/unicode_tables/*.rs # "verylongtext" but OK source code, manually audited: -cloudabi/cloudabi.rs git2/src/cred.rs +kstring/benches/clone.rs libz-sys/src/smoke.c -proptest/src/regex-contrib/crates_regex.rs +miniz_oxide/Readme.md openssl-sys/build/expando.c -rustc-demangle/src/legacy.rs -rustc-demangle/src/lib.rs -termion/logo.svg +serde_json/tests/lexical/parse.rs tinyvec/LICENSE-MIT.md unicode-normalization/src/stream_safe.rs vcpkg/notes.md walkdir/compare/nftw.c winapi/src/lib.rs -# other misc OK, manually audited: -backtrace-sys/src/android-api.c -vte/foos/large_vim_scroll.recording - memchr/scripts/make-byte-frequency-table idna/src/make_uts46_mapping_table.py walkdir/compare/walk.py -strsim/dev unicode-normalization/scripts/unicode.py unicode-width/scripts/unicode.py + +# false positive (Dyalog APL transfer) +clap/examples/tutorial_*/*.md +clap/examples/*.md + +# false positive (Algol68) +aho-corasick/src/nfa.rs +base64/src/encode.rs +base64/src/decode.rs +block-buffer/tests/mod.rs +clap/src/derive.rs +combine/src/parser/choice.rs +combine/src/parser/mod.rs +combine/src/parser/range.rs +combine/src/parser/token.rs +combine/src/stream/mod.rs +combine/src/stream/position.rs +digest/src/dev.rs +digest/src/core_api/wrapper.rs +digest/src/core_api/rt_variable.rs +env_logger-0.7.1/src/fmt/writer/mod.rs +env_logger/src/fmt/writer/mod.rs +flate2/src/mem.rs +flate2/src/zio.rs +miniz_oxide/src/deflate/mod.rs +miniz_oxide/src/inflate/mod.rs +openssl/src/cms.rs +openssl/src/envelope.rs +os_info/src/matcher.rs +proc-macro2/src/parse.rs +regex-automata/src/regex.rs +semver/src/parse.rs +snapbox/src/substitutions.rs +syn/src/attr.rs +syn/src/custom_punctuation.rs +syn/src/group.rs +syn/src/pat.rs +syn/src/path.rs +syn/src/punctuated.rs +syn/src/stmt.rs +syn/src/token.rs +syn/src/ty.rs +toml_edit/src/parser/errors.rs +url/src/parser.rs +yansi/src/tests.rs diff -Nru cargo-0.62.0ubuntu0libgit2/.github/workflows/contrib.yml cargo-0.66.0+ds0ubuntu0.libgit2/.github/workflows/contrib.yml --- cargo-0.62.0ubuntu0libgit2/.github/workflows/contrib.yml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/.github/workflows/contrib.yml 2022-10-20 06:00:42.000000000 +0000 @@ -4,11 +4,16 @@ branches: - master +permissions: + contents: read + jobs: deploy: + permissions: + contents: write # for Git to git push runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install mdbook @@ -16,6 +21,9 @@ mkdir mdbook curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.9/mdbook-v0.4.9-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook echo `pwd`/mdbook >> $GITHUB_PATH + - name: Build API doc + run: | + cargo doc --document-private-items --no-deps - name: Deploy docs run: | cd src/doc/contrib @@ -28,6 +36,8 @@ git update-ref -d refs/heads/gh-pages rm -rf contrib mv ../book contrib + # Move rustdoc under contrib/ + mv ../../../../target/doc contrib/apidoc git add contrib git commit -m "Deploy $GITHUB_SHA to gh-pages" git push --force diff -Nru cargo-0.62.0ubuntu0libgit2/.github/workflows/main.yml cargo-0.66.0+ds0ubuntu0.libgit2/.github/workflows/main.yml --- cargo-0.62.0ubuntu0libgit2/.github/workflows/main.yml 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/.github/workflows/main.yml 2022-10-20 06:00:42.000000000 +0000 @@ -9,12 +9,15 @@ run: shell: bash +permissions: + contents: read + jobs: # Check Code style quickly by running `rustfmt` over all code rustfmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: rustup update stable && rustup default stable - run: rustup component add rustfmt - run: cargo fmt --all --check @@ -34,26 +37,35 @@ strategy: matrix: include: - - os: ubuntu-latest + - name: Linux x86_64 stable + os: ubuntu-latest rust: stable other: i686-unknown-linux-gnu - - os: ubuntu-latest + - name: Linux x86_64 beta + os: ubuntu-latest rust: beta other: i686-unknown-linux-gnu - - os: ubuntu-latest + - name: Linux x86_64 nightly + os: ubuntu-latest rust: nightly other: i686-unknown-linux-gnu - - os: macos-latest + - name: macOS x86_64 stable + os: macos-latest rust: stable other: x86_64-apple-ios - - os: windows-latest + - name: Windows x86_64 MSVC stable + os: windows-latest rust: stable-msvc other: i686-pc-windows-msvc - - os: windows-latest + - name: Windows x86_64 gnu nightly + os: windows-latest rust: nightly-gnu other: i686-pc-windows-gnu + name: Tests ${{ matrix.name }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: Dump Environment + run: ci/dump-environment.sh - name: Update Rustup (temporary workaround) run: rustup self update shell: bash @@ -68,6 +80,13 @@ # Deny warnings on CI to avoid warnings getting into the codebase. - run: cargo test --features 'deny-warnings' + - name: Check operability of rustc invocation with argfile + env: + __CARGO_TEST_FORCE_ARGFILE: 1 + run: | + # This only tests `cargo fix` because fix-proxy-mode is one of the most + # complicated subprocess management in Cargo. + cargo test --test testsuite --features 'deny-warnings' -- fix:: - run: cargo test --features 'deny-warnings' --manifest-path crates/cargo-test-support/Cargo.toml env: CARGO_TARGET_DIR: target @@ -90,20 +109,27 @@ # download all workspaces. cargo test --manifest-path benches/benchsuite/Cargo.toml --all-targets -- cargo cargo check --manifest-path benches/capture/Cargo.toml + # The testsuite generates a huge amount of data, and fetch-smoke-test was + # running out of disk space. + - name: Clear test output + run: | + df -h + rm -rf target/tmp + df -h - name: Fetch smoke test run: ci/fetch-smoke-test.sh resolver: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: rustup update stable && rustup default stable - run: cargo test --manifest-path crates/resolver-tests/Cargo.toml build_std: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: rustup update nightly && rustup default nightly - run: rustup component add rust-src - run: cargo build @@ -113,7 +139,7 @@ docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: rustup update nightly && rustup default nightly - run: rustup update stable - run: rustup component add rust-docs @@ -124,7 +150,9 @@ mkdir mdbook curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook echo `pwd`/mdbook >> $GITHUB_PATH - - run: cargo doc --no-deps + - run: cargo doc --document-private-items --no-deps + env: + RUSTDOCFLAGS: -D warnings - run: cd src/doc && mdbook build --dest-dir ../../target/doc - run: | cd src/doc @@ -133,6 +161,8 @@ sh linkcheck.sh --all cargo success: + permissions: + contents: none name: bors build finished needs: [docs, rustfmt, test, resolver, build_std] runs-on: ubuntu-latest @@ -140,6 +170,8 @@ steps: - run: echo ok failure: + permissions: + contents: none name: bors build finished needs: [docs, rustfmt, test, resolver, build_std] runs-on: ubuntu-latest diff -Nru cargo-0.62.0ubuntu0libgit2/.ignore cargo-0.66.0+ds0ubuntu0.libgit2/.ignore --- cargo-0.62.0ubuntu0libgit2/.ignore 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/.ignore 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,6 @@ +# Output generated from src/doc/man +# +# The goal is to help people find the right file to edit +src/doc/man/generated_txt +src/doc/src/commands +src/etc/man diff -Nru cargo-0.62.0ubuntu0libgit2/README.md cargo-0.66.0+ds0ubuntu0.libgit2/README.md --- cargo-0.62.0ubuntu0libgit2/README.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/README.md 2022-10-20 06:00:42.000000000 +0000 @@ -22,13 +22,44 @@ ## Compiling from Source +### Requirements + Cargo requires the following tools and packages to build: -* `git` -* `curl` (on Unix) -* `pkg-config` (on Unix, used to figure out the `libssl` headers/libraries) -* OpenSSL headers (only for Unix, this is the `libssl-dev` package on ubuntu) * `cargo` and `rustc` +* A C compiler [for your platform](https://github.com/rust-lang/cc-rs#compile-time-requirements) +* `git` (to clone this repository) + +**Other requirements:** + +The following are optional based on your platform and needs. + +* `pkg-config` — This is used to help locate system packages, such as `libssl` headers/libraries. This may not be required in all cases, such as using vendored OpenSSL, or on Windows. +* OpenSSL — Only needed on Unix-like systems and only if the `vendored-openssl` Cargo feature is not used. + + This requires the development headers, which can be obtained from the `libssl-dev` package on Ubuntu or `openssl-devel` with apk or yum or the `openssl` package from Homebrew on macOS. + + If using the `vendored-openssl` Cargo feature, then a static copy of OpenSSL will be built from source instead of using the system OpenSSL. + This may require additional tools such as `perl` and `make`. + + On macOS, common installation directories from Homebrew, MacPorts, or pkgsrc will be checked. Otherwise it will fall back to `pkg-config`. + + On Windows, the system-provided Schannel will be used instead. + + LibreSSL is also supported. + +**Optional system libraries:** + +The build will automatically use vendored versions of the following libraries. However, if they are provided by the system and can be found with `pkg-config`, then the system libraries will be used instead: + +* [`libcurl`](https://curl.se/libcurl/) — Used for network transfers. +* [`libgit2`](https://libgit2.org/) — Used for fetching git dependencies. +* [`libssh2`](https://www.libssh2.org/) — Used for SSH access to git repositories. +* [`libz`](https://zlib.net/) (aka zlib) — Used for data compression. + +It is recommended to use the vendored versions as they are the versions that are tested to work with Cargo. + +### Compiling First, you'll want to check out this repository diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/cli.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/cli.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/cli.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/cli.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,10 +1,8 @@ use anyhow::anyhow; +use cargo::core::shell::Shell; use cargo::core::{features, CliUnstable}; use cargo::{self, drop_print, drop_println, CliResult, Config}; -use clap::{ - error::{ContextKind, ContextValue}, - AppSettings, Arg, ArgMatches, -}; +use clap::{AppSettings, Arg, ArgMatches}; use itertools::Itertools; use std::collections::HashMap; use std::fmt::Write; @@ -24,43 +22,24 @@ ]); } -pub fn main(config: &mut Config) -> CliResult { +pub fn main(config: &mut LazyConfig) -> CliResult { + let args = cli().try_get_matches()?; + // CAUTION: Be careful with using `config` until it is configured below. // In general, try to avoid loading config values unless necessary (like // the [alias] table). - - if commands::help::handle_embedded_help(config) { - return Ok(()); - } - - let args = match cli().try_get_matches() { - Ok(args) => args, - Err(e) => { - if e.kind() == clap::ErrorKind::UnrecognizedSubcommand { - // An unrecognized subcommand might be an external subcommand. - let cmd = e - .context() - .find_map(|c| match c { - (ContextKind::InvalidSubcommand, &ContextValue::String(ref cmd)) => { - Some(cmd) - } - _ => None, - }) - .expect("UnrecognizedSubcommand implies the presence of InvalidSubcommand"); - return super::execute_external_subcommand(config, cmd, &[cmd, "--help"]) - .map_err(|_| e.into()); - } else { - return Err(e.into()); - } - } - }; + let config = config.get_mut(); // Global args need to be extracted before expanding aliases because the // clap code for extracting a subcommand discards global options // (appearing before the subcommand). let (expanded_args, global_args) = expand_aliases(config, args, vec![])?; - if expanded_args.value_of("unstable-features") == Some("help") { + if expanded_args + .get_one::("unstable-features") + .map(String::as_str) + == Some("help") + { let options = CliUnstable::help(); let non_hidden_options: Vec<(String, String)> = options .iter() @@ -112,20 +91,20 @@ return Ok(()); } - let is_verbose = expanded_args.occurrences_of("verbose") > 0; - if expanded_args.is_present("version") { + let is_verbose = expanded_args.verbose() > 0; + if expanded_args.flag("version") { let version = get_version_string(is_verbose); drop_print!(config, "{}", version); return Ok(()); } - if let Some(code) = expanded_args.value_of("explain") { + if let Some(code) = expanded_args.get_one::("explain") { let mut procss = config.load_global_rustc(None)?.process(); procss.arg("--explain").arg(code).exec()?; return Ok(()); } - if expanded_args.is_present("list") { + if expanded_args.flag("list") { drop_println!(config, "Installed Commands:"); for (name, command) in list_commands(config) { let known_external_desc = KNOWN_EXTERNAL_COMMAND_DESCRIPTIONS.get(name.as_str()); @@ -262,7 +241,7 @@ } (Some(_), None) => { // Command is built-in and is not conflicting with alias, but contains ignored values. - if let Some(mut values) = args.values_of("") { + if let Some(mut values) = args.get_many::("") { config.shell().warn(format!( "trailing arguments after built-in command `{}` are ignored: `{}`", cmd, @@ -287,11 +266,7 @@ ))?; } - alias.extend( - args.values_of("") - .unwrap_or_default() - .map(|s| s.to_string()), - ); + alias.extend(args.get_many::("").unwrap_or_default().cloned()); // new_args strips out everything before the subcommand, so // capture those global options now. // Note that an alias to an external command will not receive @@ -327,28 +302,26 @@ subcommand_args: &ArgMatches, global_args: GlobalArgs, ) -> CliResult { - let arg_target_dir = &subcommand_args - ._is_valid_arg("target-dir") - .then(|| subcommand_args.value_of_path("target-dir", config)) - .flatten(); - let verbose = global_args.verbose + args.occurrences_of("verbose") as u32; + let arg_target_dir = &subcommand_args.value_of_path("target-dir", config); + let verbose = global_args.verbose + args.verbose(); // quiet is unusual because it is redefined in some subcommands in order // to provide custom help text. - let quiet = args.is_present("quiet") - || subcommand_args.is_valid_and_present("quiet") - || global_args.quiet; + let quiet = args.flag("quiet") || subcommand_args.flag("quiet") || global_args.quiet; let global_color = global_args.color; // Extract so it can take reference. - let color = args.value_of("color").or_else(|| global_color.as_deref()); - let frozen = args.is_present("frozen") || global_args.frozen; - let locked = args.is_present("locked") || global_args.locked; - let offline = args.is_present("offline") || global_args.offline; + let color = args + .get_one::("color") + .map(String::as_str) + .or_else(|| global_color.as_deref()); + let frozen = args.flag("frozen") || global_args.frozen; + let locked = args.flag("locked") || global_args.locked; + let offline = args.flag("offline") || global_args.offline; let mut unstable_flags = global_args.unstable_flags; - if let Some(values) = args.values_of("unstable-features") { - unstable_flags.extend(values.map(|s| s.to_string())); + if let Some(values) = args.get_many::("unstable-features") { + unstable_flags.extend(values.cloned()); } let mut config_args = global_args.config_args; - if let Some(values) = args.values_of("config") { - config_args.extend(values.map(|s| s.to_string())); + if let Some(values) = args.get_many::("config") { + config_args.extend(values.cloned()); } config.configure( verbose, @@ -370,7 +343,12 @@ } let mut ext_args: Vec<&str> = vec![cmd]; - ext_args.extend(subcommand_args.values_of("").unwrap_or_default()); + ext_args.extend( + subcommand_args + .get_many::("") + .unwrap_or_default() + .map(String::as_str), + ); super::execute_external_subcommand(config, cmd, &ext_args) } @@ -389,25 +367,27 @@ impl GlobalArgs { fn new(args: &ArgMatches) -> GlobalArgs { GlobalArgs { - verbose: args.occurrences_of("verbose") as u32, - quiet: args.is_present("quiet"), - color: args.value_of("color").map(|s| s.to_string()), - frozen: args.is_present("frozen"), - locked: args.is_present("locked"), - offline: args.is_present("offline"), + verbose: args.verbose(), + quiet: args.flag("quiet"), + color: args.get_one::("color").cloned(), + frozen: args.flag("frozen"), + locked: args.flag("locked"), + offline: args.flag("offline"), unstable_flags: args - .values_of_lossy("unstable-features") - .unwrap_or_default(), + .get_many::("unstable-features") + .unwrap_or_default() + .cloned() + .collect(), config_args: args - .values_of("config") + .get_many::("config") .unwrap_or_default() - .map(|s| s.to_string()) + .cloned() .collect(), } } } -fn cli() -> App { +pub fn cli() -> App { let is_rustup = std::env::var_os("RUSTUP_HOME").is_some(); let usage = if is_rustup { "cargo [+toolchain] [OPTIONS] [SUBCOMMAND]" @@ -416,10 +396,12 @@ }; App::new("cargo") .allow_external_subcommands(true) - .setting(AppSettings::DeriveDisplayOrder | AppSettings::NoAutoVersion) + .setting(AppSettings::DeriveDisplayOrder) // Doesn't mix well with our list of common cargo commands. See clap-rs/clap#3108 for // opening clap up to allow us to style our help template .disable_colored_help(true) + // Provide a custom help subcommand for calling into man pages + .disable_help_subcommand(true) .override_usage(usage) .help_template( "\ @@ -438,6 +420,7 @@ doc, d Build this package's and its dependencies' documentation new Create a new cargo package init Create a new cargo package in an existing directory + add Add dependencies to a manifest file run, r Run a binary or example of the local package test, t Run the tests bench Run the benchmarks @@ -449,8 +432,8 @@ See 'cargo help ' for more information on a specific command.\n", ) - .arg(opt("version", "Print version info and exit").short('V')) - .arg(opt("list", "List installed commands")) + .arg(flag("version", "Print version info and exit").short('V')) + .arg(flag("list", "List installed commands")) .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE")) .arg( opt( @@ -458,7 +441,7 @@ "Use verbose output (-vv very verbose/build.rs output)", ) .short('v') - .multiple_occurrences(true) + .action(ArgAction::Count) .global(true), ) .arg_quiet() @@ -467,28 +450,57 @@ .value_name("WHEN") .global(true), ) - .arg(opt("frozen", "Require Cargo.lock and cache are up to date").global(true)) - .arg(opt("locked", "Require Cargo.lock is up to date").global(true)) - .arg(opt("offline", "Run without accessing the network").global(true)) - .arg( - multi_opt( - "config", - "KEY=VALUE", - "Override a configuration value (unstable)", - ) - .global(true), - ) + .arg(flag("frozen", "Require Cargo.lock and cache are up to date").global(true)) + .arg(flag("locked", "Require Cargo.lock is up to date").global(true)) + .arg(flag("offline", "Run without accessing the network").global(true)) + .arg(multi_opt("config", "KEY=VALUE", "Override a configuration value").global(true)) .arg( Arg::new("unstable-features") .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details") .short('Z') .value_name("FLAG") - .multiple_occurrences(true) + .action(ArgAction::Append) .global(true), ) .subcommands(commands::builtin()) } +/// Delay loading [`Config`] until access. +/// +/// In the common path, the [`Config`] is dependent on CLI parsing and shouldn't be loaded until +/// after that is done but some other paths (like fix or earlier errors) might need access to it, +/// so this provides a way to share the instance and the implementation across these different +/// accesses. +pub struct LazyConfig { + config: Option, +} + +impl LazyConfig { + pub fn new() -> Self { + Self { config: None } + } + + /// Get the config, loading it if needed + /// + /// On error, the process is terminated + pub fn get(&mut self) -> &Config { + self.get_mut() + } + + /// Get the config, loading it if needed + /// + /// On error, the process is terminated + pub fn get_mut(&mut self) -> &mut Config { + self.config.get_or_insert_with(|| match Config::default() { + Ok(cfg) => cfg, + Err(e) => { + let mut shell = Shell::new(); + cargo::exit_with_error(e.into(), &mut shell) + } + }) + } +} + #[test] fn verify_cli() { cli().debug_assert(); diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/add.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/add.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/add.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/add.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,356 @@ +use indexmap::IndexMap; +use indexmap::IndexSet; + +use cargo::core::dependency::DepKind; +use cargo::core::FeatureValue; +use cargo::ops::cargo_add::add; +use cargo::ops::cargo_add::AddOptions; +use cargo::ops::cargo_add::DepOp; +use cargo::ops::cargo_add::DepTable; +use cargo::ops::resolve_ws; +use cargo::util::command_prelude::*; +use cargo::util::interning::InternedString; +use cargo::CargoResult; + +pub fn cli() -> clap::Command<'static> { + clap::Command::new("add") + .setting(clap::AppSettings::DeriveDisplayOrder) + .about("Add dependencies to a Cargo.toml manifest file") + .override_usage( + "\ + cargo add [OPTIONS] [@] ... + cargo add [OPTIONS] --path ... + cargo add [OPTIONS] --git ..." + ) + .after_help("Run `cargo help add` for more detailed information.\n") + .group(clap::ArgGroup::new("selected").multiple(true).required(true)) + .args([ + clap::Arg::new("crates") + .takes_value(true) + .value_name("DEP_ID") + .multiple_values(true) + .help("Reference to a package to add as a dependency") + .long_help( + "Reference to a package to add as a dependency + +You can reference a package by: +- ``, like `cargo add serde` (latest version will be used) +- `@`, like `cargo add serde@1` or `cargo add serde@=1.0.38`" + ) + .group("selected"), + flag("no-default-features", + "Disable the default features"), + flag("default-features", + "Re-enable the default features") + .overrides_with("no-default-features"), + clap::Arg::new("features") + .short('F') + .long("features") + .takes_value(true) + .value_name("FEATURES") + .action(ArgAction::Append) + .help("Space or comma separated list of features to activate"), + flag("optional", + "Mark the dependency as optional") + .long_help("Mark the dependency as optional + +The package name will be exposed as feature of your crate.") + .conflicts_with("dev"), + flag("no-optional", + "Mark the dependency as required") + .long_help("Mark the dependency as required + +The package will be removed from your features.") + .conflicts_with("dev") + .overrides_with("optional"), + clap::Arg::new("rename") + .long("rename") + .takes_value(true) + .value_name("NAME") + .help("Rename the dependency") + .long_help("Rename the dependency + +Example uses: +- Depending on multiple versions of a crate +- Depend on crates with the same name from different registries"), + ]) + .arg_manifest_path() + .args([ + clap::Arg::new("package") + .short('p') + .long("package") + .takes_value(true) + .value_name("SPEC") + .help("Package to modify"), + ]) + .arg_quiet() + .arg_dry_run("Don't actually write the manifest") + .next_help_heading("SOURCE") + .args([ + clap::Arg::new("path") + .long("path") + .takes_value(true) + .value_name("PATH") + .help("Filesystem path to local crate to add") + .group("selected") + .conflicts_with("git"), + clap::Arg::new("git") + .long("git") + .takes_value(true) + .value_name("URI") + .help("Git repository location") + .long_help("Git repository location + +Without any other information, cargo will use latest commit on the main branch.") + .group("selected"), + clap::Arg::new("branch") + .long("branch") + .takes_value(true) + .value_name("BRANCH") + .help("Git branch to download the crate from") + .requires("git") + .group("git-ref"), + clap::Arg::new("tag") + .long("tag") + .takes_value(true) + .value_name("TAG") + .help("Git tag to download the crate from") + .requires("git") + .group("git-ref"), + clap::Arg::new("rev") + .long("rev") + .takes_value(true) + .value_name("REV") + .help("Git reference to download the crate from") + .long_help("Git reference to download the crate from + +This is the catch all, handling hashes to named references in remote repositories.") + .requires("git") + .group("git-ref"), + clap::Arg::new("registry") + .long("registry") + .takes_value(true) + .value_name("NAME") + .help("Package registry for this dependency"), + ]) + .next_help_heading("SECTION") + .args([ + flag("dev", + "Add as development dependency") + .long_help("Add as development dependency + +Dev-dependencies are not used when compiling a package for building, but are used for compiling tests, examples, and benchmarks. + +These dependencies are not propagated to other packages which depend on this package.") + .group("section"), + flag("build", + "Add as build dependency") + .long_help("Add as build dependency + +Build-dependencies are the only dependencies available for use by build scripts (`build.rs` files).") + .group("section"), + clap::Arg::new("target") + .long("target") + .takes_value(true) + .value_name("TARGET") + .value_parser(clap::builder::NonEmptyStringValueParser::new()) + .help("Add as dependency to the given target platform") + ]) +} + +pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { + let dry_run = args.dry_run(); + let section = parse_section(args); + + let ws = args.workspace(config)?; + let packages = args.packages_from_flags()?; + let packages = packages.get_packages(&ws)?; + let spec = match packages.len() { + 0 => { + return Err(CliError::new( + anyhow::format_err!("no packages selected. Please specify one with `-p `"), + 101, + )); + } + 1 => packages[0], + len => { + return Err(CliError::new( + anyhow::format_err!( + "{len} packages selected. Please specify one with `-p `", + ), + 101, + )); + } + }; + + let dependencies = parse_dependencies(config, args)?; + + let options = AddOptions { + config, + spec, + dependencies, + section, + dry_run, + }; + add(&ws, &options)?; + + if !dry_run { + // Reload the workspace since we've changed dependencies + let ws = args.workspace(config)?; + resolve_ws(&ws)?; + } + + Ok(()) +} + +fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult> { + let path = matches.get_one::("path"); + let git = matches.get_one::("git"); + let branch = matches.get_one::("branch"); + let rev = matches.get_one::("rev"); + let tag = matches.get_one::("tag"); + let rename = matches.get_one::("rename"); + let registry = matches.registry(config)?; + let default_features = default_features(matches); + let optional = optional(matches); + + let mut crates = matches + .get_many::("crates") + .into_iter() + .flatten() + .map(|c| (Some(c.clone()), None)) + .collect::>(); + let mut infer_crate_name = false; + if crates.is_empty() { + if path.is_some() || git.is_some() { + crates.insert(None, None); + infer_crate_name = true; + } else { + unreachable!("clap should ensure we have some source selected"); + } + } + for feature in matches + .get_many::("features") + .into_iter() + .flatten() + .map(String::as_str) + .flat_map(parse_feature) + { + let parsed_value = FeatureValue::new(InternedString::new(feature)); + match parsed_value { + FeatureValue::Feature(_) => { + if 1 < crates.len() { + let candidates = crates + .keys() + .map(|c| { + format!( + "`{}/{}`", + c.as_deref().expect("only none when there is 1"), + feature + ) + }) + .collect::>(); + anyhow::bail!("feature `{feature}` must be qualified by the dependency its being activated for, like {}", candidates.join(", ")); + } + crates + .first_mut() + .expect("always at least one crate") + .1 + .get_or_insert_with(IndexSet::new) + .insert(feature.to_owned()); + } + FeatureValue::Dep { .. } => { + anyhow::bail!("feature `{feature}` is not allowed to use explicit `dep:` syntax",) + } + FeatureValue::DepFeature { + dep_name, + dep_feature, + .. + } => { + if infer_crate_name { + anyhow::bail!("`{feature}` is unsupported when inferring the crate name, use `{dep_feature}`"); + } + if dep_feature.contains('/') { + anyhow::bail!("multiple slashes in feature `{feature}` is not allowed"); + } + crates.get_mut(&Some(dep_name.as_str().to_owned())).ok_or_else(|| { + anyhow::format_err!("feature `{dep_feature}` activated for crate `{dep_name}` but the crate wasn't specified") + })? + .get_or_insert_with(IndexSet::new) + .insert(dep_feature.as_str().to_owned()); + } + } + } + + let mut deps: Vec = Vec::new(); + for (crate_spec, features) in crates { + let dep = DepOp { + crate_spec, + rename: rename.map(String::from), + features, + default_features, + optional, + registry: registry.clone(), + path: path.map(String::from), + git: git.map(String::from), + branch: branch.map(String::from), + rev: rev.map(String::from), + tag: tag.map(String::from), + }; + deps.push(dep); + } + + if deps.len() > 1 && rename.is_some() { + anyhow::bail!("cannot specify multiple crates with `--rename`"); + } + + Ok(deps) +} + +fn default_features(matches: &ArgMatches) -> Option { + resolve_bool_arg( + matches.flag("default-features"), + matches.flag("no-default-features"), + ) +} + +fn optional(matches: &ArgMatches) -> Option { + resolve_bool_arg(matches.flag("optional"), matches.flag("no-optional")) +} + +fn resolve_bool_arg(yes: bool, no: bool) -> Option { + match (yes, no) { + (true, false) => Some(true), + (false, true) => Some(false), + (false, false) => None, + (_, _) => unreachable!("clap should make this impossible"), + } +} + +fn parse_section(matches: &ArgMatches) -> DepTable { + let kind = if matches.flag("dev") { + DepKind::Development + } else if matches.flag("build") { + DepKind::Build + } else { + DepKind::Normal + }; + + let mut table = DepTable::new().set_kind(kind); + + if let Some(target) = matches.get_one::("target") { + assert!(!target.is_empty(), "Target specification may not be empty"); + table = table.set_target(target); + } + + table +} + +/// Split feature flag list +fn parse_feature(feature: &str) -> impl Iterator { + // Not re-using `CliFeatures` because it uses a BTreeSet and loses user's ordering + feature + .split_whitespace() + .flat_map(|s| s.split(',')) + .filter(|s| !s.is_empty()) +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/bench.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/bench.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/bench.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/bench.rs 2022-10-20 06:00:42.000000000 +0000 @@ -28,7 +28,7 @@ "Benchmark all benches", "Benchmark all targets", ) - .arg(opt("no-run", "Compile, but don't run benchmarks")) + .arg(flag("no-run", "Compile, but don't run benchmarks")) .arg_package_spec( "Package to run benchmarks for", "Benchmark all packages in the workspace", @@ -42,7 +42,7 @@ .arg_manifest_path() .arg_ignore_rust_version() .arg_message_format() - .arg(opt( + .arg(flag( "no-fail-fast", "Run all benchmarks regardless of failure", )) @@ -64,21 +64,14 @@ args.get_profile_name(config, "bench", ProfileChecking::Custom)?; let ops = TestOptions { - no_run: args.is_present("no-run"), - no_fail_fast: args.is_present("no-fail-fast"), + no_run: args.flag("no-run"), + no_fail_fast: args.flag("no-fail-fast"), compile_opts, }; - let bench_args = args.value_of("BENCHNAME").into_iter(); - let bench_args = bench_args.chain(args.values_of("args").unwrap_or_default()); - let bench_args = bench_args.collect::>(); + let bench_args = args.get_one::("BENCHNAME").into_iter(); + let bench_args = bench_args.chain(args.get_many::("args").unwrap_or_default()); + let bench_args = bench_args.map(String::as_str).collect::>(); - let err = ops::run_benches(&ws, &ops, &bench_args)?; - match err { - None => Ok(()), - Some(err) => Err(match err.code { - Some(i) => CliError::new(anyhow::format_err!("bench failed"), i), - None => CliError::new(err.into(), 101), - }), - } + ops::run_benches(&ws, &ops, &bench_args) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/check.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/check.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/check.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/check.rs 2022-10-20 06:00:42.000000000 +0000 @@ -43,7 +43,10 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { let ws = args.workspace(config)?; // This is a legacy behavior that causes `cargo check` to pass `--test`. - let test = matches!(args.value_of("profile"), Some("test")); + let test = matches!( + args.get_one::("profile").map(String::as_str), + Some("test") + ); let mode = CompileMode::Check { test }; let compile_opts = args.compile_options(config, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/clean.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/clean.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/clean.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/clean.rs 2022-10-20 06:00:42.000000000 +0000 @@ -29,8 +29,8 @@ spec: values(args, "package"), targets: args.targets(), requested_profile: args.get_profile_name(config, "dev", ProfileChecking::Custom)?, - profile_specified: args.is_present("profile") || args.is_present("release"), - doc: args.is_present("doc"), + profile_specified: args.contains_id("profile") || args.flag("release"), + doc: args.flag("doc"), }; ops::clean(&ws, &opts)?; Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/config.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/config.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/config.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/config.rs 2022-10-20 06:00:42.000000000 +0000 @@ -12,16 +12,16 @@ .arg(Arg::new("key").help("The config key to display")) .arg( opt("format", "Display format") - .possible_values(cargo_config::ConfigFormat::POSSIBLE_VALUES) + .value_parser(cargo_config::ConfigFormat::POSSIBLE_VALUES) .default_value("toml"), ) - .arg(opt( + .arg(flag( "show-origin", "Display where the config value is defined", )) .arg( opt("merged", "Whether or not to merge config values") - .possible_values(&["yes", "no"]) + .value_parser(["yes", "no"]) .default_value("yes"), ), ) @@ -34,10 +34,10 @@ match args.subcommand() { Some(("get", args)) => { let opts = cargo_config::GetOptions { - key: args.value_of("key"), - format: args.value_of("format").unwrap().parse()?, - show_origin: args.is_present("show-origin"), - merged: args.value_of("merged") == Some("yes"), + key: args.get_one::("key").map(String::as_str), + format: args.get_one::("format").unwrap().parse()?, + show_origin: args.flag("show-origin"), + merged: args.get_one::("merged").map(String::as_str) == Some("yes"), }; cargo_config::get(config, &opts)?; } diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/doc.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/doc.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/doc.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/doc.rs 2022-10-20 06:00:42.000000000 +0000 @@ -8,7 +8,7 @@ // .alias("d") .about("Build a package's documentation") .arg_quiet() - .arg(opt( + .arg(flag( "open", "Opens the docs in a browser after the operation", )) @@ -17,8 +17,11 @@ "Document all packages in the workspace", "Exclude packages from the build", ) - .arg(opt("no-deps", "Don't build documentation for dependencies")) - .arg(opt("document-private-items", "Document private items")) + .arg(flag( + "no-deps", + "Don't build documentation for dependencies", + )) + .arg(flag("document-private-items", "Document private items")) .arg_jobs() .arg_targets_lib_bin_example( "Document only this package's library", @@ -43,14 +46,14 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { let ws = args.workspace(config)?; let mode = CompileMode::Doc { - deps: !args.is_present("no-deps"), + deps: !args.flag("no-deps"), }; let mut compile_opts = args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?; - compile_opts.rustdoc_document_private_items = args.is_present("document-private-items"); + compile_opts.rustdoc_document_private_items = args.flag("document-private-items"); let doc_opts = DocOptions { - open_result: args.is_present("open"), + open_result: args.flag("open"), compile_opts, }; ops::doc(&ws, &doc_opts)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/fix.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/fix.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/fix.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/fix.rs 2022-10-20 06:00:42.000000000 +0000 @@ -31,36 +31,27 @@ .arg_target_dir() .arg_manifest_path() .arg_message_format() - .arg( - Arg::new("broken-code") - .long("broken-code") - .help("Fix code even if it already has compiler errors"), - ) - .arg( - Arg::new("edition") - .long("edition") - .help("Fix in preparation for the next edition"), - ) - .arg( - Arg::new("idioms") - .long("edition-idioms") - .help("Fix warnings to migrate to the idioms of an edition"), - ) - .arg( - Arg::new("allow-no-vcs") - .long("allow-no-vcs") - .help("Fix code even if a VCS was not detected"), - ) - .arg( - Arg::new("allow-dirty") - .long("allow-dirty") - .help("Fix code even if the working directory is dirty"), - ) - .arg( - Arg::new("allow-staged") - .long("allow-staged") - .help("Fix code even if the working directory has staged changes"), - ) + .arg(flag( + "broken-code", + "Fix code even if it already has compiler errors", + )) + .arg(flag("edition", "Fix in preparation for the next edition")) + .arg(flag( + "edition-idioms", + "Fix warnings to migrate to the idioms of an edition", + )) + .arg(flag( + "allow-no-vcs", + "Fix code even if a VCS was not detected", + )) + .arg(flag( + "allow-dirty", + "Fix code even if the working directory is dirty", + )) + .arg(flag( + "allow-staged", + "Fix code even if the working directory has staged changes", + )) .arg_ignore_rust_version() .arg_timings() .after_help("Run `cargo help fix` for more detailed information.\n") @@ -69,7 +60,10 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { let ws = args.workspace(config)?; // This is a legacy behavior that causes `cargo fix` to pass `--test`. - let test = matches!(args.value_of("profile"), Some("test")); + let test = matches!( + args.get_one::("profile").map(String::as_str), + Some("test") + ); let mode = CompileMode::Check { test }; // Unlike other commands default `cargo fix` to all targets to fix as much @@ -85,13 +79,13 @@ ops::fix( &ws, &mut ops::FixOptions { - edition: args.is_present("edition"), - idioms: args.is_present("idioms"), + edition: args.flag("edition"), + idioms: args.flag("edition-idioms"), compile_opts: opts, - allow_dirty: args.is_present("allow-dirty"), - allow_no_vcs: args.is_present("allow-no-vcs"), - allow_staged: args.is_present("allow-staged"), - broken_code: args.is_present("broken-code"), + allow_dirty: args.flag("allow-dirty"), + allow_no_vcs: args.flag("allow-no-vcs"), + allow_staged: args.flag("allow-staged"), + broken_code: args.flag("broken-code"), }, )?; Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/help.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/help.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/help.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/help.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,4 +1,5 @@ use crate::aliased_command; +use crate::command_prelude::*; use cargo::util::errors::CargoResult; use cargo::{drop_println, Config}; use cargo_util::paths::resolve_executable; @@ -10,43 +11,26 @@ const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz")); -/// Checks if the `help` command is being issued. -/// -/// This runs before clap processing, because it needs to intercept the `help` -/// command if a man page is available. -/// -/// Returns `true` if help information was successfully displayed to the user. -/// In this case, Cargo should exit. -pub fn handle_embedded_help(config: &Config) -> bool { - match try_help(config) { - Ok(true) => true, - Ok(false) => false, - Err(e) => { - log::warn!("help failed: {:?}", e); - false - } - } +pub fn cli() -> App { + subcommand("help") + .about("Displays help for a cargo subcommand") + .arg(Arg::new("SUBCOMMAND")) } -fn try_help(config: &Config) -> CargoResult { - let mut args = std::env::args_os() - .skip(1) - .skip_while(|arg| arg.to_str().map_or(false, |s| s.starts_with('-'))); - if !args - .next() - .map_or(false, |arg| arg.to_str() == Some("help")) - { - return Ok(false); +pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { + let subcommand = args.get_one::("SUBCOMMAND"); + if let Some(subcommand) = subcommand { + if !try_help(config, subcommand)? { + crate::execute_external_subcommand(config, subcommand, &[subcommand, "--help"])?; + } + } else { + let mut cmd = crate::cli::cli(); + let _ = cmd.print_help(); } - let subcommand = match args.next() { - Some(arg) => arg, - None => return Ok(false), - }; - let subcommand = match subcommand.to_str() { - Some(s) => s, - None => return Ok(false), - }; + Ok(()) +} +fn try_help(config: &Config, subcommand: &str) -> CargoResult { let subcommand = match check_alias(config, subcommand) { // If this alias is more than a simple subcommand pass-through, show the alias. Some(argv) if argv.len() > 1 => { diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/install.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/install.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/install.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/install.rs 2022-10-20 06:00:42.000000000 +0000 @@ -12,7 +12,7 @@ .arg_quiet() .arg( Arg::new("crate") - .forbid_empty_values(true) + .value_parser(clap::builder::NonEmptyStringValueParser::new()) .multiple_values(true), ) .arg( @@ -46,16 +46,19 @@ .value_name("PATH") .conflicts_with_all(&["git", "index", "registry"]), ) - .arg(opt( + .arg(flag( "list", "list all installed packages and their versions", )) .arg_jobs() - .arg(opt("force", "Force overwriting existing crates or binaries").short('f')) - .arg(opt("no-track", "Do not save tracking information")) + .arg(flag("force", "Force overwriting existing crates or binaries").short('f')) + .arg(flag("no-track", "Do not save tracking information")) .arg_features() .arg_profile("Install artifacts with the specified profile") - .arg(opt("debug", "Build in debug mode instead of release mode")) + .arg(flag( + "debug", + "Build in debug mode (with the 'dev' profile) instead of release mode", + )) .arg_targets_bins_examples( "Install only the specified binary", "Install all binaries", @@ -97,21 +100,23 @@ // but not `Config::reload_rooted_at` which is always cwd) let path = path.map(|p| paths::normalize_path(&p)); + let version = args.get_one::("version").map(String::as_str); let krates = args - .values_of("crate") + .get_many::("crate") .unwrap_or_default() - .collect::>(); + .map(|k| resolve_crate(k, version)) + .collect::>>()?; let mut from_cwd = false; - let source = if let Some(url) = args.value_of("git") { + let source = if let Some(url) = args.get_one::("git") { let url = url.into_url()?; - let gitref = if let Some(branch) = args.value_of("branch") { - GitReference::Branch(branch.to_string()) - } else if let Some(tag) = args.value_of("tag") { - GitReference::Tag(tag.to_string()) - } else if let Some(rev) = args.value_of("rev") { - GitReference::Rev(rev.to_string()) + let gitref = if let Some(branch) = args.get_one::("branch") { + GitReference::Branch(branch.clone()) + } else if let Some(tag) = args.get_one::("tag") { + GitReference::Tag(tag.clone()) + } else if let Some(rev) = args.get_one::("rev") { + GitReference::Rev(rev.clone()) } else { GitReference::DefaultBranch }; @@ -123,14 +128,13 @@ SourceId::for_path(config.cwd())? } else if let Some(registry) = args.registry(config)? { SourceId::alt_registry(config, ®istry)? - } else if let Some(index) = args.value_of("index") { + } else if let Some(index) = args.get_one::("index") { SourceId::for_registry(&index.into_url()?)? } else { SourceId::crates_io(config)? }; - let version = args.value_of("version"); - let root = args.value_of("root"); + let root = args.get_one::("root").map(String::as_str); // We only provide workspace information for local crate installation from // one of the following sources: @@ -157,7 +161,7 @@ compile_opts.build_config.requested_profile = args.get_profile_name(config, "release", ProfileChecking::Custom)?; - if args.is_present("list") { + if args.flag("list") { ops::install_list(root, config)?; } else { ops::install( @@ -166,11 +170,28 @@ krates, source, from_cwd, - version, &compile_opts, - args.is_present("force"), - args.is_present("no-track"), + args.flag("force"), + args.flag("no-track"), )?; } Ok(()) } + +fn resolve_crate<'k>( + mut krate: &'k str, + mut version: Option<&'k str>, +) -> crate::CargoResult<(&'k str, Option<&'k str>)> { + if let Some((k, v)) = krate.split_once('@') { + if version.is_some() { + anyhow::bail!("cannot specify both `@{v}` and `--version`"); + } + if k.is_empty() { + // by convention, arguments starting with `@` are response files + anyhow::bail!("missing crate name for `@{v}`"); + } + krate = k; + version = Some(v); + } + Ok((krate, version)) +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/locate_project.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/locate_project.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/locate_project.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/locate_project.rs 2022-10-20 06:00:42.000000000 +0000 @@ -15,7 +15,7 @@ ) .value_name("FMT"), ) - .arg(opt("workspace", "Locate Cargo.toml of the workspace root")) + .arg(flag("workspace", "Locate Cargo.toml of the workspace root")) .after_help("Run `cargo help locate-project` for more detailed information.\n") } @@ -65,7 +65,7 @@ impl WhatToFind { fn parse(args: &ArgMatches) -> Self { - if args.is_present("workspace") { + if args.flag("workspace") { WhatToFind::Workspace } else { WhatToFind::CurrentManifest @@ -80,7 +80,7 @@ impl MessageFormat { fn parse(args: &ArgMatches) -> CargoResult { - let fmt = match args.value_of("message-format") { + let fmt = match args.get_one::("message-format") { Some(fmt) => fmt, None => return Ok(MessageFormat::Json), }; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/login.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/login.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/login.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/login.rs 2022-10-20 06:00:42.000000000 +0000 @@ -17,8 +17,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { ops::registry_login( config, - args.value_of("token").map(String::from), - args.value_of("registry").map(String::from), + args.get_one::("token").cloned(), + args.get_one::("registry").cloned(), )?; Ok(()) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/logout.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/logout.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/logout.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/logout.rs 2022-10-20 06:00:42.000000000 +0000 @@ -16,6 +16,6 @@ .fail_if_stable_command(config, "logout", 8933)?; } config.load_credentials()?; - ops::registry_logout(config, args.value_of("registry").map(String::from))?; + ops::registry_logout(config, args.get_one::("registry").cloned())?; Ok(()) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/metadata.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/metadata.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/metadata.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/metadata.rs 2022-10-20 06:00:42.000000000 +0000 @@ -15,7 +15,7 @@ "TRIPLE", "Only include resolve dependencies matching the given target-triple", )) - .arg(opt( + .arg(flag( "no-deps", "Output information only about the workspace members \ and don't fetch dependencies", @@ -24,7 +24,7 @@ .arg( opt("format-version", "Format version") .value_name("VERSION") - .possible_value("1"), + .value_parser(["1"]), ) .after_help("Run `cargo help metadata` for more detailed information.\n") } @@ -32,7 +32,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { let ws = args.workspace(config)?; - let version = match args.value_of("format-version") { + let version = match args.get_one::("format-version") { None => { config.shell().warn( "please specify `--format-version` flag explicitly \ @@ -45,7 +45,7 @@ let options = OutputMetadataOptions { cli_features: args.cli_features()?, - no_deps: args.is_present("no-deps"), + no_deps: args.flag("no-deps"), filter_platforms: args._values_of("filter-platform"), version, }; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -2,6 +2,7 @@ pub fn builtin() -> Vec { vec![ + add::cli(), bench::cli(), build::cli(), check::cli(), @@ -12,6 +13,7 @@ fix::cli(), generate_lockfile::cli(), git_checkout::cli(), + help::cli(), init::cli(), install::cli(), locate_project::cli(), @@ -42,6 +44,7 @@ pub fn builtin_exec(cmd: &str) -> Option CliResult> { let f = match cmd { + "add" => add::exec, "bench" => bench::exec, "build" => build::exec, "check" => check::exec, @@ -52,6 +55,7 @@ "fix" => fix::exec, "generate-lockfile" => generate_lockfile::exec, "git-checkout" => git_checkout::exec, + "help" => help::exec, "init" => init::exec, "install" => install::exec, "locate-project" => locate_project::exec, @@ -82,6 +86,7 @@ Some(f) } +pub mod add; pub mod bench; pub mod build; pub mod check; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/new.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/new.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/new.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/new.rs 2022-10-20 06:00:42.000000000 +0000 @@ -16,8 +16,8 @@ let opts = args.new_options(config)?; ops::new(&opts, config)?; - let path = args.value_of("path").unwrap(); - let package_name = if let Some(name) = args.value_of("name") { + let path = args.get_one::("path").unwrap(); + let package_name = if let Some(name) = args.get_one::("name") { name } else { path diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/owner.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/owner.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/owner.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/owner.rs 2022-10-20 06:00:42.000000000 +0000 @@ -23,7 +23,7 @@ ) .short('r'), ) - .arg(opt("list", "List owners of a crate").short('l')) + .arg(flag("list", "List owners of a crate").short('l')) .arg(opt("index", "Registry index to modify owners for").value_name("INDEX")) .arg(opt("token", "API token to use when authenticating").value_name("TOKEN")) .arg(opt("registry", "Registry to use").value_name("REGISTRY")) @@ -35,16 +35,16 @@ let registry = args.registry(config)?; let opts = OwnersOptions { - krate: args.value_of("crate").map(|s| s.to_string()), - token: args.value_of("token").map(|s| s.to_string()), - index: args.value_of("index").map(|s| s.to_string()), + krate: args.get_one::("crate").cloned(), + token: args.get_one::("token").cloned(), + index: args.get_one::("index").cloned(), to_add: args - .values_of("add") - .map(|xs| xs.map(|s| s.to_string()).collect()), + .get_many::("add") + .map(|xs| xs.cloned().collect()), to_remove: args - .values_of("remove") - .map(|xs| xs.map(|s| s.to_string()).collect()), - list: args.is_present("list"), + .get_many::("remove") + .map(|xs| xs.cloned().collect()), + list: args.flag("list"), registry, }; ops::modify_owners(config, &opts)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/package.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/package.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/package.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/package.rs 2022-10-20 06:00:42.000000000 +0000 @@ -7,21 +7,21 @@ .about("Assemble the local package into a distributable tarball") .arg_quiet() .arg( - opt( + flag( "list", "Print files included in a package without making one", ) .short('l'), ) - .arg(opt( + .arg(flag( "no-verify", "Don't verify the contents by building them", )) - .arg(opt( + .arg(flag( "no-metadata", "Ignore warnings about a lack of human-usable metadata", )) - .arg(opt( + .arg(flag( "allow-dirty", "Allow dirty working directories to be packaged", )) @@ -46,10 +46,10 @@ &ws, &PackageOpts { config, - verify: !args.is_present("no-verify"), - list: args.is_present("list"), - check_metadata: !args.is_present("no-metadata"), - allow_dirty: args.is_present("allow-dirty"), + verify: !args.flag("no-verify"), + list: args.flag("list"), + check_metadata: !args.flag("no-metadata"), + allow_dirty: args.flag("allow-dirty"), to_package: specs, targets: args.targets(), jobs: args.jobs()?, diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/pkgid.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/pkgid.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/pkgid.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/pkgid.rs 2022-10-20 06:00:42.000000000 +0000 @@ -18,7 +18,10 @@ if args.is_present_with_zero_values("package") { print_available_packages(&ws)? } - let spec = args.value_of("spec").or_else(|| args.value_of("package")); + let spec = args + .get_one::("spec") + .or_else(|| args.get_one::("package")) + .map(String::as_str); let spec = ops::pkgid(&ws, spec)?; cargo::drop_println!(config, "{}", spec); Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/publish.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/publish.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/publish.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/publish.rs 2022-10-20 06:00:42.000000000 +0000 @@ -8,11 +8,11 @@ .arg_quiet() .arg_index() .arg(opt("token", "Token to use when uploading").value_name("TOKEN")) - .arg(opt( + .arg(flag( "no-verify", "Don't verify the contents by building them", )) - .arg(opt( + .arg(flag( "allow-dirty", "Allow dirty working directories to be packaged", )) @@ -38,15 +38,15 @@ &ws, &PublishOpts { config, - token: args.value_of("token").map(|s| s.to_string()), + token: args.get_one::("token").map(|s| s.to_string()), index, - verify: !args.is_present("no-verify"), - allow_dirty: args.is_present("allow-dirty"), + verify: !args.flag("no-verify"), + allow_dirty: args.flag("allow-dirty"), to_publish: args.packages_from_flags()?, targets: args.targets(), jobs: args.jobs()?, keep_going: args.keep_going(), - dry_run: args.is_present("dry-run"), + dry_run: args.dry_run(), registry, cli_features: args.cli_features()?, }, diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/report.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/report.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/report.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/report.rs 2022-10-20 06:00:42.000000000 +0000 @@ -25,7 +25,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { match args.subcommand() { - Some(("future-incompatibilities", args)) => report_future_incompatibilies(config, args), + Some(("future-incompatibilities", args)) => report_future_incompatibilities(config, args), Some((cmd, _)) => { unreachable!("unexpected command {}", cmd) } @@ -35,13 +35,13 @@ } } -fn report_future_incompatibilies(config: &Config, args: &ArgMatches) -> CliResult { +fn report_future_incompatibilities(config: &Config, args: &ArgMatches) -> CliResult { let ws = args.workspace(config)?; let reports = OnDiskReports::load(&ws)?; let id = args .value_of_u32("id")? .unwrap_or_else(|| reports.last_id()); - let krate = args.value_of("package"); + let krate = args.get_one::("package").map(String::as_str); let report = reports.get_report(id, config, krate)?; drop_println!(config, "{}", REPORT_PREAMBLE); drop(config.shell().print_ansi_stdout(report.as_bytes())); diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/run.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/run.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/run.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/run.rs 2022-10-20 06:00:42.000000000 +0000 @@ -13,7 +13,7 @@ .arg_quiet() .arg( Arg::new("args") - .allow_invalid_utf8(true) + .value_parser(value_parser!(std::ffi::OsString)) .multiple_values(true), ) .arg_targets_bin_example( @@ -56,7 +56,7 @@ } } - if !args.is_present("example") && !args.is_present("bin") { + if !args.contains_id("example") && !args.contains_id("bin") { let default_runs: Vec<_> = compile_opts .spec .get_packages(&ws)? diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/rustc.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/rustc.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/rustc.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/rustc.rs 2022-10-20 06:00:42.000000000 +0000 @@ -39,7 +39,7 @@ .arg(multi_opt( CRATE_TYPE_ARG_NAME, "CRATE-TYPE", - "Comma separated list of types of crates for the compiler to emit (unstable)", + "Comma separated list of types of crates for the compiler to emit", )) .arg_target_dir() .arg_manifest_path() @@ -56,7 +56,7 @@ // This is a legacy behavior that changes the behavior based on the profile. // If we want to support this more formally, I think adding a --mode flag // would be warranted. - let mode = match args.value_of("profile") { + let mode = match args.get_one::("profile").map(String::as_str) { Some("test") => CompileMode::Test, Some("bench") => CompileMode::Bench, Some("check") => CompileMode::Check { test: false }, @@ -77,7 +77,7 @@ } else { Some(target_args) }; - if let Some(opt_value) = args.value_of(PRINT_ARG_NAME) { + if let Some(opt_value) = args.get_one::(PRINT_ARG_NAME) { config .cli_unstable() .fail_if_stable_opt(PRINT_ARG_NAME, 9357)?; @@ -88,9 +88,6 @@ compile_opts.target_rustc_crate_types = if crate_types.is_empty() { None } else { - config - .cli_unstable() - .fail_if_stable_opt(CRATE_TYPE_ARG_NAME, 10083)?; Some(crate_types) }; ops::compile(&ws, &compile_opts)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/rustdoc.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/rustdoc.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/rustdoc.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/rustdoc.rs 2022-10-20 06:00:42.000000000 +0000 @@ -8,7 +8,7 @@ .about("Build a package's documentation, using specified custom flags.") .arg_quiet() .arg(Arg::new("args").multiple_values(true)) - .arg(opt( + .arg(flag( "open", "Opens the docs in a browser after the operation", )) @@ -54,7 +54,7 @@ Some(target_args) }; let doc_opts = DocOptions { - open_result: args.is_present("open"), + open_result: args.flag("open"), compile_opts, }; ops::doc(&ws, &doc_opts)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/search.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/search.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/search.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/search.rs 2022-10-20 06:00:42.000000000 +0000 @@ -26,7 +26,11 @@ let index = args.index()?; let limit = args.value_of_u32("limit")?; let limit = min(100, limit.unwrap_or(10)); - let query: Vec<&str> = args.values_of("query").unwrap_or_default().collect(); + let query: Vec<&str> = args + .get_many::("query") + .unwrap_or_default() + .map(String::as_str) + .collect(); let query: String = query.join("+"); ops::search(&query, config, index, limit, registry)?; Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/test.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/test.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/test.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/test.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,4 @@ use crate::command_prelude::*; -use anyhow::Error; use cargo::ops; pub fn cli() -> App { @@ -19,7 +18,7 @@ .last(true), ) .arg( - opt( + flag( "quiet", "Display one character per test instead of one line", ) @@ -37,9 +36,9 @@ "Test all benches", "Test all targets", ) - .arg(opt("doc", "Test only this library's documentation")) - .arg(opt("no-run", "Compile, but don't run tests")) - .arg(opt("no-fail-fast", "Run all tests regardless of failure")) + .arg(flag("doc", "Test only this library's documentation")) + .arg(flag("no-run", "Compile, but don't run tests")) + .arg(flag("no-fail-fast", "Run all tests regardless of failure")) .arg_package_spec( "Package to run tests for", "Test all packages in the workspace", @@ -78,13 +77,13 @@ // `TESTNAME` is actually an argument of the test binary, but it's // important, so we explicitly mention it and reconfigure. - let test_name = args.value_of("TESTNAME"); - let test_args = args.value_of("TESTNAME").into_iter(); - let test_args = test_args.chain(args.values_of("args").unwrap_or_default()); - let test_args = test_args.collect::>(); + let test_name = args.get_one::("TESTNAME"); + let test_args = args.get_one::("TESTNAME").into_iter(); + let test_args = test_args.chain(args.get_many::("args").unwrap_or_default()); + let test_args = test_args.map(String::as_str).collect::>(); - let no_run = args.is_present("no-run"); - let doc = args.is_present("doc"); + let no_run = args.flag("no-run"); + let doc = args.flag("doc"); if doc { if compile_opts.filter.is_specific() { return Err( @@ -106,22 +105,9 @@ let ops = ops::TestOptions { no_run, - no_fail_fast: args.is_present("no-fail-fast"), + no_fail_fast: args.flag("no-fail-fast"), compile_opts, }; - let err = ops::run_tests(&ws, &ops, &test_args)?; - match err { - None => Ok(()), - Some(err) => { - let context = anyhow::format_err!("{}", err.hint(&ws, &ops.compile_opts)); - let e = match err.code { - // Don't show "process didn't exit successfully" for simple errors. - Some(i) if cargo_util::is_simple_exit_code(i) => CliError::new(context, i), - Some(i) => CliError::new(Error::from(err).context(context), i), - None => CliError::new(Error::from(err).context(context), 101), - }; - Err(e) - } - } + ops::run_tests(&ws, &ops, &test_args) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/tree.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/tree.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/tree.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/tree.rs 2022-10-20 06:00:42.000000000 +0000 @@ -19,21 +19,18 @@ "Display the tree for all packages in the workspace", "Exclude specific workspace members", ) - // Deprecated, use --no-dedupe instead. - .arg(Arg::new("all").long("all").short('a').hide(true)) - // Deprecated, use --target=all instead. - .arg(Arg::new("all-targets").long("all-targets").hide(true)) + .arg( + flag("all", "Deprecated, use --no-dedupe instead") + .short('a') + .hide(true), + ) + .arg(flag("all-targets", "Deprecated, use --target=all instead").hide(true)) .arg_features() .arg_target_triple( "Filter dependencies matching the given target-triple (default host platform). \ Pass `all` to include all targets.", ) - // Deprecated, use -e=no-dev instead. - .arg( - Arg::new("no-dev-dependencies") - .long("no-dev-dependencies") - .hide(true), - ) + .arg(flag("no-dev-dependencies", "Deprecated, use -e=no-dev instead").hide(true)) .arg( multi_opt( "edges", @@ -58,25 +55,23 @@ "Prune the given package from the display of the dependency tree", )) .arg(opt("depth", "Maximum display depth of the dependency tree").value_name("DEPTH")) - // Deprecated, use --prefix=none instead. - .arg(Arg::new("no-indent").long("no-indent").hide(true)) - // Deprecated, use --prefix=depth instead. - .arg(Arg::new("prefix-depth").long("prefix-depth").hide(true)) + .arg(flag("no-indent", "Deprecated, use --prefix=none instead").hide(true)) + .arg(flag("prefix-depth", "Deprecated, use --prefix=depth instead").hide(true)) .arg( opt( "prefix", "Change the prefix (indentation) of how each entry is displayed", ) .value_name("PREFIX") - .possible_values(&["depth", "indent", "none"]) + .value_parser(["depth", "indent", "none"]) .default_value("indent"), ) - .arg(opt( + .arg(flag( "no-dedupe", "Do not de-duplicate (repeats all shared dependencies)", )) .arg( - opt( + flag( "duplicates", "Show only dependencies which come in multiple versions (implies -i)", ) @@ -86,7 +81,7 @@ .arg( opt("charset", "Character set to use in output: utf8, ascii") .value_name("CHARSET") - .possible_values(&["utf8", "ascii"]) + .value_parser(["utf8", "ascii"]) .default_value("utf8"), ) .arg( @@ -97,35 +92,37 @@ ) .arg( // Backwards compatibility with old cargo-tree. - Arg::new("version").long("version").short('V').hide(true), + flag("version", "Print version info and exit") + .short('V') + .hide(true), ) .after_help("Run `cargo help tree` for more detailed information.\n") } pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { - if args.is_present("version") { - let verbose = args.occurrences_of("verbose") > 0; + if args.flag("version") { + let verbose = args.verbose() > 0; let version = cli::get_version_string(verbose); cargo::drop_print!(config, "{}", version); return Ok(()); } - let prefix = if args.is_present("no-indent") { + let prefix = if args.flag("no-indent") { config .shell() .warn("the --no-indent flag has been changed to --prefix=none")?; "none" - } else if args.is_present("prefix-depth") { + } else if args.flag("prefix-depth") { config .shell() .warn("the --prefix-depth flag has been changed to --prefix=depth")?; "depth" } else { - args.value_of("prefix").unwrap() + args.get_one::("prefix").unwrap().as_str() }; let prefix = tree::Prefix::from_str(prefix).map_err(|e| anyhow::anyhow!("{}", e))?; - let no_dedupe = args.is_present("no-dedupe") || args.is_present("all"); - if args.is_present("all") { + let no_dedupe = args.flag("no-dedupe") || args.flag("all"); + if args.flag("all") { config.shell().warn( "The `cargo tree` --all flag has been changed to --no-dedupe, \ and may be removed in a future version.\n\ @@ -133,7 +130,7 @@ )?; } - let targets = if args.is_present("all-targets") { + let targets = if args.flag("all-targets") { config .shell() .warn("the --all-targets flag has been changed to --target=all")?; @@ -150,7 +147,7 @@ let packages = args.packages_from_flags()?; let mut invert = args - .values_of("invert") + .get_many::("invert") .map_or_else(|| Vec::new(), |is| is.map(|s| s.to_string()).collect()); if args.is_present_with_zero_values("invert") { match &packages { @@ -185,7 +182,7 @@ print_available_packages(&ws)?; } - let charset = tree::Charset::from_str(args.value_of("charset").unwrap()) + let charset = tree::Charset::from_str(args.get_one::("charset").unwrap()) .map_err(|e| anyhow::anyhow!("{}", e))?; let opts = tree::TreeOptions { cli_features: args.cli_features()?, @@ -196,9 +193,9 @@ pkgs_to_prune, prefix, no_dedupe, - duplicates: args.is_present("duplicates"), + duplicates: args.flag("duplicates"), charset, - format: args.value_of("format").unwrap().to_string(), + format: args.get_one::("format").cloned().unwrap(), graph_features, max_display_depth: args.value_of_u32("depth")?.unwrap_or(u32::MAX), no_proc_macro, @@ -218,7 +215,7 @@ fn parse_edge_kinds(config: &Config, args: &ArgMatches) -> CargoResult<(HashSet, bool)> { let (kinds, no_proc_macro) = { let mut no_proc_macro = false; - let mut kinds = args.values_of("edges").map_or_else( + let mut kinds = args.get_many::("edges").map_or_else( || Vec::new(), |es| { es.flat_map(|e| e.split(',')) @@ -230,7 +227,7 @@ }, ); - if args.is_present("no-dev-dependencies") { + if args.flag("no-dev-dependencies") { config .shell() .warn("the --no-dev-dependencies flag has changed to -e=no-dev")?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/uninstall.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/uninstall.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/uninstall.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/uninstall.rs 2022-10-20 06:00:42.000000000 +0000 @@ -14,7 +14,7 @@ } pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { - let root = args.value_of("root"); + let root = args.get_one::("root").map(String::as_str); if args.is_present_with_zero_values("package") { return Err(anyhow::anyhow!( @@ -25,8 +25,9 @@ } let specs = args - .values_of("spec") - .unwrap_or_else(|| args.values_of("package").unwrap_or_default()) + .get_many::("spec") + .unwrap_or_else(|| args.get_many::("package").unwrap_or_default()) + .map(String::as_str) .collect(); ops::uninstall(root, specs, &values(args, "bin"), config)?; Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/update.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/update.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/update.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/update.rs 2022-10-20 06:00:42.000000000 +0000 @@ -7,9 +7,9 @@ subcommand("update") .about("Update dependencies as recorded in the local lock file") .arg_quiet() - .arg(opt("workspace", "Only update the workspace packages").short('w')) + .arg(flag("workspace", "Only update the workspace packages").short('w')) .arg_package_spec_simple("Package to update") - .arg(opt( + .arg(flag( "aggressive", "Force updating all dependencies of SPEC as well when used with -p", )) @@ -33,11 +33,11 @@ } let update_opts = UpdateOptions { - aggressive: args.is_present("aggressive"), - precise: args.value_of("precise"), + aggressive: args.flag("aggressive"), + precise: args.get_one::("precise").map(String::as_str), to_update: values(args, "package"), - dry_run: args.is_present("dry-run"), - workspace: args.is_present("workspace"), + dry_run: args.dry_run(), + workspace: args.flag("workspace"), config, }; ops::update_lockfile(&ws, &update_opts)?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/vendor.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/vendor.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/vendor.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/vendor.rs 2022-10-20 06:00:42.000000000 +0000 @@ -9,50 +9,34 @@ .arg_manifest_path() .arg( Arg::new("path") - .allow_invalid_utf8(true) + .value_parser(clap::value_parser!(PathBuf)) .help("Where to vendor crates (`vendor` by default)"), ) - .arg( - Arg::new("no-delete") - .long("no-delete") - .help("Don't delete older crates in the vendor directory"), - ) + .arg(flag( + "no-delete", + "Don't delete older crates in the vendor directory", + )) .arg( Arg::new("tomls") .short('s') .long("sync") .help("Additional `Cargo.toml` to sync and vendor") .value_name("TOML") - .allow_invalid_utf8(true) - .multiple_occurrences(true), - ) - .arg( - Arg::new("respect-source-config") - .long("respect-source-config") - .help("Respect `[source]` config in `.cargo/config`") - .multiple_occurrences(true), - ) - .arg( - Arg::new("versioned-dirs") - .long("versioned-dirs") - .help("Always include version in subdir name"), - ) - // Not supported. - .arg( - Arg::new("no-merge-sources") - .long("no-merge-sources") - .hide(true), - ) - // Not supported. - .arg(Arg::new("relative-path").long("relative-path").hide(true)) - // Not supported. - .arg(Arg::new("only-git-deps").long("only-git-deps").hide(true)) - // Not supported. - .arg( - Arg::new("disallow-duplicates") - .long("disallow-duplicates") - .hide(true), + .value_parser(clap::value_parser!(PathBuf)) + .action(clap::ArgAction::Append), ) + .arg(flag( + "respect-source-config", + "Respect `[source]` config in `.cargo/config`", + )) + .arg(flag( + "versioned-dirs", + "Always include version in subdir name", + )) + .arg(flag("no-merge-sources", "Not supported").hide(true)) + .arg(flag("relative-path", "Not supported").hide(true)) + .arg(flag("only-git-deps", "Not supported").hide(true)) + .arg(flag("disallow-duplicates", "Not supported").hide(true)) .after_help("Run `cargo help vendor` for more detailed information.\n") } @@ -61,20 +45,20 @@ // to respect any of the `source` configuration in Cargo itself. That's // intended for other consumers of Cargo, but we want to go straight to the // source, e.g. crates.io, to fetch crates. - if !args.is_present("respect-source-config") { + if !args.flag("respect-source-config") { config.values_mut()?.remove("source"); } // When we moved `cargo vendor` into Cargo itself we didn't stabilize a few // flags, so try to provide a helpful error message in that case to ensure // that users currently using the flag aren't tripped up. - let crates_io_cargo_vendor_flag = if args.is_present("no-merge-sources") { + let crates_io_cargo_vendor_flag = if args.flag("no-merge-sources") { Some("--no-merge-sources") - } else if args.is_present("relative-path") { + } else if args.flag("relative-path") { Some("--relative-path") - } else if args.is_present("only-git-deps") { + } else if args.flag("only-git-deps") { Some("--only-git-deps") - } else if args.is_present("disallow-duplicates") { + } else if args.flag("disallow-duplicates") { Some("--disallow-duplicates") } else { None @@ -95,19 +79,19 @@ let ws = args.workspace(config)?; let path = args - .value_of_os("path") - .map(|val| PathBuf::from(val.to_os_string())) + .get_one::("path") + .cloned() .unwrap_or_else(|| PathBuf::from("vendor")); ops::vendor( &ws, &ops::VendorOptions { - no_delete: args.is_present("no-delete"), + no_delete: args.flag("no-delete"), destination: &path, - versioned_dirs: args.is_present("versioned-dirs"), + versioned_dirs: args.flag("versioned-dirs"), extra: args - .values_of_os("tomls") + .get_many::("tomls") .unwrap_or_default() - .map(|s| PathBuf::from(s.to_os_string())) + .cloned() .collect(), }, )?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/version.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/version.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/version.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/version.rs 2022-10-20 06:00:42.000000000 +0000 @@ -9,7 +9,7 @@ } pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { - let verbose = args.occurrences_of("verbose") > 0; + let verbose = args.verbose() > 0; let version = cli::get_version_string(verbose); cargo::drop_print!(config, "{}", version); Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/yank.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/yank.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/commands/yank.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/commands/yank.rs 2022-10-20 06:00:42.000000000 +0000 @@ -8,11 +8,11 @@ .arg_quiet() .arg(Arg::new("crate")) .arg( - opt("vers", "The version to yank or un-yank") - .value_name("VERSION") - .required(true), + opt("version", "The version to yank or un-yank") + .alias("vers") + .value_name("VERSION"), ) - .arg(opt( + .arg(flag( "undo", "Undo a yank, putting a version back into the index", )) @@ -27,14 +27,40 @@ let registry = args.registry(config)?; + let (krate, version) = resolve_crate( + args.get_one::("crate").map(String::as_str), + args.get_one::("version").map(String::as_str), + )?; + if version.is_none() { + return Err(anyhow::format_err!("`--version` is required").into()); + } + ops::yank( config, - args.value_of("crate").map(|s| s.to_string()), - args.value_of("vers").map(|s| s.to_string()), - args.value_of("token").map(|s| s.to_string()), - args.value_of("index").map(|s| s.to_string()), - args.is_present("undo"), + krate.map(|s| s.to_string()), + version.map(|s| s.to_string()), + args.get_one::("token").cloned(), + args.get_one::("index").cloned(), + args.flag("undo"), registry, )?; Ok(()) } + +fn resolve_crate<'k>( + mut krate: Option<&'k str>, + mut version: Option<&'k str>, +) -> crate::CargoResult<(Option<&'k str>, Option<&'k str>)> { + if let Some((k, v)) = krate.and_then(|k| k.split_once('@')) { + if version.is_some() { + anyhow::bail!("cannot specify both `@{v}` and `--version`"); + } + if k.is_empty() { + // by convention, arguments starting with `@` are response files + anyhow::bail!("missing crate name for `@{v}`"); + } + krate = Some(k); + version = Some(v); + } + Ok((krate, version)) +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/bin/cargo/main.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/main.rs --- cargo-0.62.0ubuntu0libgit2/src/bin/cargo/main.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/bin/cargo/main.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,7 +1,6 @@ #![warn(rust_2018_idioms)] // while we're getting used to 2018 #![allow(clippy::all)] -use cargo::core::shell::Shell; use cargo::util::toml::StringOrVec; use cargo::util::CliError; use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config}; @@ -22,25 +21,17 @@ #[cfg(not(feature = "pretty-env-logger"))] env_logger::init_from_env("CARGO_LOG"); - let mut config = match Config::default() { - Ok(cfg) => cfg, - Err(e) => { - let mut shell = Shell::new(); - cargo::exit_with_error(e.into(), &mut shell) - } - }; + let mut config = cli::LazyConfig::new(); - let result = match cargo::ops::fix_maybe_exec_rustc(&config) { - Ok(true) => Ok(()), - Ok(false) => { - let _token = cargo::util::job::setup(); - cli::main(&mut config) - } - Err(e) => Err(CliError::from(e)), + let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() { + cargo::ops::fix_exec_rustc(config.get(), &lock_addr).map_err(|e| CliError::from(e)) + } else { + let _token = cargo::util::job::setup(); + cli::main(&mut config) }; match result { - Err(e) => cargo::exit_with_error(e, &mut *config.shell()), + Err(e) => cargo::exit_with_error(e, &mut config.get_mut().shell()), Ok(()) => {} } } @@ -166,19 +157,36 @@ let command = match path { Some(command) => command, None => { - let suggestions = list_commands(config); - let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c); - let err = anyhow::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean); + let err = if cmd.starts_with('+') { + anyhow::format_err!( + "no such subcommand: `{}`\n\n\t\ + Cargo does not handle `+toolchain` directives.\n\t\ + Did you mean to invoke `cargo` through `rustup` instead?", + cmd + ) + } else { + let suggestions = list_commands(config); + let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c); + + anyhow::format_err!( + "no such subcommand: `{}`{}\n\n\t\ + View all installed commands with `cargo --list`", + cmd, + did_you_mean + ) + }; + return Err(CliError::new(err, 101)); } }; let cargo_exe = config.cargo_exe()?; - let err = match ProcessBuilder::new(&command) - .env(cargo::CARGO_ENV, cargo_exe) - .args(args) - .exec_replace() - { + let mut cmd = ProcessBuilder::new(&command); + cmd.env(cargo::CARGO_ENV, cargo_exe).args(args); + if let Some(client) = config.jobserver_from_env() { + cmd.inherit_jobserver(client); + } + let err = match cmd.exec_replace() { Ok(()) => return Ok(()), Err(e) => e, }; @@ -204,11 +212,28 @@ } fn search_directories(config: &Config) -> Vec { - let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")]; - if let Some(val) = env::var_os("PATH") { - dirs.extend(env::split_paths(&val)); - } - dirs + let mut path_dirs = if let Some(val) = env::var_os("PATH") { + env::split_paths(&val).collect() + } else { + vec![] + }; + + let home_bin = config.home().clone().into_path_unlocked().join("bin"); + + // If any of that PATH elements contains `home_bin`, do not + // add it again. This is so that the users can control priority + // of it using PATH, while preserving the historical + // behavior of preferring it over system global directories even + // when not in PATH at all. + // See https://github.com/rust-lang/cargo/issues/11020 for details. + // + // Note: `p == home_bin` will ignore trailing slash, but we don't + // `canonicalize` the paths. + if !path_dirs.iter().any(|p| p == &home_bin) { + path_dirs.insert(0, home_bin); + }; + + path_dirs } fn init_git_transports(config: &Config) { @@ -239,4 +264,27 @@ unsafe { git2_curl::register(handle); } + + // Disabling the owner validation in git can, in theory, lead to code execution + // vulnerabilities. However, libgit2 does not launch executables, which is the foundation of + // the original security issue. Meanwhile, issues with refusing to load git repos in + // `CARGO_HOME` for example will likely be very frustrating for users. So, we disable the + // validation. + // + // For further discussion of Cargo's current interactions with git, see + // + // https://github.com/rust-lang/rfcs/pull/3279 + // + // and in particular the subsection on "Git support". + // + // Note that we only disable this when Cargo is run as a binary. If Cargo is used as a library, + // this code won't be invoked. Instead, developers will need to explicitly disable the + // validation in their code. This is inconvenient, but won't accidentally open consuming + // applications up to security issues if they use git2 to open repositories elsewhere in their + // code. + unsafe { + if git2::opts::set_verify_owner_validation(false).is_err() { + return; + } + } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_config.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_config.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_config.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_config.rs 2022-10-20 06:00:42.000000000 +0000 @@ -46,6 +46,12 @@ pub timing_outputs: Vec, } +fn default_parallelism() -> CargoResult { + Ok(available_parallelism() + .context("failed to determine the amount of parallelism available")? + .get() as u32) +} + impl BuildConfig { /// Parses all config files to learn about build configuration. Currently /// configured options are: @@ -57,16 +63,13 @@ /// * `target.$target.libfoo.metadata` pub fn new( config: &Config, - jobs: Option, + jobs: Option, keep_going: bool, requested_targets: &[String], mode: CompileMode, ) -> CargoResult { let cfg = config.build_config()?; let requested_kinds = CompileKind::from_requested_targets(config, requested_targets)?; - if jobs == Some(0) { - anyhow::bail!("jobs must be at least 1") - } if jobs.is_some() && config.jobserver_from_env().is_some() { config.shell().warn( "a `-j` argument was passed to Cargo but Cargo is \ @@ -75,13 +78,15 @@ )?; } let jobs = match jobs.or(cfg.jobs) { - Some(j) => j, - None => available_parallelism() - .context("failed to determine the amount of parallelism available")? - .get() as u32, + None => default_parallelism()?, + Some(0) => anyhow::bail!("jobs may not be 0"), + Some(j) if j < 0 => (default_parallelism()? as i32 + j).max(1) as u32, + Some(j) => j as u32, }; - if jobs == 0 { - anyhow::bail!("jobs may not be 0"); + + if config.cli_unstable().build_std.is_some() && requested_kinds[0].is_host() { + // TODO: This should eventually be fixed. + anyhow::bail!("-Zbuild-std requires --target"); } Ok(BuildConfig { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_context/target_info.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_context/target_info.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_context/target_info.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_context/target_info.rs 2022-10-20 06:00:42.000000000 +0000 @@ -597,7 +597,7 @@ /// provided) for artifacts that are always built for the host (plugins, build scripts, ...). /// For those artifacts, _only_ `host.*.rustflags` is respected, and no other configuration /// sources, _regardless of the value of `target-applies-to-host`_. This is counterintuitive, but -/// necessary to retain bacwkards compatibility with older versions of Cargo. +/// necessary to retain backwards compatibility with older versions of Cargo. fn env_args( config: &Config, requested_kinds: &[CompileKind], diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_plan.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_plan.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/build_plan.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/build_plan.rs 2022-10-20 06:00:42.000000000 +0000 @@ -78,7 +78,7 @@ .ok_or_else(|| anyhow::format_err!("unicode program string required"))? .to_string(); self.cwd = Some(cmd.get_cwd().unwrap().to_path_buf()); - for arg in cmd.get_args().iter() { + for arg in cmd.get_args() { self.args.push( arg.to_str() .ok_or_else(|| anyhow::format_err!("unicode argument string required"))? diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/compilation.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/compilation.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/compilation.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/compilation.rs 2022-10-20 06:00:42.000000000 +0000 @@ -194,6 +194,7 @@ let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?); let cmd = fill_rustc_tool_env(rustdoc, unit); let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?; + cmd.retry_with_argfile(true); unit.target.edition().cmd_edition_arg(&mut cmd); for crate_type in unit.target.rustc_crate_types() { @@ -346,6 +347,10 @@ metadata.license_file.as_ref().unwrap_or(&String::new()), ) .env("CARGO_PKG_AUTHORS", &pkg.authors().join(":")) + .env( + "CARGO_PKG_RUST_VERSION", + &pkg.rust_version().unwrap_or(&String::new()), + ) .cwd(pkg.root()); // Apply any environment variables from the config @@ -404,7 +409,7 @@ let matching_runner = cfgs.next(); if let Some((key, runner)) = cfgs.next() { anyhow::bail!( - "several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`\n\ + "several matching instances of `target.'cfg(..)'.runner` in configurations\n\ first match `{}` located in {}\n\ second match `{}` located in {}", matching_runner.unwrap().0, diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/compile_kind.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/compile_kind.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/compile_kind.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/compile_kind.rs 2022-10-20 06:00:42.000000000 +0000 @@ -2,7 +2,7 @@ use crate::util::errors::CargoResult; use crate::util::interning::InternedString; use crate::util::{Config, StableHasher}; -use anyhow::{bail, Context as _}; +use anyhow::Context as _; use serde::Serialize; use std::collections::BTreeSet; use std::fs; @@ -65,9 +65,6 @@ }; if !targets.is_empty() { - if targets.len() > 1 && !config.cli_unstable().multitarget { - bail!("specifying multiple `--target` flags requires `-Zmultitarget`") - } return dedup(targets); } @@ -182,14 +179,20 @@ /// See [`CompileKind::fingerprint_hash`]. pub fn fingerprint_hash(&self) -> u64 { let mut hasher = StableHasher::new(); - self.name.hash(&mut hasher); - if self.name.ends_with(".json") { - // This may have some performance concerns, since it is called - // fairly often. If that ever seems worth fixing, consider - // embedding this in `CompileTarget`. - if let Ok(contents) = fs::read_to_string(self.name) { + match self + .name + .ends_with(".json") + .then(|| fs::read_to_string(self.name)) + { + Some(Ok(contents)) => { + // This may have some performance concerns, since it is called + // fairly often. If that ever seems worth fixing, consider + // embedding this in `CompileTarget`. contents.hash(&mut hasher); } + _ => { + self.name.hash(&mut hasher); + } } hasher.finish() } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/context/compilation_files.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/context/compilation_files.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/context/compilation_files.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/context/compilation_files.rs 2022-10-20 06:00:42.000000000 +0000 @@ -587,10 +587,12 @@ unit.mode.hash(&mut hasher); cx.lto[unit].hash(&mut hasher); - // Artifacts compiled for the host should have a different metadata - // piece than those compiled for the target, so make sure we throw in - // the unit's `kind` as well - unit.kind.hash(&mut hasher); + // Artifacts compiled for the host should have a different + // metadata piece than those compiled for the target, so make sure + // we throw in the unit's `kind` as well. Use `fingerprint_hash` + // so that the StableHash doesn't change based on the pathnames + // of the custom target JSON spec files. + unit.kind.fingerprint_hash().hash(&mut hasher); // Finally throw in the target name/kind. This ensures that concurrent // compiles of targets in the same crate don't collide. diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/context/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/context/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/context/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/context/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -92,7 +92,7 @@ let jobserver = match bcx.config.jobserver_from_env() { Some(c) => c.clone(), None => { - let client = Client::new(bcx.build_config.jobs as usize) + let client = Client::new(bcx.jobs() as usize) .with_context(|| "failed to create jobserver")?; client.acquire_raw()?; client @@ -224,7 +224,8 @@ let mut unstable_opts = false; let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?; args.extend(compiler::lto_args(&self, unit)); - args.extend(compiler::features_args(&self, unit)); + args.extend(compiler::features_args(unit)); + args.extend(compiler::check_cfg_args(&self, unit)); let script_meta = self.find_build_script_metadata(unit); if let Some(meta) = script_meta { @@ -234,6 +235,14 @@ args.push(cfg.into()); } + if !output.check_cfgs.is_empty() { + args.push("-Zunstable-options".into()); + for check_cfg in &output.check_cfgs { + args.push("--check-cfg".into()); + args.push(check_cfg.into()); + } + } + for (lt, arg) in &output.linker_args { if lt.applies_to(&unit.target) { args.push("-C".into()); @@ -594,7 +603,7 @@ } pub fn new_jobserver(&mut self) -> CargoResult { - let tokens = self.bcx.build_config.jobs as usize; + let tokens = self.bcx.jobs() as usize; let client = Client::new(tokens).with_context(|| "failed to create jobserver")?; // Drain the client fully diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/custom_build.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/custom_build.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/custom_build.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/custom_build.rs 2022-10-20 06:00:42.000000000 +0000 @@ -29,6 +29,8 @@ pub linker_args: Vec<(LinkType, String)>, /// Various `--cfg` flags to pass to the compiler. pub cfgs: Vec, + /// Various `--check-cfg` flags to pass to the compiler. + pub check_cfgs: Vec, /// Additional environment variables to run the compiler with. pub env: Vec<(String, String)>, /// Metadata to pass to the immediate dependencies. @@ -322,6 +324,10 @@ paths::create_dir_all(&script_out_dir)?; let nightly_features_allowed = cx.bcx.config.nightly_features_allowed; + let extra_check_cfg = match cx.bcx.config.cli_unstable().check_cfg { + Some((_, _, _, output)) => output, + None => false, + }; let targets: Vec = unit.pkg.targets().to_vec(); // Need a separate copy for the fresh closure. let targets_fresh = targets.clone(); @@ -432,6 +438,7 @@ &pkg_descr, &script_out_dir, &script_out_dir, + extra_check_cfg, nightly_features_allowed, &targets, )?; @@ -459,6 +466,7 @@ &pkg_descr, &prev_script_out_dir, &script_out_dir, + extra_check_cfg, nightly_features_allowed, &targets_fresh, )?, @@ -511,6 +519,7 @@ pkg_descr: &str, script_out_dir_when_generated: &Path, script_out_dir: &Path, + extra_check_cfg: bool, nightly_features_allowed: bool, targets: &[Target], ) -> CargoResult { @@ -521,6 +530,7 @@ pkg_descr, script_out_dir_when_generated, script_out_dir, + extra_check_cfg, nightly_features_allowed, targets, ) @@ -536,6 +546,7 @@ pkg_descr: &str, script_out_dir_when_generated: &Path, script_out_dir: &Path, + extra_check_cfg: bool, nightly_features_allowed: bool, targets: &[Target], ) -> CargoResult { @@ -543,6 +554,7 @@ let mut library_links = Vec::new(); let mut linker_args = Vec::new(); let mut cfgs = Vec::new(); + let mut check_cfgs = Vec::new(); let mut env = Vec::new(); let mut metadata = Vec::new(); let mut rerun_if_changed = Vec::new(); @@ -669,6 +681,13 @@ linker_args.push((LinkType::All, value)); } "rustc-cfg" => cfgs.push(value.to_string()), + "rustc-check-cfg" => { + if extra_check_cfg { + check_cfgs.push(value.to_string()); + } else { + warnings.push(format!("cargo:{} requires -Zcheck-cfg=output flag", key)); + } + } "rustc-env" => { let (key, val) = BuildOutput::parse_rustc_env(&value, &whence)?; // Build scripts aren't allowed to set RUSTC_BOOTSTRAP. @@ -728,6 +747,7 @@ library_links, linker_args, cfgs, + check_cfgs, env, metadata, rerun_if_changed, @@ -968,6 +988,10 @@ &unit.pkg.to_string(), &prev_script_out_dir, &script_out_dir, + match cx.bcx.config.cli_unstable().check_cfg { + Some((_, _, _, output)) => output, + None => false, + }, cx.bcx.config.nightly_features_allowed, unit.pkg.targets(), ) diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/fingerprint.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/fingerprint.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/fingerprint.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/fingerprint.rs 2022-10-20 06:00:42.000000000 +0000 @@ -313,7 +313,6 @@ //! use std::collections::hash_map::{Entry, HashMap}; -use std::convert::TryInto; use std::env; use std::hash::{self, Hash, Hasher}; use std::io; @@ -1831,7 +1830,7 @@ // This is a bit of a tricky statement, but here we're *removing* the // dependency on environment variables that were defined specifically for - // the command itself. Environment variables returend by `get_envs` includes + // the command itself. Environment variables returned by `get_envs` includes // environment variables like: // // * `OUT_DIR` if applicable diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/future_incompat.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/future_incompat.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/future_incompat.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/future_incompat.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,7 +1,7 @@ //! Support for future-incompatible warning reporting. use crate::core::compiler::BuildContext; -use crate::core::{Dependency, PackageId, Workspace}; +use crate::core::{Dependency, PackageId, QueryKind, Workspace}; use crate::sources::SourceConfigMap; use crate::util::{iter_join, CargoResult, Config}; use anyhow::{bail, format_err, Context}; @@ -236,7 +236,7 @@ let mut report: BTreeMap = BTreeMap::new(); for per_package in per_package_reports { let package_spec = format!( - "{}:{}", + "{}@{}", per_package.package_id.name(), per_package.package_id.version() ); @@ -293,7 +293,7 @@ Ok(dep) => dep, Err(_) => return false, }; - match source.query_vec(&dep) { + match source.query_vec(&dep, QueryKind::Exact) { Poll::Ready(Ok(sum)) => { summaries.push((pkg_id, sum)); false @@ -415,10 +415,10 @@ let manifest = bcx.packages.get_one(*package_id).unwrap().manifest(); format!( " - - {name} + - {package_spec} - Repository: {url} - - Detailed warning command: `cargo report future-incompatibilities --id {id} --package {name}`", - name = format!("{}:{}", package_id.name(), package_id.version()), + - Detailed warning command: `cargo report future-incompatibilities --id {id} --package {package_spec}`", + package_spec = format!("{}@{}", package_id.name(), package_id.version()), url = manifest .metadata() .repository diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/job_queue.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/job_queue.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/job_queue.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/job_queue.rs 2022-10-20 06:00:42.000000000 +0000 @@ -55,11 +55,11 @@ use std::io; use std::marker; use std::sync::Arc; +use std::thread::{self, Scope}; use std::time::Duration; use anyhow::{format_err, Context as _}; use cargo_util::ProcessBuilder; -use crossbeam_utils::thread::Scope; use jobserver::{Acquired, Client, HelperThread}; use log::{debug, trace}; use semver::Version; @@ -162,7 +162,7 @@ /// The list of jobs that we have not yet started executing, but have /// retrieved from the `queue`. We eagerly pull jobs off the main queue to /// allow us to request jobserver tokens pretty early. - pending_queue: Vec<(Unit, Job)>, + pending_queue: Vec<(Unit, Job, usize)>, print: DiagnosticPrinter<'cfg>, /// How many jobs we've finished @@ -556,29 +556,36 @@ .take() .map(move |srv| srv.start(move |msg| messages.push(Message::FixDiagnostic(msg)))); - crossbeam_utils::thread::scope(move |scope| { - match state.drain_the_queue(cx, plan, scope, &helper) { + thread::scope( + move |scope| match state.drain_the_queue(cx, plan, scope, &helper) { Some(err) => Err(err), None => Ok(()), - } - }) - .expect("child threads shouldn't panic") + }, + ) } } impl<'cfg> DrainState<'cfg> { - fn spawn_work_if_possible( + fn spawn_work_if_possible<'s>( &mut self, cx: &mut Context<'_, '_>, jobserver_helper: &HelperThread, - scope: &Scope<'_>, + scope: &'s Scope<'s, '_>, ) -> CargoResult<()> { // Dequeue as much work as we can, learning about everything // possible that can run. Note that this is also the point where we // start requesting job tokens. Each job after the first needs to // request a token. - while let Some((unit, job)) = self.queue.dequeue() { - self.pending_queue.push((unit, job)); + while let Some((unit, job, priority)) = self.queue.dequeue() { + // We want to keep the pieces of work in the `pending_queue` sorted + // by their priorities, and insert the current job at its correctly + // sorted position: following the lower priority jobs, and the ones + // with the same priority (since they were dequeued before the + // current one, we also keep that relation). + let idx = self + .pending_queue + .partition_point(|&(_, _, p)| p <= priority); + self.pending_queue.insert(idx, (unit, job, priority)); if self.active.len() + self.pending_queue.len() > 1 { jobserver_helper.request_token(); } @@ -587,8 +594,11 @@ // Now that we've learned of all possible work that we can execute // try to spawn it so long as we've got a jobserver token which says // we're able to perform some parallel work. + // The `pending_queue` is sorted in ascending priority order, and we + // remove items from its end to schedule the highest priority items + // sooner. while self.has_extra_tokens() && !self.pending_queue.is_empty() { - let (unit, job) = self.pending_queue.remove(0); + let (unit, job, _) = self.pending_queue.pop().unwrap(); *self.counts.get_mut(&unit.pkg.package_id()).unwrap() -= 1; if !cx.bcx.build_config.build_plan { // Print out some nice progress information. @@ -807,11 +817,11 @@ /// /// This returns an Option to prevent the use of `?` on `Result` types /// because it is important for the loop to carefully handle errors. - fn drain_the_queue( + fn drain_the_queue<'s>( mut self, cx: &mut Context<'_, '_>, plan: &mut BuildPlan, - scope: &Scope<'_>, + scope: &'s Scope<'s, '_>, jobserver_helper: &HelperThread, ) -> Option { trace!("queue: {:#?}", self.queue); @@ -997,7 +1007,7 @@ /// /// Fresh jobs block until finished (which should be very fast!), Dirty /// jobs will spawn a thread in the background and return immediately. - fn run(&mut self, unit: &Unit, job: Job, cx: &Context<'_, '_>, scope: &Scope<'_>) { + fn run<'s>(&mut self, unit: &Unit, job: Job, cx: &Context<'_, '_>, scope: &'s Scope<'s, '_>) { let id = JobId(self.next_id); self.next_id = self.next_id.checked_add(1).unwrap(); @@ -1072,7 +1082,7 @@ } Freshness::Dirty => { self.timings.add_dirty(); - scope.spawn(move |_| { + scope.spawn(move || { doit(JobState { id, messages: messages.clone(), diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -292,7 +292,7 @@ )?; add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; } - add_custom_env(&mut rustc, &script_outputs, script_metadata); + add_custom_flags(&mut rustc, &script_outputs, script_metadata)?; } for output in outputs.iter() { @@ -408,9 +408,6 @@ } if key.0 == current_id { - for cfg in &output.cfgs { - rustc.arg("--cfg").arg(cfg); - } if pass_l_flag { for name in output.library_links.iter() { rustc.arg("-l").arg(name); @@ -431,22 +428,6 @@ } Ok(()) } - - // Add all custom environment variables present in `state` (after they've - // been put there by one of the `build_scripts`) to the command provided. - fn add_custom_env( - rustc: &mut ProcessBuilder, - build_script_outputs: &BuildScriptOutputs, - metadata: Option, - ) { - if let Some(metadata) = metadata { - if let Some(output) = build_script_outputs.get(metadata) { - for &(ref name, ref value) in output.env.iter() { - rustc.env(name, value); - } - } - } - } } /// Link the compiled target (often of form `foo-{metadata_hash}`) to the @@ -645,7 +626,8 @@ paths::create_dir_all(&doc_dir)?; rustdoc.arg("-o").arg(&doc_dir); - rustdoc.args(&features_args(cx, unit)); + rustdoc.args(&features_args(unit)); + rustdoc.args(&check_cfg_args(cx, unit)); add_error_format_and_color(cx, &mut rustdoc); add_allow_features(cx, &mut rustdoc); @@ -682,7 +664,7 @@ rustdoc.arg("--scrape-examples-target-crate").arg(name); } } - } else if cx.bcx.scrape_units.len() > 0 && cx.bcx.ws.is_member(&unit.pkg) { + } else if cx.bcx.scrape_units.len() > 0 && cx.bcx.ws.unit_needs_doc_scrape(unit) { // We only pass scraped examples to packages in the workspace // since examples are only coming from reverse-dependencies of workspace packages @@ -712,16 +694,11 @@ let mut output_options = OutputOptions::new(cx, unit); let script_metadata = cx.find_build_script_metadata(unit); Ok(Work::new(move |state| { - if let Some(script_metadata) = script_metadata { - if let Some(output) = build_script_outputs.lock().unwrap().get(script_metadata) { - for cfg in output.cfgs.iter() { - rustdoc.arg("--cfg").arg(cfg); - } - for &(ref name, ref value) in output.env.iter() { - rustdoc.env(name, value); - } - } - } + add_custom_flags( + &mut rustdoc, + &build_script_outputs.lock().unwrap(), + script_metadata, + )?; let crate_dir = doc_dir.join(&crate_name); if crate_dir.exists() { // Remove output from a previous build. This ensures that stale @@ -754,7 +731,7 @@ // The --crate-version flag could have already been passed in RUSTDOCFLAGS // or as an extra compiler argument for rustdoc fn crate_version_flag_already_present(rustdoc: &ProcessBuilder) -> bool { - rustdoc.get_args().iter().any(|flag| { + rustdoc.get_args().any(|flag| { flag.to_str() .map_or(false, |flag| flag.starts_with(RUSTDOC_CRATE_VERSION_FLAG)) }) @@ -816,11 +793,11 @@ ) { // Terminal width explicitly provided - only useful for testing. (Some(Some(width)), _) => { - cmd.arg(format!("-Zterminal-width={}", width)); + cmd.arg(format!("--diagnostic-width={}", width)); } // Terminal width was not explicitly provided but flag was provided - common case. (Some(None), Some(width)) => { - cmd.arg(format!("-Zterminal-width={}", width)); + cmd.arg(format!("--diagnostic-width={}", width)); } // User didn't opt-in. _ => (), @@ -965,7 +942,8 @@ cmd.arg("--cfg").arg("test"); } - cmd.args(&features_args(cx, unit)); + cmd.args(&features_args(unit)); + cmd.args(&check_cfg_args(cx, unit)); let meta = cx.files().metadata(unit); cmd.arg("-C").arg(&format!("metadata={}", meta)); @@ -1039,33 +1017,56 @@ Ok(()) } -/// Features with --cfg and all features with --check-cfg -fn features_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec { - let mut args = Vec::with_capacity(unit.features.len() + 2); +/// All active features for the unit passed as --cfg +fn features_args(unit: &Unit) -> Vec { + let mut args = Vec::with_capacity(unit.features.len() * 2); for feat in &unit.features { args.push(OsString::from("--cfg")); args.push(OsString::from(format!("feature=\"{}\"", feat))); } - if cx.bcx.config.cli_unstable().check_cfg_features { - // This generate something like this: - // - values(feature) - // - values(feature, "foo", "bar") - let mut arg = OsString::from("values(feature"); - for (&feat, _) in unit.pkg.summary().features() { - arg.push(", \""); - arg.push(&feat); - arg.push("\""); - } - arg.push(")"); + args +} +/// Generate the --check-cfg arguments for the unit +fn check_cfg_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec { + if let Some((features, well_known_names, well_known_values, _output)) = + cx.bcx.config.cli_unstable().check_cfg + { + let mut args = Vec::with_capacity(unit.pkg.summary().features().len() * 2 + 4); args.push(OsString::from("-Zunstable-options")); - args.push(OsString::from("--check-cfg")); - args.push(arg); - } - args + if features { + // This generate something like this: + // - values(feature) + // - values(feature, "foo", "bar") + let mut arg = OsString::from("values(feature"); + for (&feat, _) in unit.pkg.summary().features() { + arg.push(", \""); + arg.push(&feat); + arg.push("\""); + } + arg.push(")"); + + args.push(OsString::from("--check-cfg")); + args.push(arg); + } + + if well_known_names { + args.push(OsString::from("--check-cfg")); + args.push(OsString::from("names()")); + } + + if well_known_values { + args.push(OsString::from("--check-cfg")); + args.push(OsString::from("values()")); + } + + args + } else { + Vec::new() + } } fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec { @@ -1157,6 +1158,32 @@ } Ok(()) +} + +/// Add custom flags from the output a of build-script to a `ProcessBuilder` +fn add_custom_flags( + cmd: &mut ProcessBuilder, + build_script_outputs: &BuildScriptOutputs, + metadata: Option, +) -> CargoResult<()> { + if let Some(metadata) = metadata { + if let Some(output) = build_script_outputs.get(metadata) { + for cfg in output.cfgs.iter() { + cmd.arg("--cfg").arg(cfg); + } + if !output.check_cfgs.is_empty() { + cmd.arg("-Zunstable-options"); + for check_cfg in &output.check_cfgs { + cmd.arg("--check-cfg").arg(check_cfg); + } + } + for &(ref name, ref value) in output.env.iter() { + cmd.env(name, value); + } + } + } + + Ok(()) } /// Generates a list of `--extern` arguments. diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/output_depinfo.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/output_depinfo.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/output_depinfo.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/output_depinfo.rs 2022-10-20 06:00:42.000000000 +0000 @@ -22,6 +22,7 @@ //! dependencies are not included under the assumption that changes to them can //! be detected via changes to `Cargo.lock`. +use cargo_util::paths::normalize_path; use std::collections::{BTreeSet, HashSet}; use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; @@ -33,16 +34,21 @@ fn render_filename>(path: P, basedir: Option<&str>) -> CargoResult { let path = path.as_ref(); - let relpath = match basedir { - None => path, - Some(base) => match path.strip_prefix(base) { - Ok(relpath) => relpath, - _ => path, - }, - }; - relpath - .to_str() - .ok_or_else(|| internal(format!("path `{:?}` not utf-8", relpath))) + if let Some(basedir) = basedir { + let norm_path = normalize_path(path); + let norm_basedir = normalize_path(basedir.as_ref()); + match norm_path.strip_prefix(norm_basedir) { + Ok(relpath) => wrap_path(relpath), + _ => wrap_path(path), + } + } else { + wrap_path(path) + } +} + +fn wrap_path(path: &Path) -> CargoResult { + path.to_str() + .ok_or_else(|| internal(format!("path `{:?}` not utf-8", path))) .map(|f| f.replace(" ", "\\ ")) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/standard_lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/standard_lib.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/standard_lib.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/standard_lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -9,10 +9,13 @@ use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace}; use crate::ops::{self, Packages}; use crate::util::errors::CargoResult; +use crate::Config; use std::collections::{HashMap, HashSet}; use std::env; use std::path::PathBuf; +use super::BuildConfig; + /// Parse the `-Zbuild-std` flag. pub fn parse_unstable_flag(value: Option<&str>) -> Vec { // This is a temporary hack until there is a more principled way to @@ -31,13 +34,45 @@ crates.into_iter().map(|s| s.to_string()).collect() } +pub(crate) fn std_crates(config: &Config, units: Option<&[Unit]>) -> Option> { + let crates = config.cli_unstable().build_std.as_ref()?.clone(); + + // Only build libtest if it looks like it is needed. + let mut crates = crates.clone(); + // If we know what units we're building, we can filter for libtest depending on the jobs. + if let Some(units) = units { + if units + .iter() + .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) + { + // Only build libtest when libstd is built (libtest depends on libstd) + if crates.iter().any(|c| c == "std") && !crates.iter().any(|c| c == "test") { + crates.push("test".to_string()); + } + } + } else { + // We don't know what jobs are going to be run, so download libtest just in case. + if !crates.iter().any(|c| c == "test") { + crates.push("test".to_string()) + } + } + + Some(crates) +} + /// Resolve the standard library dependencies. pub fn resolve_std<'cfg>( ws: &Workspace<'cfg>, target_data: &RustcTargetData<'cfg>, - requested_targets: &[CompileKind], + build_config: &BuildConfig, crates: &[String], ) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> { + if build_config.build_plan { + ws.config() + .shell() + .warn("-Zbuild-std does not currently fully support --build-plan")?; + } + let src_path = detect_sysroot_src_path(target_data)?; let to_patch = [ "rustc-std-workspace-core", @@ -114,7 +149,7 @@ let resolve = ops::resolve_ws_with_opts( &std_ws, target_data, - requested_targets, + &build_config.requested_kinds, &cli_features, &specs, HasDevUnits::No, diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/timings.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/timings.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/timings.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/timings.rs 2022-10-20 06:00:42.000000000 +0000 @@ -30,7 +30,7 @@ start_str: String, /// A summary of the root units. /// - /// Tuples of `(package_description, target_descrptions)`. + /// Tuples of `(package_description, target_descriptions)`. root_targets: Vec<(String, Vec)>, /// The build profile. profile: String, @@ -445,7 +445,7 @@ self.total_dirty, self.total_fresh + self.total_dirty, max_concurrency, - bcx.build_config.jobs, + bcx.jobs(), num_cpus, self.start_str, total_time, @@ -733,6 +733,7 @@

Cargo Build Timings

+See Documentation "#; static HTML_CANVAS: &str = r#" diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/unit_dependencies.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/unit_dependencies.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/compiler/unit_dependencies.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/compiler/unit_dependencies.rs 2022-10-20 06:00:42.000000000 +0000 @@ -708,14 +708,9 @@ } } - // Add all units being scraped for examples as a dependency of Doc units. - if state.ws.is_member(&unit.pkg) { + // Add all units being scraped for examples as a dependency of top-level Doc units. + if state.ws.unit_needs_doc_scrape(unit) { for scrape_unit in state.scrape_units.iter() { - // This needs to match the FeaturesFor used in cargo_compile::generate_targets. - let unit_for = UnitFor::new_host( - scrape_unit.target.proc_macro(), - unit_for.root_compile_kind(), - ); deps_of(scrape_unit, state, unit_for)?; ret.push(new_unit_dep( state, diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/features.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/features.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/features.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/features.rs 2022-10-20 06:00:42.000000000 +0000 @@ -86,7 +86,9 @@ //! `CliUnstable. Remove the `(unstable)` note in the clap help text if //! necessary. //! 2. Remove `masquerade_as_nightly_cargo` from any tests, and remove -//! `cargo-features` from `Cargo.toml` test files if any. +//! `cargo-features` from `Cargo.toml` test files if any. You can +//! quickly find what needs to be removed by searching for the name +//! of the feature, e.g. `print_im_a_teapot` //! 3. Update the docs in unstable.md to move the section to the bottom //! and summarize it similar to the other entries. Update the rest of the //! documentation to add the new feature. @@ -100,6 +102,7 @@ use cargo_util::ProcessBuilder; use serde::{Deserialize, Serialize}; +use crate::core::resolver::ResolveBehavior; use crate::util::errors::CargoResult; use crate::util::{indented_lines, iter_join}; use crate::Config; @@ -158,7 +161,7 @@ /// /// This requires a static value due to the way clap works, otherwise I /// would have built this dynamically. - pub const CLI_VALUES: &'static [&'static str] = &["2015", "2018", "2021"]; + pub const CLI_VALUES: [&'static str; 3] = ["2015", "2018", "2021"]; /// Returns the first version that a particular edition was released on /// stable. @@ -240,6 +243,14 @@ Edition2021 => false, } } + + pub(crate) fn default_resolve_behavior(&self) -> ResolveBehavior { + if *self >= Edition::Edition2021 { + ResolveBehavior::V2 + } else { + ResolveBehavior::V1 + } + } } impl fmt::Display for Edition { @@ -414,7 +425,7 @@ (unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"), // Allow specifying rustflags directly in a profile - (unstable, workspace_inheritance, "", "reference/unstable.html#workspace-inheritance"), + (stable, workspace_inheritance, "1.64", "reference/unstable.html#workspace-inheritance"), } pub struct Feature { @@ -641,7 +652,8 @@ build_std_features: Option> = ("Configure features enabled for the standard library itself when building the standard library"), config_include: bool = ("Enable the `include` key in config files"), credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"), - check_cfg_features: bool = ("Enable compile-time checking of features in `cfg`"), + #[serde(deserialize_with = "deserialize_check_cfg")] + check_cfg: Option<(/*features:*/ bool, /*well_known_names:*/ bool, /*well_known_values:*/ bool, /*output:*/ bool)> = ("Specify scope of compile-time checking of `cfg` names/values"), doctest_in_workspace: bool = ("Compile doctests with paths relative to the workspace root"), doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"), dual_proc_macros: bool = ("Build proc-macros for both the host and the target"), @@ -653,7 +665,7 @@ no_index_update: bool = ("Do not update the registry index even if the cache is outdated"), panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"), host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"), - http_registry: bool = ("Support HTTP-based crate registries"), + sparse_registry: bool = ("Support plain-HTTP-based crate registries"), target_applies_to_host: bool = ("Enable the `target-applies-to-host` key in the .cargo/config.toml file"), rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"), separate_nightlies: bool = (HIDDEN), @@ -719,6 +731,8 @@ const STABILIZED_TIMINGS: &str = "The -Ztimings option has been stabilized as --timings."; +const STABILISED_MULTITARGET: &str = "Multiple `--target` options are now always available."; + fn deserialize_build_std<'de, D>(deserializer: D) -> Result>, D::Error> where D: serde::Deserializer<'de>, @@ -733,6 +747,47 @@ )) } +fn deserialize_check_cfg<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + use serde::de::Error; + let crates = match >>::deserialize(deserializer)? { + Some(list) => list, + None => return Ok(None), + }; + + parse_check_cfg(crates.into_iter()).map_err(D::Error::custom) +} + +fn parse_check_cfg( + it: impl Iterator>, +) -> CargoResult> { + let mut features = false; + let mut well_known_names = false; + let mut well_known_values = false; + let mut output = false; + + for e in it { + match e.as_ref() { + "features" => features = true, + "names" => well_known_names = true, + "values" => well_known_values = true, + "output" => output = true, + _ => bail!("unstable check-cfg only takes `features`, `names`, `values` or `output` as valid inputs"), + } + } + + Ok(Some(( + features, + well_known_names, + well_known_values, + output, + ))) +} + impl CliUnstable { pub fn parse( &mut self, @@ -840,7 +895,9 @@ "minimal-versions" => self.minimal_versions = parse_empty(k, v)?, "advanced-env" => self.advanced_env = parse_empty(k, v)?, "config-include" => self.config_include = parse_empty(k, v)?, - "check-cfg-features" => self.check_cfg_features = parse_empty(k, v)?, + "check-cfg" => { + self.check_cfg = v.map_or(Ok(None), |v| parse_check_cfg(v.split(',')))? + } "dual-proc-macros" => self.dual_proc_macros = parse_empty(k, v)?, // can also be set in .cargo/config or with and ENV "mtime-on-use" => self.mtime_on_use = parse_empty(k, v)?, @@ -876,10 +933,10 @@ self.features = Some(feats); } "separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?, - "multitarget" => self.multitarget = parse_empty(k, v)?, + "multitarget" => stabilized_warn(k, "1.64", STABILISED_MULTITARGET), "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, "terminal-width" => self.terminal_width = Some(parse_usize_opt(v)?), - "http-registry" => self.http_registry = parse_empty(k, v)?, + "sparse-registry" => self.sparse_registry = parse_empty(k, v)?, "namespaced-features" => stabilized_warn(k, "1.60", STABILISED_NAMESPACED_FEATURES), "weak-dep-features" => stabilized_warn(k, "1.60", STABILIZED_WEAK_DEP_FEATURES), "credential-process" => self.credential_process = parse_empty(k, v)?, diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/manifest.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/manifest.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/manifest.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/manifest.rs 2022-10-20 06:00:42.000000000 +0000 @@ -26,6 +26,15 @@ Virtual(VirtualManifest), } +impl EitherManifest { + pub(crate) fn workspace_config(&self) -> &WorkspaceConfig { + match *self { + EitherManifest::Real(ref r) => r.workspace_config(), + EitherManifest::Virtual(ref v) => v.workspace_config(), + } + } +} + /// Contains all the information about a package, as loaded from a `Cargo.toml`. /// /// This is deserialized using the [`TomlManifest`] type. diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -8,11 +8,13 @@ pub use self::registry::Registry; pub use self::resolver::{Resolve, ResolveVersion}; pub use self::shell::{Shell, Verbosity}; -pub use self::source::{GitReference, Source, SourceId, SourceMap}; +pub use self::source::{GitReference, QueryKind, Source, SourceId, SourceMap}; pub use self::summary::{FeatureMap, FeatureValue, Summary}; pub use self::workspace::{ - InheritableFields, MaybePackage, Workspace, WorkspaceConfig, WorkspaceRootConfig, + find_workspace_root, resolve_relative_path, MaybePackage, Workspace, WorkspaceConfig, + WorkspaceRootConfig, }; +pub use crate::util::toml::InheritableFields; pub mod compiler; pub mod dependency; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/package_id_spec.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/package_id_spec.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/package_id_spec.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/package_id_spec.rs 2022-10-20 06:00:42.000000000 +0000 @@ -41,8 +41,10 @@ /// "https://crates.io/foo", /// "https://crates.io/foo#1.2.3", /// "https://crates.io/foo#bar:1.2.3", + /// "https://crates.io/foo#bar@1.2.3", /// "foo", /// "foo:1.2.3", + /// "foo@1.2.3", /// ]; /// for spec in specs { /// assert!(PackageIdSpec::parse(spec).is_ok()); @@ -65,7 +67,7 @@ ); } } - let mut parts = spec.splitn(2, ':'); + let mut parts = spec.splitn(2, [':', '@']); let name = parts.next().unwrap(); let version = match parts.next() { Some(version) => Some(version.to_semver()?), @@ -122,7 +124,7 @@ })?; match frag { Some(fragment) => { - let mut parts = fragment.splitn(2, ':'); + let mut parts = fragment.splitn(2, [':', '@']); let name_or_version = parts.next().unwrap(); match parts.next() { Some(part) => { @@ -268,7 +270,7 @@ } for id in ids { if version_cnt[id.version()] == 1 { - msg.push_str(&format!("\n {}:{}", spec.name(), id.version())); + msg.push_str(&format!("\n {}@{}", spec.name(), id.version())); } else { msg.push_str(&format!("\n {}", PackageIdSpec::from_package_id(*id))); } @@ -290,11 +292,11 @@ } None => { printed_name = true; - write!(f, "{}", self.name)? + write!(f, "{}", self.name)?; } } if let Some(ref v) = self.version { - write!(f, "{}{}", if printed_name { ":" } else { "#" }, v)?; + write!(f, "{}{}", if printed_name { "@" } else { "#" }, v)?; } Ok(()) } @@ -329,10 +331,11 @@ #[test] fn good_parsing() { - fn ok(spec: &str, expected: PackageIdSpec) { + #[track_caller] + fn ok(spec: &str, expected: PackageIdSpec, expected_rendered: &str) { let parsed = PackageIdSpec::parse(spec).unwrap(); assert_eq!(parsed, expected); - assert_eq!(parsed.to_string(), spec); + assert_eq!(parsed.to_string(), expected_rendered); } ok( @@ -342,6 +345,7 @@ version: None, url: Some(Url::parse("https://crates.io/foo").unwrap()), }, + "https://crates.io/foo", ); ok( "https://crates.io/foo#1.2.3", @@ -350,6 +354,7 @@ version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("https://crates.io/foo").unwrap()), }, + "https://crates.io/foo#1.2.3", ); ok( "https://crates.io/foo#bar:1.2.3", @@ -358,6 +363,16 @@ version: Some("1.2.3".to_semver().unwrap()), url: Some(Url::parse("https://crates.io/foo").unwrap()), }, + "https://crates.io/foo#bar@1.2.3", + ); + ok( + "https://crates.io/foo#bar@1.2.3", + PackageIdSpec { + name: InternedString::new("bar"), + version: Some("1.2.3".to_semver().unwrap()), + url: Some(Url::parse("https://crates.io/foo").unwrap()), + }, + "https://crates.io/foo#bar@1.2.3", ); ok( "foo", @@ -366,6 +381,7 @@ version: None, url: None, }, + "foo", ); ok( "foo:1.2.3", @@ -374,6 +390,16 @@ version: Some("1.2.3".to_semver().unwrap()), url: None, }, + "foo@1.2.3", + ); + ok( + "foo@1.2.3", + PackageIdSpec { + name: InternedString::new("foo"), + version: Some("1.2.3".to_semver().unwrap()), + url: None, + }, + "foo@1.2.3", ); } @@ -382,6 +408,9 @@ assert!(PackageIdSpec::parse("baz:").is_err()); assert!(PackageIdSpec::parse("baz:*").is_err()); assert!(PackageIdSpec::parse("baz:1.0").is_err()); + assert!(PackageIdSpec::parse("baz@").is_err()); + assert!(PackageIdSpec::parse("baz@*").is_err()); + assert!(PackageIdSpec::parse("baz@1.0").is_err()); assert!(PackageIdSpec::parse("https://baz:1.0").is_err()); assert!(PackageIdSpec::parse("https://#baz:1.0").is_err()); } @@ -397,5 +426,7 @@ assert!(!PackageIdSpec::parse("foo").unwrap().matches(bar)); assert!(PackageIdSpec::parse("foo:1.2.3").unwrap().matches(foo)); assert!(!PackageIdSpec::parse("foo:1.2.2").unwrap().matches(foo)); + assert!(PackageIdSpec::parse("foo@1.2.3").unwrap().matches(foo)); + assert!(!PackageIdSpec::parse("foo@1.2.2").unwrap().matches(foo)); } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/registry.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/registry.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/registry.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/registry.rs 2022-10-20 06:00:42.000000000 +0000 @@ -2,7 +2,7 @@ use std::task::Poll; use crate::core::PackageSet; -use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Source, SourceId, SourceMap, Summary}; use crate::sources::config::SourceConfigMap; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -19,14 +19,13 @@ fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency, fuzzy: bool) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, &mut |s| ret.push(s), fuzzy) - .map_ok(|()| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|()| ret) } fn describe_source(&self, source: SourceId) -> String; @@ -327,7 +326,7 @@ .get_mut(dep.source_id()) .expect("loaded source not present"); - let summaries = match source.query_vec(dep)? { + let summaries = match source.query_vec(dep, QueryKind::Exact)? { Poll::Ready(deps) => deps, Poll::Pending => { deps_pending.push(dep_remaining); @@ -483,7 +482,7 @@ for &s in self.overrides.iter() { let src = self.sources.get_mut(s).unwrap(); let dep = Dependency::new_override(dep.package_name(), s); - let mut results = match src.query_vec(&dep) { + let mut results = match src.query_vec(&dep, QueryKind::Exact) { Poll::Ready(results) => results?, Poll::Pending => return Poll::Pending, }; @@ -575,8 +574,8 @@ fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll> { assert!(self.patches_locked); let (override_summary, n, to_warn) = { @@ -671,11 +670,7 @@ } f(lock(locked, all_patches, summary)) }; - return if fuzzy { - source.fuzzy_query(dep, callback) - } else { - source.query(dep, callback) - }; + return source.query(dep, kind, callback); } // If we have an override summary then we query the source @@ -694,11 +689,7 @@ n += 1; to_warn = Some(summary); }; - let pend = if fuzzy { - source.fuzzy_query(dep, callback)? - } else { - source.query(dep, callback)? - }; + let pend = source.query(dep, kind, callback); if pend.is_pending() { return Poll::Pending; } @@ -889,7 +880,7 @@ // No summaries found, try to help the user figure out what is wrong. if let Some(locked) = locked { // Since the locked patch did not match anything, try the unlocked one. - let orig_matches = match source.query_vec(orig_patch) { + let orig_matches = match source.query_vec(orig_patch, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } @@ -914,7 +905,7 @@ // Try checking if there are *any* packages that match this by name. let name_only_dep = Dependency::new_override(orig_patch.package_name(), orig_patch.source_id()); - let name_summaries = match source.query_vec(&name_only_dep) { + let name_summaries = match source.query_vec(&name_only_dep, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/dep_cache.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/dep_cache.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/dep_cache.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/dep_cache.rs 2022-10-20 06:00:42.000000000 +0000 @@ -16,7 +16,9 @@ ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering, VersionPreferences, }; -use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary}; +use crate::core::{ + Dependency, FeatureValue, PackageId, PackageIdSpec, QueryKind, Registry, Summary, +}; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -100,13 +102,9 @@ } let mut ret = Vec::new(); - let ready = self.registry.query( - dep, - &mut |s| { - ret.push(s); - }, - false, - )?; + let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| { + ret.push(s); + })?; if ready.is_pending() { self.registry_cache.insert(dep.clone(), Poll::Pending); return Poll::Pending; @@ -127,7 +125,7 @@ dep.version_req() ); - let mut summaries = match self.registry.query_vec(dep, false)? { + let mut summaries = match self.registry.query_vec(dep, QueryKind::Exact)? { Poll::Ready(s) => s.into_iter(), Poll::Pending => { self.registry_cache.insert(dep.clone(), Poll::Pending); diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/errors.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/errors.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/errors.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/errors.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,7 +1,7 @@ use std::fmt; use std::task::Poll; -use crate::core::{Dependency, PackageId, Registry, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary}; use crate::util::lev_distance::lev_distance; use crate::util::{Config, VersionExt}; use anyhow::Error; @@ -182,7 +182,7 @@ msg.push_str("` does not have these features.\n"); msg.push_str( " It has an optional dependency with that name, \ - but but that dependency uses the \"dep:\" \ + but that dependency uses the \"dep:\" \ syntax in the features table, so it does not have an \ implicit feature with that name.\n", ); @@ -228,7 +228,7 @@ new_dep.set_version_req(all_req); let mut candidates = loop { - match registry.query_vec(&new_dep, false) { + match registry.query_vec(&new_dep, QueryKind::Exact) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { @@ -294,7 +294,7 @@ // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing` // was meant. So we try asking the registry for a `fuzzy` search for suggestions. let mut candidates = loop { - match registry.query_vec(&new_dep, true) { + match registry.query_vec(&new_dep, QueryKind::Fuzzy) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/types.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/types.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/resolver/types.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/resolver/types.rs 2022-10-20 06:00:42.000000000 +0000 @@ -119,11 +119,12 @@ } } - pub fn to_manifest(&self) -> Option { + pub fn to_manifest(&self) -> String { match self { - ResolveBehavior::V1 => None, - ResolveBehavior::V2 => Some("2".to_string()), + ResolveBehavior::V1 => "1", + ResolveBehavior::V2 => "2", } + .to_owned() } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/shell.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/shell.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/shell.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/shell.rs 2022-10-20 06:00:42.000000000 +0000 @@ -344,6 +344,17 @@ self.output.write_stdout(fragment, color) } + /// Write a styled fragment + /// + /// Caller is responsible for deciding whether [`Shell::verbosity`] is affects output. + pub fn write_stderr( + &mut self, + fragment: impl fmt::Display, + color: &ColorSpec, + ) -> CargoResult<()> { + self.output.write_stderr(fragment, color) + } + /// Prints a message to stderr and translates ANSI escape code into console colors. pub fn print_ansi_stderr(&mut self, message: &[u8]) -> CargoResult<()> { if self.needs_clear { @@ -445,6 +456,22 @@ } ShellOut::Write(ref mut w) => { write!(w, "{}", fragment)?; + } + } + Ok(()) + } + + /// Write a styled fragment + fn write_stderr(&mut self, fragment: impl fmt::Display, color: &ColorSpec) -> CargoResult<()> { + match *self { + ShellOut::Stream { ref mut stderr, .. } => { + stderr.reset()?; + stderr.set_color(&color)?; + write!(stderr, "{}", fragment)?; + stderr.reset()?; + } + ShellOut::Write(ref mut w) => { + write!(w, "{}", fragment)?; } } Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/source/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/source/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/source/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/source/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -29,21 +29,16 @@ fn requires_precise(&self) -> bool; /// Attempts to find the packages that match a dependency request. - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll>; - - /// 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, - /// whereas an `Index` source may return dependencies that have the same canonicalization. - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, &mut |s| ret.push(s)).map_ok(|_| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret) } /// Ensure that the source is fully up-to-date for the current session on the next query. @@ -103,7 +98,7 @@ /// Query if a package is yanked. Only registry sources can mark packages /// as yanked. This ignores the yanked whitelist. - fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult; + fn is_yanked(&mut self, _pkg: PackageId) -> Poll>; /// Block until all outstanding Poll::Pending requests are `Poll::Ready`. /// @@ -115,6 +110,15 @@ fn block_until_ready(&mut self) -> CargoResult<()>; } +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum QueryKind { + Exact, + /// Each source gets to define what `close` means for it. + /// Path/Git sources may return all dependencies that are at that URI, + /// whereas an `Index` source may return dependencies that have the same canonicalization. + Fuzzy, +} + pub enum MaybePackage { Ready(Package), Download { url: String, descriptor: String }, @@ -142,17 +146,13 @@ } /// Forwards to `Source::query`. - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - (**self).query(dep, f) - } - - /// Forwards to `Source::query`. - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).fuzzy_query(dep, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { @@ -190,7 +190,7 @@ (**self).add_to_yanked_whitelist(pkgs); } - fn is_yanked(&mut self, pkg: PackageId) -> CargoResult { + fn is_yanked(&mut self, pkg: PackageId) -> Poll> { (**self).is_yanked(pkg) } @@ -216,16 +216,13 @@ (**self).requires_precise() } - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - (**self).query(dep, f) - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).fuzzy_query(dep, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { @@ -260,7 +257,7 @@ (**self).add_to_yanked_whitelist(pkgs); } - fn is_yanked(&mut self, pkg: PackageId) -> CargoResult { + fn is_yanked(&mut self, pkg: PackageId) -> Poll> { (**self).is_yanked(pkg) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/source/source_id.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/source/source_id.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/source/source_id.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/source/source_id.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,4 +1,5 @@ use crate::core::PackageId; +use crate::sources::registry::CRATES_IO_HTTP_INDEX; use crate::sources::{DirectorySource, CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::sources::{GitSource, PathSource, RegistrySource}; use crate::util::{CanonicalUrl, CargoResult, Config, IntoUrl}; @@ -206,6 +207,18 @@ }) } + /// Returns the `SourceId` corresponding to the main repository, using the + /// sparse HTTP index if allowed. + pub fn crates_io_maybe_sparse_http(config: &Config) -> CargoResult { + if config.cli_unstable().sparse_registry { + config.check_registry_index_not_set()?; + let url = CRATES_IO_HTTP_INDEX.into_url().unwrap(); + SourceId::new(SourceKind::Registry, url, Some(CRATES_IO_REGISTRY)) + } else { + Self::crates_io(config) + } + } + /// Gets the `SourceId` associated with given name of the remote registry. pub fn alt_registry(config: &Config, key: &str) -> CargoResult { let url = config.get_registry_index(key)?; @@ -356,7 +369,8 @@ SourceKind::Registry => {} _ => return false, } - self.inner.url.as_str() == CRATES_IO_INDEX + let url = self.inner.url.as_str(); + url == CRATES_IO_INDEX || url == CRATES_IO_HTTP_INDEX } /// Hashes `self`. diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/core/workspace.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/workspace.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/core/workspace.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/core/workspace.rs 2022-10-20 06:00:42.000000000 +0000 @@ -11,22 +11,23 @@ use toml_edit::easy as toml; use url::Url; +use crate::core::compiler::Unit; use crate::core::features::Features; use crate::core::registry::PackageRegistry; use crate::core::resolver::features::CliFeatures; use crate::core::resolver::ResolveBehavior; -use crate::core::{Dependency, Edition, FeatureValue, PackageId, PackageIdSpec}; +use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec}; use crate::core::{EitherManifest, Package, SourceId, VirtualManifest}; use crate::ops; use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::util::errors::{CargoResult, ManifestError}; use crate::util::interning::InternedString; use crate::util::lev_distance; -use crate::util::toml::{ - read_manifest, StringOrBool, TomlDependency, TomlProfiles, VecStringOrBool, -}; +use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles}; use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl}; use cargo_util::paths; +use cargo_util::paths::normalize_path; +use pathdiff::diff_paths; /// The core abstraction in Cargo for working with a workspace of crates. /// @@ -132,6 +133,34 @@ WorkspaceConfig::Member { .. } => None, } } + + /// Returns the path of the workspace root based on this `[workspace]` configuration. + /// + /// Returns `None` if the root is not explicitly known. + /// + /// * `self_path` is the path of the manifest this `WorkspaceConfig` is located. + /// * `look_from` is the path where discovery started (usually the current + /// working directory), used for `workspace.exclude` checking. + fn get_ws_root(&self, self_path: &Path, look_from: &Path) -> Option { + match self { + WorkspaceConfig::Root(ances_root_config) => { + debug!("find_root - found a root checking exclusion"); + if !ances_root_config.is_excluded(look_from) { + debug!("find_root - found!"); + Some(self_path.to_owned()) + } else { + None + } + } + WorkspaceConfig::Member { + root: Some(path_to_root), + } => { + debug!("find_root - found pointer"); + Some(read_root_pointer(self_path, path_to_root)) + } + WorkspaceConfig::Member { .. } => None, + } + } } /// Intermediate configuration of a workspace root in a manifest. @@ -258,16 +287,12 @@ // - If the root package specifies edition 2021, use v2. // - Otherwise, use the default v1. self.resolve_behavior = match self.root_maybe() { - MaybePackage::Package(p) => p.manifest().resolve_behavior().or_else(|| { - if p.manifest().edition() >= Edition::Edition2021 { - Some(ResolveBehavior::V2) - } else { - None - } - }), - MaybePackage::Virtual(vm) => vm.resolve_behavior(), + MaybePackage::Package(p) => p + .manifest() + .resolve_behavior() + .unwrap_or_else(|| p.manifest().edition().default_resolve_behavior()), + MaybePackage::Virtual(vm) => vm.resolve_behavior().unwrap_or(ResolveBehavior::V1), } - .unwrap_or(ResolveBehavior::V1); } /// Returns the current package of this workspace. @@ -591,67 +616,23 @@ /// Returns an error if `manifest_path` isn't actually a valid manifest or /// if some other transient error happens. fn find_root(&mut self, manifest_path: &Path) -> CargoResult> { - fn read_root_pointer(member_manifest: &Path, root_link: &str) -> PathBuf { - let path = member_manifest - .parent() - .unwrap() - .join(root_link) - .join("Cargo.toml"); - debug!("find_root - pointer {}", path.display()); - paths::normalize_path(&path) - } - + let current = self.packages.load(manifest_path)?; + match current + .workspace_config() + .get_ws_root(manifest_path, manifest_path) { - let current = self.packages.load(manifest_path)?; - match *current.workspace_config() { - WorkspaceConfig::Root(_) => { - debug!("find_root - is root {}", manifest_path.display()); - return Ok(Some(manifest_path.to_path_buf())); - } - WorkspaceConfig::Member { - root: Some(ref path_to_root), - } => return Ok(Some(read_root_pointer(manifest_path, path_to_root))), - WorkspaceConfig::Member { root: None } => {} - } - } - - for path in paths::ancestors(manifest_path, None).skip(2) { - if path.ends_with("target/package") { - break; - } - - let ances_manifest_path = path.join("Cargo.toml"); - debug!("find_root - trying {}", ances_manifest_path.display()); - if ances_manifest_path.exists() { - match *self.packages.load(&ances_manifest_path)?.workspace_config() { - WorkspaceConfig::Root(ref ances_root_config) => { - debug!("find_root - found a root checking exclusion"); - if !ances_root_config.is_excluded(manifest_path) { - debug!("find_root - found!"); - return Ok(Some(ances_manifest_path)); - } - } - WorkspaceConfig::Member { - root: Some(ref path_to_root), - } => { - debug!("find_root - found pointer"); - return Ok(Some(read_root_pointer(&ances_manifest_path, path_to_root))); - } - WorkspaceConfig::Member { .. } => {} - } - } - - // Don't walk across `CARGO_HOME` when we're looking for the - // workspace root. Sometimes a package will be organized with - // `CARGO_HOME` pointing inside of the workspace root or in the - // current package, but we don't want to mistakenly try to put - // crates.io crates into the workspace by accident. - if self.config.home() == path { - break; - } + Some(root_path) => { + debug!("find_root - is root {}", manifest_path.display()); + Ok(Some(root_path)) + } + None => find_workspace_root_with_loader(manifest_path, self.config, |self_path| { + Ok(self + .packages + .load(self_path)? + .workspace_config() + .get_ws_root(self_path, manifest_path)) + }), } - - Ok(None) } /// After the root of a workspace has been located, probes for all members @@ -701,6 +682,8 @@ })?; } + self.find_path_deps(&root_manifest_path, &root_manifest_path, false)?; + if let Some(default) = default_members_paths { for path in default { let normalized_path = paths::normalize_path(&path); @@ -731,7 +714,7 @@ self.default_members.push(self.current_manifest.clone()) } - self.find_path_deps(&root_manifest_path, &root_manifest_path, false) + Ok(()) } fn find_path_deps( @@ -1525,6 +1508,15 @@ ms } + + /// Returns true if `unit` should depend on the output of Docscrape units. + pub fn unit_needs_doc_scrape(&self, unit: &Unit) -> bool { + // We do not add scraped units for Host units, as they're either build scripts + // (not documented) or proc macros (have no scrape-able exports). Additionally, + // naively passing a proc macro's unit_for to new_unit_dep will currently cause + // Cargo to panic, see issue #10545. + self.is_member(&unit.pkg) && !unit.target.for_host() + } } impl<'cfg> Packages<'cfg> { @@ -1653,191 +1645,146 @@ .collect::, _>>()?; Ok(res) } -} -/// A group of fields that are inheritable by members of the workspace -#[derive(Clone, Debug, Default)] -pub struct InheritableFields { - dependencies: Option>, - version: Option, - authors: Option>, - description: Option, - homepage: Option, - documentation: Option, - readme: Option, - keywords: Option>, - categories: Option>, - license: Option, - license_file: Option, - repository: Option, - publish: Option, - edition: Option, - badges: Option>>, -} - -impl InheritableFields { - pub fn new( - dependencies: Option>, - version: Option, - authors: Option>, - description: Option, - homepage: Option, - documentation: Option, - readme: Option, - keywords: Option>, - categories: Option>, - license: Option, - license_file: Option, - repository: Option, - publish: Option, - edition: Option, - badges: Option>>, - ) -> InheritableFields { - Self { - dependencies, - version, - authors, - description, - homepage, - documentation, - readme, - keywords, - categories, - license, - license_file, - repository, - publish, - edition, - badges, - } + pub fn inheritable(&self) -> &InheritableFields { + &self.inheritable_fields } +} - pub fn dependencies(&self) -> CargoResult> { - self.dependencies.clone().map_or( - Err(anyhow!("`workspace.dependencies` was not defined")), - |d| Ok(d), - ) - } - - pub fn get_dependency(&self, name: &str) -> CargoResult { - self.dependencies.clone().map_or( - Err(anyhow!("`workspace.dependencies` was not defined")), - |deps| { - deps.get(name).map_or( - Err(anyhow!( - "`dependency.{}` was not found in `workspace.dependencies`", - name - )), - |dep| Ok(dep.clone()), +pub fn resolve_relative_path( + label: &str, + old_root: &Path, + new_root: &Path, + rel_path: &str, +) -> CargoResult { + let joined_path = normalize_path(&old_root.join(rel_path)); + match diff_paths(joined_path, new_root) { + None => Err(anyhow!( + "`{}` was defined in {} but could not be resolved with {}", + label, + old_root.display(), + new_root.display() + )), + Some(path) => Ok(path + .to_str() + .ok_or_else(|| { + anyhow!( + "`{}` resolved to non-UTF value (`{}`)", + label, + path.display() ) - }, - ) - } - - pub fn version(&self) -> CargoResult { - self.version - .clone() - .map_or(Err(anyhow!("`workspace.version` was not defined")), |d| { - Ok(d) - }) - } - - pub fn authors(&self) -> CargoResult> { - self.authors - .clone() - .map_or(Err(anyhow!("`workspace.authors` was not defined")), |d| { - Ok(d) - }) - } - - pub fn description(&self) -> CargoResult { - self.description.clone().map_or( - Err(anyhow!("`workspace.description` was not defined")), - |d| Ok(d), - ) + })? + .to_owned()), } +} - pub fn homepage(&self) -> CargoResult { - self.homepage - .clone() - .map_or(Err(anyhow!("`workspace.homepage` was not defined")), |d| { - Ok(d) - }) - } +/// Finds the path of the root of the workspace. +pub fn find_workspace_root(manifest_path: &Path, config: &Config) -> CargoResult> { + find_workspace_root_with_loader(manifest_path, config, |self_path| { + let key = self_path.parent().unwrap(); + let source_id = SourceId::for_path(key)?; + let (manifest, _nested_paths) = read_manifest(self_path, source_id, config)?; + Ok(manifest + .workspace_config() + .get_ws_root(self_path, manifest_path)) + }) +} - pub fn documentation(&self) -> CargoResult { - self.documentation.clone().map_or( - Err(anyhow!("`workspace.documentation` was not defined")), - |d| Ok(d), - ) +/// Finds the path of the root of the workspace. +/// +/// This uses a callback to determine if the given path tells us what the +/// workspace root is. +fn find_workspace_root_with_loader( + manifest_path: &Path, + config: &Config, + mut loader: impl FnMut(&Path) -> CargoResult>, +) -> CargoResult> { + // Check if there are any workspace roots that have already been found that would work + { + let roots = config.ws_roots.borrow(); + // Iterate through the manifests parent directories until we find a workspace + // root. Note we skip the first item since that is just the path itself + for current in manifest_path.ancestors().skip(1) { + if let Some(ws_config) = roots.get(current) { + if !ws_config.is_excluded(manifest_path) { + // Add `Cargo.toml` since ws_root is the root and not the file + return Ok(Some(current.join("Cargo.toml"))); + } + } + } } - pub fn readme(&self) -> CargoResult { - self.readme - .clone() - .map_or(Err(anyhow!("`workspace.readme` was not defined")), |d| { - Ok(d) - }) + for ances_manifest_path in find_root_iter(manifest_path, config) { + debug!("find_root - trying {}", ances_manifest_path.display()); + if let Some(ws_root_path) = loader(&ances_manifest_path)? { + return Ok(Some(ws_root_path)); + } } + Ok(None) +} - pub fn keywords(&self) -> CargoResult> { - self.keywords - .clone() - .map_or(Err(anyhow!("`workspace.keywords` was not defined")), |d| { - Ok(d) - }) - } +fn read_root_pointer(member_manifest: &Path, root_link: &str) -> PathBuf { + let path = member_manifest + .parent() + .unwrap() + .join(root_link) + .join("Cargo.toml"); + debug!("find_root - pointer {}", path.display()); + paths::normalize_path(&path) +} - pub fn categories(&self) -> CargoResult> { - self.categories.clone().map_or( - Err(anyhow!("`workspace.categories` was not defined")), - |d| Ok(d), - ) - } +fn find_root_iter<'a>( + manifest_path: &'a Path, + config: &'a Config, +) -> impl Iterator + 'a { + LookBehind::new(paths::ancestors(manifest_path, None).skip(2)) + .take_while(|path| !path.curr.ends_with("target/package")) + // Don't walk across `CARGO_HOME` when we're looking for the + // workspace root. Sometimes a package will be organized with + // `CARGO_HOME` pointing inside of the workspace root or in the + // current package, but we don't want to mistakenly try to put + // crates.io crates into the workspace by accident. + .take_while(|path| { + if let Some(last) = path.last { + config.home() != last + } else { + true + } + }) + .map(|path| path.curr.join("Cargo.toml")) + .filter(|ances_manifest_path| ances_manifest_path.exists()) +} - pub fn license(&self) -> CargoResult { - self.license - .clone() - .map_or(Err(anyhow!("`workspace.license` was not defined")), |d| { - Ok(d) - }) - } +struct LookBehindWindow<'a, T: ?Sized> { + curr: &'a T, + last: Option<&'a T>, +} - pub fn license_file(&self) -> CargoResult { - self.license_file.clone().map_or( - Err(anyhow!("`workspace.license_file` was not defined")), - |d| Ok(d), - ) - } - - pub fn repository(&self) -> CargoResult { - self.repository.clone().map_or( - Err(anyhow!("`workspace.repository` was not defined")), - |d| Ok(d), - ) - } +struct LookBehind<'a, T: ?Sized, K: Iterator> { + iter: K, + last: Option<&'a T>, +} - pub fn publish(&self) -> CargoResult { - self.publish - .clone() - .map_or(Err(anyhow!("`workspace.publish` was not defined")), |d| { - Ok(d) - }) +impl<'a, T: ?Sized, K: Iterator> LookBehind<'a, T, K> { + fn new(items: K) -> Self { + Self { + iter: items, + last: None, + } } +} - pub fn edition(&self) -> CargoResult { - self.edition - .clone() - .map_or(Err(anyhow!("`workspace.edition` was not defined")), |d| { - Ok(d) - }) - } +impl<'a, T: ?Sized, K: Iterator> Iterator for LookBehind<'a, T, K> { + type Item = LookBehindWindow<'a, T>; - pub fn badges(&self) -> CargoResult>> { - self.badges - .clone() - .map_or(Err(anyhow!("`workspace.badges` was not defined")), |d| { - Ok(d) - }) + fn next(&mut self) -> Option { + match self.iter.next() { + None => None, + Some(next) => { + let last = self.last; + self.last = Some(next); + Some(LookBehindWindow { curr: next, last }) + } + } } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/lib.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/lib.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/lib.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/lib.rs 2022-10-20 06:00:42.000000000 +0000 @@ -5,6 +5,75 @@ // Due to some of the default clippy lints being somewhat subjective and not // necessarily an improvement, we prefer to not use them at this time. #![allow(clippy::all)] +#![allow(rustdoc::private_intra_doc_links)] + +//! # Cargo as a library +//! +//! Cargo, the Rust package manager, is also provided as a library. +//! +//! There are two places you can find API documentation of cargo-the-library, +//! +//! - and +//! - . +//! +//! Each of them targets on a slightly different audience. +//! +//! ## For external tool developers +//! +//! The documentation on contains public-facing items in cargo-the-library. +//! External tool developers may find it useful when trying to reuse existing building blocks from Cargo. +//! However, using Cargo as a library has drawbacks, especially cargo-the-library is unstable, +//! and there is no clear path to stabilize it soon at the time of writing. +//! See [The Cargo Book: External tools] for more on this topic. +//! +//! Cargo API documentation on docs.rs gets updates along with each Rust release. +//! Its version always has a 0 major version to state it is unstable. +//! The minor version is always +1 of rustc's minor version +//! (that is, `cargo 0.66.0` corresponds to `rustc 1.65`). +//! +//! ## For Cargo contributors +//! +//! The documentation on contains all items in Cargo. +//! Contributors of Cargo may find it useful as a reference of Cargo's implementation details. +//! It's built with `--document-private-items` rustdoc flag, +//! so you might expect to see some noise and strange items here. +//! The Cargo team and contributors strive for jotting down every details +//! from their brains in each issue and PR. +//! However, something might just disappear in the air with no reason. +//! This documentation can be seen as their extended minds, +//! sharing designs and hacks behind both public and private interfaces. +//! +//! If you are just diving into Cargo internals, [Cargo Architecture Overview] +//! is the best material to get a broader context of how Cargo works under the hood. +//! Things also worth a read are important concepts reside in source code, +//! which Cargo developers have been crafting for a while, namely +//! +//! - [`cargo::core::resolver`](crate::core::resolver), +//! - [`cargo::core::compiler::fingerprint`](core/compiler/fingerprint/index.html), +//! - [`cargo::util::config`](crate::util::config), +//! - [`cargo::ops::fix`](ops/fix/index.html), and +//! - [`cargo::sources::registry`](crate::sources::registry). +//! +//! This API documentation is published on each push of rust-lang/cargo master branch. +//! In other words, it always reflects the latest doc comments in source code on master branch. +//! +//! ## Contribute to Cargo documentations +//! +//! The Cargo team always continues improving all external and internal documentations. +//! If you spot anything could be better, don't hesitate to discuss with the team on +//! Zulip [`t-cargo` stream], or [submit an issue] right on GitHub. +//! There is also an issue label [`A-documenting-cargo-itself`], +//! which is generally for documenting user-facing [The Cargo Book], +//! but the Cargo team is welcome any form of enhancement for the [Cargo Contributor Guide] +//! and this API documentation as well. +//! +//! [The Cargo Book: External tools]: https://doc.rust-lang.org/stable/cargo/reference/external-tools.html +//! [Cargo Architecture Overview]: https://doc.crates.io/contrib/architecture +//! [`t-cargo` stream]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo +//! [submit an issue]: https://github.com/rust-lang/cargo/issues/new/choose +//! [`A-documenting-cargo-itself`]: https://github.com/rust-lang/cargo/labels/A-documenting-cargo-itself +//! [The Cargo Book]: https://doc.rust-lang.org/cargo/ +//! [Cargo Contributor Guide]: https://doc.crates.io/contrib/ use crate::core::shell::Verbosity::Verbose; use crate::core::Shell; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/crate_spec.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/crate_spec.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/crate_spec.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/crate_spec.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,63 @@ +//! Crate name parsing. + +use anyhow::Context as _; + +use super::Dependency; +use super::RegistrySource; +use crate::util::validate_package_name; +use crate::CargoResult; + +/// User-specified crate +/// +/// This can be a +/// - Name (e.g. `docopt`) +/// - Name and a version req (e.g. `docopt@^0.8`) +/// - Path +#[derive(Debug)] +pub struct CrateSpec { + /// Crate name + name: String, + /// Optional version requirement + version_req: Option, +} + +impl CrateSpec { + /// Convert a string to a `Crate` + pub fn resolve(pkg_id: &str) -> CargoResult { + let (name, version) = pkg_id + .split_once('@') + .map(|(n, v)| (n, Some(v))) + .unwrap_or((pkg_id, None)); + + validate_package_name(name, "dependency name", "")?; + + if let Some(version) = version { + semver::VersionReq::parse(version) + .with_context(|| format!("invalid version requirement `{version}`"))?; + } + + let id = Self { + name: name.to_owned(), + version_req: version.map(|s| s.to_owned()), + }; + + Ok(id) + } + + /// Generate a dependency entry for this crate specifier + pub fn to_dependency(&self) -> CargoResult { + let mut dep = Dependency::new(self.name()); + if let Some(version_req) = self.version_req() { + dep = dep.set_source(RegistrySource::new(version_req)); + } + Ok(dep) + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn version_req(&self) -> Option<&str> { + self.version_req.as_deref() + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/dependency.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/dependency.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/dependency.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/dependency.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,1127 @@ +use std::fmt::{Display, Formatter}; +use std::path::{Path, PathBuf}; + +use indexmap::IndexSet; +use toml_edit::KeyMut; + +use super::manifest::str_or_1_len_table; +use crate::core::GitReference; +use crate::core::SourceId; +use crate::core::Summary; +use crate::CargoResult; +use crate::Config; + +/// A dependency handled by Cargo +/// +/// `None` means the field will be blank in TOML +#[derive(Debug, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct Dependency { + /// The name of the dependency (as it is set in its `Cargo.toml` and known to crates.io) + pub name: String, + /// Whether the dependency is opted-in with a feature flag + pub optional: Option, + + /// List of features to add (or None to keep features unchanged). + pub features: Option>, + /// Whether default features are enabled + pub default_features: Option, + /// List of features inherited from a workspace dependency + pub inherited_features: Option>, + + /// Where the dependency comes from + pub source: Option, + /// Non-default registry + pub registry: Option, + + /// If the dependency is renamed, this is the new name for the dependency + /// as a string. None if it is not renamed. + pub rename: Option, +} + +impl Dependency { + /// Create a new dependency with a name + pub fn new(name: &str) -> Self { + Self { + name: name.into(), + optional: None, + features: None, + default_features: None, + inherited_features: None, + source: None, + registry: None, + rename: None, + } + } + + /// Set dependency to a given version + pub fn set_source(mut self, source: impl Into) -> Self { + self.source = Some(source.into()); + self + } + + /// Remove the existing version requirement + pub fn clear_version(mut self) -> Self { + match &mut self.source { + Some(Source::Registry(_)) => { + self.source = None; + } + Some(Source::Path(path)) => { + path.version = None; + } + Some(Source::Git(git)) => { + git.version = None; + } + Some(Source::Workspace(_workspace)) => {} + None => {} + } + self + } + + /// Set whether the dependency is optional + #[allow(dead_code)] + pub fn set_optional(mut self, opt: bool) -> Self { + self.optional = Some(opt); + self + } + + /// Set features as an array of string (does some basic parsing) + #[allow(dead_code)] + pub fn set_features(mut self, features: IndexSet) -> Self { + self.features = Some(features); + self + } + /// Set features as an array of string (does some basic parsing) + pub fn extend_features(mut self, features: impl IntoIterator) -> Self { + self.features + .get_or_insert_with(Default::default) + .extend(features); + self + } + + /// Set the value of default-features for the dependency + #[allow(dead_code)] + pub fn set_default_features(mut self, default_features: bool) -> Self { + self.default_features = Some(default_features); + self + } + + /// Set the alias for the dependency + pub fn set_rename(mut self, rename: &str) -> Self { + self.rename = Some(rename.into()); + self + } + + /// Set the value of registry for the dependency + pub fn set_registry(mut self, registry: impl Into) -> Self { + self.registry = Some(registry.into()); + self + } + + /// Set features as an array of string (does some basic parsing) + pub fn set_inherited_features(mut self, features: IndexSet) -> Self { + self.inherited_features = Some(features); + self + } + + /// Get the dependency source + pub fn source(&self) -> Option<&Source> { + self.source.as_ref() + } + + /// Get version of dependency + pub fn version(&self) -> Option<&str> { + match self.source()? { + Source::Registry(src) => Some(src.version.as_str()), + Source::Path(src) => src.version.as_deref(), + Source::Git(src) => src.version.as_deref(), + Source::Workspace(_) => None, + } + } + + /// Get registry of the dependency + pub fn registry(&self) -> Option<&str> { + self.registry.as_deref() + } + + /// Get the alias for the dependency (if any) + pub fn rename(&self) -> Option<&str> { + self.rename.as_deref() + } + + /// Whether default features are activated + pub fn default_features(&self) -> Option { + self.default_features + } + + /// Get whether the dep is optional + pub fn optional(&self) -> Option { + self.optional + } + + /// Get the SourceID for this dependency + pub fn source_id(&self, config: &Config) -> CargoResult> { + match &self.source.as_ref() { + Some(Source::Registry(_)) | None => { + if let Some(r) = self.registry() { + let source_id = SourceId::alt_registry(config, r)?; + Ok(MaybeWorkspace::Other(source_id)) + } else { + let source_id = SourceId::crates_io(config)?; + Ok(MaybeWorkspace::Other(source_id)) + } + } + Some(Source::Path(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)), + Some(Source::Git(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)), + Some(Source::Workspace(workspace)) => Ok(MaybeWorkspace::Workspace(workspace.clone())), + } + } + + /// Query to find this dependency + pub fn query( + &self, + config: &Config, + ) -> CargoResult> { + let source_id = self.source_id(config)?; + match source_id { + MaybeWorkspace::Workspace(workspace) => Ok(MaybeWorkspace::Workspace(workspace)), + MaybeWorkspace::Other(source_id) => Ok(MaybeWorkspace::Other( + crate::core::dependency::Dependency::parse( + self.name.as_str(), + self.version(), + source_id, + )?, + )), + } + } +} + +pub enum MaybeWorkspace { + Workspace(WorkspaceSource), + Other(T), +} + +impl Dependency { + /// Create a dependency from a TOML table entry + pub fn from_toml(crate_root: &Path, key: &str, item: &toml_edit::Item) -> CargoResult { + if let Some(version) = item.as_str() { + let dep = Self::new(key).set_source(RegistrySource::new(version)); + Ok(dep) + } else if let Some(table) = item.as_table_like() { + let (name, rename) = if let Some(value) = table.get("package") { + ( + value + .as_str() + .ok_or_else(|| invalid_type(key, "package", value.type_name(), "string"))? + .to_owned(), + Some(key.to_owned()), + ) + } else { + (key.to_owned(), None) + }; + + let source: Source = + if let Some(git) = table.get("git") { + let mut src = GitSource::new( + git.as_str() + .ok_or_else(|| invalid_type(key, "git", git.type_name(), "string"))?, + ); + if let Some(value) = table.get("branch") { + src = src.set_branch(value.as_str().ok_or_else(|| { + invalid_type(key, "branch", value.type_name(), "string") + })?); + } + if let Some(value) = table.get("tag") { + src = src.set_tag(value.as_str().ok_or_else(|| { + invalid_type(key, "tag", value.type_name(), "string") + })?); + } + if let Some(value) = table.get("rev") { + src = src.set_rev(value.as_str().ok_or_else(|| { + invalid_type(key, "rev", value.type_name(), "string") + })?); + } + if let Some(value) = table.get("version") { + src = src.set_version(value.as_str().ok_or_else(|| { + invalid_type(key, "version", value.type_name(), "string") + })?); + } + src.into() + } else if let Some(path) = table.get("path") { + let path = crate_root + .join(path.as_str().ok_or_else(|| { + invalid_type(key, "path", path.type_name(), "string") + })?); + let mut src = PathSource::new(path); + if let Some(value) = table.get("version") { + src = src.set_version(value.as_str().ok_or_else(|| { + invalid_type(key, "version", value.type_name(), "string") + })?); + } + src.into() + } else if let Some(version) = table.get("version") { + let src = RegistrySource::new(version.as_str().ok_or_else(|| { + invalid_type(key, "version", version.type_name(), "string") + })?); + src.into() + } else if let Some(workspace) = table.get("workspace") { + let workspace_bool = workspace.as_bool().ok_or_else(|| { + invalid_type(key, "workspace", workspace.type_name(), "bool") + })?; + if !workspace_bool { + anyhow::bail!("`{key}.workspace = false` is unsupported") + } + let src = WorkspaceSource::new(); + src.into() + } else { + anyhow::bail!("Unrecognized dependency source for `{key}`"); + }; + let registry = if let Some(value) = table.get("registry") { + Some( + value + .as_str() + .ok_or_else(|| invalid_type(key, "registry", value.type_name(), "string"))? + .to_owned(), + ) + } else { + None + }; + + let default_features = table.get("default-features").and_then(|v| v.as_bool()); + if table.contains_key("default_features") { + anyhow::bail!("Use of `default_features` in `{key}` is unsupported, please switch to `default-features`"); + } + + let features = if let Some(value) = table.get("features") { + Some( + value + .as_array() + .ok_or_else(|| invalid_type(key, "features", value.type_name(), "array"))? + .iter() + .map(|v| { + v.as_str().map(|s| s.to_owned()).ok_or_else(|| { + invalid_type(key, "features", v.type_name(), "string") + }) + }) + .collect::>>()?, + ) + } else { + None + }; + + let optional = table.get("optional").and_then(|v| v.as_bool()); + + let dep = Self { + name, + rename, + source: Some(source), + registry, + default_features, + features, + optional, + inherited_features: None, + }; + Ok(dep) + } else { + anyhow::bail!("Unrecognized` dependency entry format for `{key}"); + } + } + + /// Get the dependency name as defined in the manifest, + /// that is, either the alias (rename field if Some), + /// or the official package name (name field). + pub fn toml_key(&self) -> &str { + self.rename().unwrap_or(&self.name) + } + + /// Convert dependency to TOML + /// + /// Returns a tuple with the dependency's name and either the version as a `String` + /// or the path/git repository as an `InlineTable`. + /// (If the dependency is set as `optional` or `default-features` is set to `false`, + /// an `InlineTable` is returned in any case.) + /// + /// # Panic + /// + /// Panics if the path is relative + pub fn to_toml(&self, crate_root: &Path) -> toml_edit::Item { + assert!( + crate_root.is_absolute(), + "Absolute path needed, got: {}", + crate_root.display() + ); + let table: toml_edit::Item = match ( + self.optional.unwrap_or(false), + self.features.as_ref(), + self.default_features.unwrap_or(true), + self.source.as_ref(), + self.registry.as_ref(), + self.rename.as_ref(), + ) { + // Extra short when version flag only + ( + false, + None, + true, + Some(Source::Registry(RegistrySource { version: v })), + None, + None, + ) => toml_edit::value(v), + (false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => { + let mut table = toml_edit::InlineTable::default(); + table.set_dotted(true); + table.insert("workspace", true.into()); + toml_edit::value(toml_edit::Value::InlineTable(table)) + } + // Other cases are represented as an inline table + (_, _, _, _, _, _) => { + let mut table = toml_edit::InlineTable::default(); + + match &self.source { + Some(Source::Registry(src)) => { + table.insert("version", src.version.as_str().into()); + } + Some(Source::Path(src)) => { + let relpath = path_field(crate_root, &src.path); + if let Some(r) = src.version.as_deref() { + table.insert("version", r.into()); + } + table.insert("path", relpath.into()); + } + Some(Source::Git(src)) => { + table.insert("git", src.git.as_str().into()); + if let Some(branch) = src.branch.as_deref() { + table.insert("branch", branch.into()); + } + if let Some(tag) = src.tag.as_deref() { + table.insert("tag", tag.into()); + } + if let Some(rev) = src.rev.as_deref() { + table.insert("rev", rev.into()); + } + if let Some(r) = src.version.as_deref() { + table.insert("version", r.into()); + } + } + Some(Source::Workspace(_)) => { + table.insert("workspace", true.into()); + } + None => {} + } + if table.contains_key("version") { + if let Some(r) = self.registry.as_deref() { + table.insert("registry", r.into()); + } + } + + if self.rename.is_some() { + table.insert("package", self.name.as_str().into()); + } + if let Some(v) = self.default_features { + table.insert("default-features", v.into()); + } + if let Some(features) = self.features.as_ref() { + let features: toml_edit::Value = features.iter().cloned().collect(); + table.insert("features", features); + } + if let Some(v) = self.optional { + table.insert("optional", v.into()); + } + + toml_edit::value(toml_edit::Value::InlineTable(table)) + } + }; + + table + } + + /// Modify existing entry to match this dependency + pub fn update_toml<'k>( + &self, + crate_root: &Path, + key: &mut KeyMut<'k>, + item: &mut toml_edit::Item, + ) { + if str_or_1_len_table(item) { + // Nothing to preserve + *item = self.to_toml(crate_root); + key.fmt(); + } else if let Some(table) = item.as_table_like_mut() { + match &self.source { + Some(Source::Registry(src)) => { + table.insert("version", toml_edit::value(src.version.as_str())); + + for key in ["path", "git", "branch", "tag", "rev", "workspace"] { + table.remove(key); + } + } + Some(Source::Path(src)) => { + let relpath = path_field(crate_root, &src.path); + table.insert("path", toml_edit::value(relpath)); + if let Some(r) = src.version.as_deref() { + table.insert("version", toml_edit::value(r)); + } else { + table.remove("version"); + } + + for key in ["git", "branch", "tag", "rev", "workspace"] { + table.remove(key); + } + } + Some(Source::Git(src)) => { + table.insert("git", toml_edit::value(src.git.as_str())); + if let Some(branch) = src.branch.as_deref() { + table.insert("branch", toml_edit::value(branch)); + } else { + table.remove("branch"); + } + if let Some(tag) = src.tag.as_deref() { + table.insert("tag", toml_edit::value(tag)); + } else { + table.remove("tag"); + } + if let Some(rev) = src.rev.as_deref() { + table.insert("rev", toml_edit::value(rev)); + } else { + table.remove("rev"); + } + if let Some(r) = src.version.as_deref() { + table.insert("version", toml_edit::value(r)); + } else { + table.remove("version"); + } + + for key in ["path", "workspace"] { + table.remove(key); + } + } + Some(Source::Workspace(_)) => { + table.insert("workspace", toml_edit::value(true)); + table.set_dotted(true); + key.fmt(); + for key in [ + "version", + "registry", + "registry-index", + "path", + "git", + "branch", + "tag", + "rev", + "package", + "default-features", + ] { + table.remove(key); + } + } + None => {} + } + if table.contains_key("version") { + if let Some(r) = self.registry.as_deref() { + table.insert("registry", toml_edit::value(r)); + } else { + table.remove("registry"); + } + } else { + table.remove("registry"); + } + + if self.rename.is_some() { + table.insert("package", toml_edit::value(self.name.as_str())); + } + match self.default_features { + Some(v) => { + table.insert("default-features", toml_edit::value(v)); + } + None => { + table.remove("default-features"); + } + } + if let Some(new_features) = self.features.as_ref() { + let mut features = table + .get("features") + .and_then(|i| i.as_value()) + .and_then(|v| v.as_array()) + .and_then(|a| { + a.iter() + .map(|v| v.as_str()) + .collect::>>() + }) + .unwrap_or_default(); + features.extend(new_features.iter().map(|s| s.as_str())); + let features = toml_edit::value(features.into_iter().collect::()); + table.set_dotted(false); + table.insert("features", features); + } else { + table.remove("features"); + } + match self.optional { + Some(v) => { + table.set_dotted(false); + table.insert("optional", toml_edit::value(v)); + } + None => { + table.remove("optional"); + } + } + + table.fmt(); + } else { + unreachable!("Invalid dependency type: {}", item.type_name()); + } + } +} + +fn invalid_type(dep: &str, key: &str, actual: &str, expected: &str) -> anyhow::Error { + anyhow::format_err!("Found {actual} for {key} when {expected} was expected for {dep}") +} + +impl std::fmt::Display for Dependency { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(source) = self.source() { + write!(f, "{}@{}", self.name, source) + } else { + self.toml_key().fmt(f) + } + } +} + +impl<'s> From<&'s Summary> for Dependency { + fn from(other: &'s Summary) -> Self { + let source: Source = if let Some(path) = other.source_id().local_path() { + PathSource::new(path) + .set_version(other.version().to_string()) + .into() + } else if let Some(git_ref) = other.source_id().git_reference() { + let mut src = GitSource::new(other.source_id().url().to_string()) + .set_version(other.version().to_string()); + match git_ref { + GitReference::Branch(branch) => src = src.set_branch(branch), + GitReference::Tag(tag) => src = src.set_tag(tag), + GitReference::Rev(rev) => src = src.set_rev(rev), + GitReference::DefaultBranch => {} + } + src.into() + } else { + RegistrySource::new(other.version().to_string()).into() + }; + Dependency::new(other.name().as_str()).set_source(source) + } +} + +impl From for Dependency { + fn from(other: Summary) -> Self { + (&other).into() + } +} + +fn path_field(crate_root: &Path, abs_path: &Path) -> String { + let relpath = pathdiff::diff_paths(abs_path, crate_root).expect("both paths are absolute"); + let relpath = relpath.to_str().unwrap().replace('\\', "/"); + relpath +} + +/// Primary location of a dependency +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +pub enum Source { + /// Dependency from a registry + Registry(RegistrySource), + /// Dependency from a local path + Path(PathSource), + /// Dependency from a git repo + Git(GitSource), + /// Dependency from a workspace + Workspace(WorkspaceSource), +} + +impl Source { + /// Access the registry source, if present + pub fn as_registry(&self) -> Option<&RegistrySource> { + match self { + Self::Registry(src) => Some(src), + _ => None, + } + } + + /// Access the path source, if present + #[allow(dead_code)] + pub fn as_path(&self) -> Option<&PathSource> { + match self { + Self::Path(src) => Some(src), + _ => None, + } + } + + /// Access the git source, if present + #[allow(dead_code)] + pub fn as_git(&self) -> Option<&GitSource> { + match self { + Self::Git(src) => Some(src), + _ => None, + } + } + + /// Access the workspace source, if present + #[allow(dead_code)] + pub fn as_workspace(&self) -> Option<&WorkspaceSource> { + match self { + Self::Workspace(src) => Some(src), + _ => None, + } + } +} + +impl std::fmt::Display for Source { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Registry(src) => src.fmt(f), + Self::Path(src) => src.fmt(f), + Self::Git(src) => src.fmt(f), + Self::Workspace(src) => src.fmt(f), + } + } +} + +impl<'s> From<&'s Source> for Source { + fn from(inner: &'s Source) -> Self { + inner.clone() + } +} + +impl From for Source { + fn from(inner: RegistrySource) -> Self { + Self::Registry(inner) + } +} + +impl From for Source { + fn from(inner: PathSource) -> Self { + Self::Path(inner) + } +} + +impl From for Source { + fn from(inner: GitSource) -> Self { + Self::Git(inner) + } +} + +impl From for Source { + fn from(inner: WorkspaceSource) -> Self { + Self::Workspace(inner) + } +} + +/// Dependency from a registry +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct RegistrySource { + /// Version requirement + pub version: String, +} + +impl RegistrySource { + /// Specify dependency by version requirement + pub fn new(version: impl AsRef) -> Self { + // versions might have semver metadata appended which we do not want to + // store in the cargo toml files. This would cause a warning upon compilation + // ("version requirement […] includes semver metadata which will be ignored") + let version = version.as_ref().split('+').next().unwrap(); + Self { + version: version.to_owned(), + } + } +} + +impl std::fmt::Display for RegistrySource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.version.fmt(f) + } +} + +/// Dependency from a local path +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct PathSource { + /// Local, absolute path + pub path: PathBuf, + /// Version requirement for when published + pub version: Option, +} + +impl PathSource { + /// Specify dependency from a path + pub fn new(path: impl Into) -> Self { + Self { + path: path.into(), + version: None, + } + } + + /// Set an optional version requirement + pub fn set_version(mut self, version: impl AsRef) -> Self { + // versions might have semver metadata appended which we do not want to + // store in the cargo toml files. This would cause a warning upon compilation + // ("version requirement […] includes semver metadata which will be ignored") + let version = version.as_ref().split('+').next().unwrap(); + self.version = Some(version.to_owned()); + self + } + + /// Get the SourceID for this dependency + pub fn source_id(&self) -> CargoResult { + SourceId::for_path(&self.path) + } +} + +impl std::fmt::Display for PathSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.path.display().fmt(f) + } +} + +/// Dependency from a git repo +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct GitSource { + /// Repo URL + pub git: String, + /// Select specific branch + pub branch: Option, + /// Select specific tag + pub tag: Option, + /// Select specific rev + pub rev: Option, + /// Version requirement for when published + pub version: Option, +} + +impl GitSource { + /// Specify dependency from a git repo + pub fn new(git: impl Into) -> Self { + Self { + git: git.into(), + branch: None, + tag: None, + rev: None, + version: None, + } + } + + /// Specify an optional branch + pub fn set_branch(mut self, branch: impl Into) -> Self { + self.branch = Some(branch.into()); + self.tag = None; + self.rev = None; + self + } + + /// Specify an optional tag + pub fn set_tag(mut self, tag: impl Into) -> Self { + self.branch = None; + self.tag = Some(tag.into()); + self.rev = None; + self + } + + /// Specify an optional rev + pub fn set_rev(mut self, rev: impl Into) -> Self { + self.branch = None; + self.tag = None; + self.rev = Some(rev.into()); + self + } + + /// Get the SourceID for this dependency + pub fn source_id(&self) -> CargoResult { + let git_url = self.git.parse::()?; + let git_ref = self.git_ref(); + SourceId::for_git(&git_url, git_ref) + } + + fn git_ref(&self) -> GitReference { + match ( + self.branch.as_deref(), + self.tag.as_deref(), + self.rev.as_deref(), + ) { + (Some(branch), _, _) => GitReference::Branch(branch.to_owned()), + (_, Some(tag), _) => GitReference::Tag(tag.to_owned()), + (_, _, Some(rev)) => GitReference::Rev(rev.to_owned()), + _ => GitReference::DefaultBranch, + } + } + + /// Set an optional version requirement + pub fn set_version(mut self, version: impl AsRef) -> Self { + // versions might have semver metadata appended which we do not want to + // store in the cargo toml files. This would cause a warning upon compilation + // ("version requirement […] includes semver metadata which will be ignored") + let version = version.as_ref().split('+').next().unwrap(); + self.version = Some(version.to_owned()); + self + } +} + +impl std::fmt::Display for GitSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let git_ref = self.git_ref(); + if let Some(pretty_ref) = git_ref.pretty_ref() { + write!(f, "{}?{}", self.git, pretty_ref) + } else { + write!(f, "{}", self.git) + } + } +} + +/// Dependency from a workspace +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct WorkspaceSource; + +impl WorkspaceSource { + pub fn new() -> Self { + Self + } +} + +impl Display for WorkspaceSource { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + "workspace".fmt(f) + } +} + +#[cfg(test)] +mod tests { + use std::path::Path; + + use crate::ops::cargo_add::manifest::LocalManifest; + use cargo_util::paths; + + use super::*; + + #[test] + fn to_toml_simple_dep() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep").set_source(RegistrySource::new("1.0")); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_simple_dep_with_version() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep").set_source(RegistrySource::new("1.0")); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert_eq!(item.as_str(), Some("1.0")); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_optional_dep() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep") + .set_source(RegistrySource::new("1.0")) + .set_optional(true); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("optional").unwrap().as_bool(), Some(true)); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_dep_without_default_features() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep") + .set_source(RegistrySource::new("1.0")) + .set_default_features(false); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("default-features").unwrap().as_bool(), Some(false)); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_dep_with_path_source() { + let root = paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let crate_root = root.join("foo"); + let dep = Dependency::new("dep").set_source(PathSource::new(root.join("bar"))); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("path").unwrap().as_str(), Some("../bar")); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_dep_with_git_source() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep").set_source(GitSource::new("https://foor/bar.git")); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!( + dep.get("git").unwrap().as_str(), + Some("https://foor/bar.git") + ); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_renamed_dep() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep") + .set_source(RegistrySource::new("1.0")) + .set_rename("d"); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "d".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("package").unwrap().as_str(), Some("dep")); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_dep_from_alt_registry() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep") + .set_source(RegistrySource::new("1.0")) + .set_registry("alternative"); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "dep".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("registry").unwrap().as_str(), Some("alternative")); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn to_toml_complex_dep() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let dep = Dependency::new("dep") + .set_source(RegistrySource::new("1.0")) + .set_default_features(false) + .set_rename("d"); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + assert_eq!(key, "d".to_owned()); + assert!(item.is_inline_table()); + + let dep = item.as_inline_table().unwrap(); + assert_eq!(dep.get("package").unwrap().as_str(), Some("dep")); + assert_eq!(dep.get("version").unwrap().as_str(), Some("1.0")); + assert_eq!(dep.get("default-features").unwrap().as_bool(), Some(false)); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn paths_with_forward_slashes_are_left_as_is() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let path = crate_root.join("sibling/crate"); + let relpath = "sibling/crate"; + let dep = Dependency::new("dep").set_source(PathSource::new(path)); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + let table = item.as_inline_table().unwrap(); + let got = table.get("path").unwrap().as_str().unwrap(); + assert_eq!(got, relpath); + + verify_roundtrip(&crate_root, key, &item); + } + + #[test] + fn overwrite_with_workspace_source_fmt_key() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("./"))); + let toml = "dep = \"1.0\"\n"; + let manifest = toml.parse().unwrap(); + let mut local = LocalManifest { + path: crate_root.clone(), + manifest, + }; + assert_eq!(local.manifest.to_string(), toml); + for (key, item) in local.data.clone().iter() { + let dep = Dependency::from_toml(&crate_root, key, item).unwrap(); + let dep = dep.set_source(WorkspaceSource::new()); + local.insert_into_table(&vec![], &dep).unwrap(); + assert_eq!(local.data.to_string(), "dep.workspace = true\n"); + } + } + + #[test] + #[cfg(windows)] + fn normalise_windows_style_paths() { + let crate_root = + paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new("/"))); + let original = crate_root.join(r"sibling\crate"); + let should_be = "sibling/crate"; + let dep = Dependency::new("dep").set_source(PathSource::new(original)); + let key = dep.toml_key(); + let item = dep.to_toml(&crate_root); + + let table = item.as_inline_table().unwrap(); + let got = table.get("path").unwrap().as_str().unwrap(); + assert_eq!(got, should_be); + + verify_roundtrip(&crate_root, key, &item); + } + + #[track_caller] + fn verify_roundtrip(crate_root: &Path, key: &str, item: &toml_edit::Item) { + let roundtrip = Dependency::from_toml(crate_root, key, item).unwrap(); + let round_key = roundtrip.toml_key(); + let round_item = roundtrip.to_toml(crate_root); + assert_eq!(key, round_key); + assert_eq!(item.to_string(), round_item.to_string()); + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/manifest.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/manifest.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/manifest.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/manifest.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,516 @@ +use std::ops::{Deref, DerefMut}; +use std::path::{Path, PathBuf}; +use std::str; + +use anyhow::Context as _; + +use super::dependency::Dependency; +use crate::core::dependency::DepKind; +use crate::core::FeatureValue; +use crate::util::interning::InternedString; +use crate::CargoResult; + +/// Dependency table to add dep to +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DepTable { + kind: DepKind, + target: Option, +} + +impl DepTable { + const KINDS: &'static [Self] = &[ + Self::new().set_kind(DepKind::Normal), + Self::new().set_kind(DepKind::Development), + Self::new().set_kind(DepKind::Build), + ]; + + /// Reference to a Dependency Table + pub const fn new() -> Self { + Self { + kind: DepKind::Normal, + target: None, + } + } + + /// Choose the type of dependency + pub const fn set_kind(mut self, kind: DepKind) -> Self { + self.kind = kind; + self + } + + /// Choose the platform for the dependency + pub fn set_target(mut self, target: impl Into) -> Self { + self.target = Some(target.into()); + self + } + + /// Type of dependency + pub fn kind(&self) -> DepKind { + self.kind + } + + /// Platform for the dependency + pub fn target(&self) -> Option<&str> { + self.target.as_deref() + } + + /// Keys to the table + pub fn to_table(&self) -> Vec<&str> { + if let Some(target) = &self.target { + vec!["target", target, self.kind_table()] + } else { + vec![self.kind_table()] + } + } + + fn kind_table(&self) -> &str { + match self.kind { + DepKind::Normal => "dependencies", + DepKind::Development => "dev-dependencies", + DepKind::Build => "build-dependencies", + } + } +} + +impl Default for DepTable { + fn default() -> Self { + Self::new() + } +} + +impl From for DepTable { + fn from(other: DepKind) -> Self { + Self::new().set_kind(other) + } +} + +/// A Cargo manifest +#[derive(Debug, Clone)] +pub struct Manifest { + /// Manifest contents as TOML data + pub data: toml_edit::Document, +} + +impl Manifest { + /// Get the manifest's package name + pub fn package_name(&self) -> CargoResult<&str> { + self.data + .as_table() + .get("package") + .and_then(|m| m.get("name")) + .and_then(|m| m.as_str()) + .ok_or_else(parse_manifest_err) + } + + /// Get the specified table from the manifest. + pub fn get_table<'a>(&'a self, table_path: &[String]) -> CargoResult<&'a toml_edit::Item> { + /// Descend into a manifest until the required table is found. + fn descend<'a>( + input: &'a toml_edit::Item, + path: &[String], + ) -> CargoResult<&'a toml_edit::Item> { + if let Some(segment) = path.get(0) { + let value = input + .get(&segment) + .ok_or_else(|| non_existent_table_err(segment))?; + + if value.is_table_like() { + descend(value, &path[1..]) + } else { + Err(non_existent_table_err(segment)) + } + } else { + Ok(input) + } + } + + descend(self.data.as_item(), table_path) + } + + /// Get the specified table from the manifest. + pub fn get_table_mut<'a>( + &'a mut self, + table_path: &[String], + ) -> CargoResult<&'a mut toml_edit::Item> { + /// Descend into a manifest until the required table is found. + fn descend<'a>( + input: &'a mut toml_edit::Item, + path: &[String], + ) -> CargoResult<&'a mut toml_edit::Item> { + if let Some(segment) = path.get(0) { + let mut default_table = toml_edit::Table::new(); + default_table.set_implicit(true); + let value = input[&segment].or_insert(toml_edit::Item::Table(default_table)); + + if value.is_table_like() { + descend(value, &path[1..]) + } else { + Err(non_existent_table_err(segment)) + } + } else { + Ok(input) + } + } + + descend(self.data.as_item_mut(), table_path) + } + + /// Get all sections in the manifest that exist and might contain dependencies. + /// The returned items are always `Table` or `InlineTable`. + pub fn get_sections(&self) -> Vec<(DepTable, toml_edit::Item)> { + let mut sections = Vec::new(); + + for table in DepTable::KINDS { + let dependency_type = table.kind_table(); + // Dependencies can be in the three standard sections... + if self + .data + .get(dependency_type) + .map(|t| t.is_table_like()) + .unwrap_or(false) + { + sections.push((table.clone(), self.data[dependency_type].clone())) + } + + // ... and in `target..(build-/dev-)dependencies`. + let target_sections = self + .data + .as_table() + .get("target") + .and_then(toml_edit::Item::as_table_like) + .into_iter() + .flat_map(toml_edit::TableLike::iter) + .filter_map(|(target_name, target_table)| { + let dependency_table = target_table.get(dependency_type)?; + dependency_table.as_table_like().map(|_| { + ( + table.clone().set_target(target_name), + dependency_table.clone(), + ) + }) + }); + + sections.extend(target_sections); + } + + sections + } + + pub fn get_legacy_sections(&self) -> Vec { + let mut result = Vec::new(); + + for dependency_type in ["dev_dependencies", "build_dependencies"] { + if self.data.contains_key(dependency_type) { + result.push(dependency_type.to_owned()); + } + + // ... and in `target..(build-/dev-)dependencies`. + result.extend( + self.data + .as_table() + .get("target") + .and_then(toml_edit::Item::as_table_like) + .into_iter() + .flat_map(toml_edit::TableLike::iter) + .filter_map(|(target_name, target_table)| { + if target_table.as_table_like()?.contains_key(dependency_type) { + Some(format!("target.{target_name}.{dependency_type}")) + } else { + None + } + }), + ); + } + result + } +} + +impl str::FromStr for Manifest { + type Err = anyhow::Error; + + /// Read manifest data from string + fn from_str(input: &str) -> ::std::result::Result { + let d: toml_edit::Document = input.parse().context("Manifest not valid TOML")?; + + Ok(Manifest { data: d }) + } +} + +impl std::fmt::Display for Manifest { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.data.fmt(f) + } +} + +/// A Cargo manifest that is available locally. +#[derive(Debug)] +pub struct LocalManifest { + /// Path to the manifest + pub path: PathBuf, + /// Manifest contents + pub manifest: Manifest, +} + +impl Deref for LocalManifest { + type Target = Manifest; + + fn deref(&self) -> &Manifest { + &self.manifest + } +} + +impl DerefMut for LocalManifest { + fn deref_mut(&mut self) -> &mut Manifest { + &mut self.manifest + } +} + +impl LocalManifest { + /// Construct the `LocalManifest` corresponding to the `Path` provided. + pub fn try_new(path: &Path) -> CargoResult { + if !path.is_absolute() { + anyhow::bail!("can only edit absolute paths, got {}", path.display()); + } + let data = cargo_util::paths::read(&path)?; + let manifest = data.parse().context("Unable to parse Cargo.toml")?; + Ok(LocalManifest { + manifest, + path: path.to_owned(), + }) + } + + /// Write changes back to the file + pub fn write(&self) -> CargoResult<()> { + if !self.manifest.data.contains_key("package") + && !self.manifest.data.contains_key("project") + { + if self.manifest.data.contains_key("workspace") { + anyhow::bail!( + "found virtual manifest at {}, but this command requires running against an \ + actual package in this workspace.", + self.path.display() + ); + } else { + anyhow::bail!( + "missing expected `package` or `project` fields in {}", + self.path.display() + ); + } + } + + let s = self.manifest.data.to_string(); + let new_contents_bytes = s.as_bytes(); + + cargo_util::paths::write(&self.path, new_contents_bytes) + } + + /// Lookup a dependency + pub fn get_dependency_versions<'s>( + &'s self, + dep_key: &'s str, + ) -> impl Iterator)> + 's { + let crate_root = self.path.parent().expect("manifest path is absolute"); + self.get_sections() + .into_iter() + .filter_map(move |(table_path, table)| { + let table = table.into_table().ok()?; + Some( + table + .into_iter() + .filter_map(|(key, item)| { + if key.as_str() == dep_key { + Some((table_path.clone(), key, item)) + } else { + None + } + }) + .collect::>(), + ) + }) + .flatten() + .map(move |(table_path, dep_key, dep_item)| { + let dep = Dependency::from_toml(crate_root, &dep_key, &dep_item); + (table_path, dep) + }) + } + + /// Add entry to a Cargo.toml. + pub fn insert_into_table( + &mut self, + table_path: &[String], + dep: &Dependency, + ) -> CargoResult<()> { + let crate_root = self + .path + .parent() + .expect("manifest path is absolute") + .to_owned(); + let dep_key = dep.toml_key(); + + let table = self.get_table_mut(table_path)?; + if let Some((mut dep_key, dep_item)) = table + .as_table_like_mut() + .unwrap() + .get_key_value_mut(dep_key) + { + dep.update_toml(&crate_root, &mut dep_key, dep_item); + } else { + let new_dependency = dep.to_toml(&crate_root); + table[dep_key] = new_dependency; + } + if let Some(t) = table.as_inline_table_mut() { + t.fmt() + } + + Ok(()) + } + + /// Remove references to `dep_key` if its no longer present + pub fn gc_dep(&mut self, dep_key: &str) { + let explicit_dep_activation = self.is_explicit_dep_activation(dep_key); + let status = self.dep_status(dep_key); + + if let Some(toml_edit::Item::Table(feature_table)) = + self.data.as_table_mut().get_mut("features") + { + for (_feature, mut feature_values) in feature_table.iter_mut() { + if let toml_edit::Item::Value(toml_edit::Value::Array(feature_values)) = + &mut feature_values + { + fix_feature_activations( + feature_values, + dep_key, + status, + explicit_dep_activation, + ); + } + } + } + } + + fn is_explicit_dep_activation(&self, dep_key: &str) -> bool { + if let Some(toml_edit::Item::Table(feature_table)) = self.data.as_table().get("features") { + for values in feature_table + .iter() + .map(|(_, a)| a) + .filter_map(|i| i.as_value()) + .filter_map(|v| v.as_array()) + { + for value in values.iter().filter_map(|v| v.as_str()) { + let value = FeatureValue::new(InternedString::new(value)); + if let FeatureValue::Dep { dep_name } = &value { + if dep_name.as_str() == dep_key { + return true; + } + } + } + } + } + + false + } + + fn dep_status(&self, dep_key: &str) -> DependencyStatus { + let mut status = DependencyStatus::None; + for (_, tbl) in self.get_sections() { + if let toml_edit::Item::Table(tbl) = tbl { + if let Some(dep_item) = tbl.get(dep_key) { + let optional = dep_item + .get("optional") + .and_then(|i| i.as_value()) + .and_then(|i| i.as_bool()) + .unwrap_or(false); + if optional { + return DependencyStatus::Optional; + } else { + status = DependencyStatus::Required; + } + } + } + } + status + } +} + +impl std::fmt::Display for LocalManifest { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.manifest.fmt(f) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +enum DependencyStatus { + None, + Optional, + Required, +} + +fn fix_feature_activations( + feature_values: &mut toml_edit::Array, + dep_key: &str, + status: DependencyStatus, + explicit_dep_activation: bool, +) { + let remove_list: Vec = feature_values + .iter() + .enumerate() + .filter_map(|(idx, value)| value.as_str().map(|s| (idx, s))) + .filter_map(|(idx, value)| { + let parsed_value = FeatureValue::new(InternedString::new(value)); + match status { + DependencyStatus::None => match (parsed_value, explicit_dep_activation) { + (FeatureValue::Feature(dep_name), false) + | (FeatureValue::Dep { dep_name }, _) + | (FeatureValue::DepFeature { dep_name, .. }, _) => dep_name == dep_key, + _ => false, + }, + DependencyStatus::Optional => false, + DependencyStatus::Required => match (parsed_value, explicit_dep_activation) { + (FeatureValue::Feature(dep_name), false) + | (FeatureValue::Dep { dep_name }, _) => dep_name == dep_key, + (FeatureValue::Feature(_), true) | (FeatureValue::DepFeature { .. }, _) => { + false + } + }, + } + .then(|| idx) + }) + .collect(); + + // Remove found idx in revers order so we don't invalidate the idx. + for idx in remove_list.iter().rev() { + feature_values.remove(*idx); + } + + if status == DependencyStatus::Required { + for value in feature_values.iter_mut() { + let parsed_value = if let Some(value) = value.as_str() { + FeatureValue::new(InternedString::new(value)) + } else { + continue; + }; + if let FeatureValue::DepFeature { + dep_name, + dep_feature, + weak, + } = parsed_value + { + if dep_name == dep_key && weak { + *value = format!("{dep_name}/{dep_feature}").into(); + } + } + } + } +} + +pub fn str_or_1_len_table(item: &toml_edit::Item) -> bool { + item.is_str() || item.as_table_like().map(|t| t.len() == 1).unwrap_or(false) +} + +fn parse_manifest_err() -> anyhow::Error { + anyhow::format_err!("unable to parse external Cargo.toml") +} + +fn non_existent_table_err(table: impl std::fmt::Display) -> anyhow::Error { + anyhow::format_err!("the table `{table}` could not be found.") +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_add/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_add/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,886 @@ +//! Core of cargo-add command + +mod crate_spec; +mod dependency; +mod manifest; + +use std::collections::BTreeMap; +use std::collections::BTreeSet; +use std::collections::VecDeque; +use std::path::Path; + +use anyhow::Context as _; +use cargo_util::paths; +use indexmap::IndexSet; +use termcolor::Color::Green; +use termcolor::Color::Red; +use termcolor::ColorSpec; +use toml_edit::Item as TomlItem; + +use crate::core::dependency::DepKind; +use crate::core::registry::PackageRegistry; +use crate::core::FeatureValue; +use crate::core::Package; +use crate::core::QueryKind; +use crate::core::Registry; +use crate::core::Shell; +use crate::core::Summary; +use crate::core::Workspace; +use crate::CargoResult; +use crate::Config; +use crate_spec::CrateSpec; +use dependency::Dependency; +use dependency::GitSource; +use dependency::PathSource; +use dependency::RegistrySource; +use dependency::Source; +use manifest::LocalManifest; + +use crate::ops::cargo_add::dependency::{MaybeWorkspace, WorkspaceSource}; +pub use manifest::DepTable; + +/// Information on what dependencies should be added +#[derive(Clone, Debug)] +pub struct AddOptions<'a> { + /// Configuration information for cargo operations + pub config: &'a Config, + /// Package to add dependencies to + pub spec: &'a Package, + /// Dependencies to add or modify + pub dependencies: Vec, + /// Which dependency section to add these to + pub section: DepTable, + /// Act as if dependencies will be added + pub dry_run: bool, +} + +/// Add dependencies to a manifest +pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<()> { + let dep_table = options + .section + .to_table() + .into_iter() + .map(String::from) + .collect::>(); + + let manifest_path = options.spec.manifest_path().to_path_buf(); + let mut manifest = LocalManifest::try_new(&manifest_path)?; + let original_raw_manifest = manifest.to_string(); + let legacy = manifest.get_legacy_sections(); + if !legacy.is_empty() { + anyhow::bail!( + "Deprecated dependency sections are unsupported: {}", + legacy.join(", ") + ); + } + + let mut registry = PackageRegistry::new(options.config)?; + + let deps = { + let _lock = options.config.acquire_package_cache_lock()?; + registry.lock_patches(); + options + .dependencies + .iter() + .map(|raw| { + resolve_dependency( + &manifest, + raw, + workspace, + &options.section, + options.config, + &mut registry, + ) + }) + .collect::>>()? + }; + + let was_sorted = manifest + .get_table(&dep_table) + .map(TomlItem::as_table) + .map_or(true, |table_option| { + table_option.map_or(true, |table| is_sorted(table.iter().map(|(name, _)| name))) + }); + for dep in deps { + print_msg(&mut options.config.shell(), &dep, &dep_table)?; + if let Some(Source::Path(src)) = dep.source() { + if src.path == manifest.path.parent().unwrap_or_else(|| Path::new("")) { + anyhow::bail!( + "cannot add `{}` as a dependency to itself", + manifest.package_name()? + ) + } + } + + let available_features = dep + .available_features + .keys() + .map(|s| s.as_ref()) + .collect::>(); + let mut unknown_features: Vec<&str> = Vec::new(); + if let Some(req_feats) = dep.features.as_ref() { + let req_feats: BTreeSet<_> = req_feats.iter().map(|s| s.as_str()).collect(); + unknown_features.extend(req_feats.difference(&available_features).copied()); + } + if let Some(inherited_features) = dep.inherited_features.as_ref() { + let inherited_features: BTreeSet<_> = + inherited_features.iter().map(|s| s.as_str()).collect(); + unknown_features.extend(inherited_features.difference(&available_features).copied()); + } + unknown_features.sort(); + if !unknown_features.is_empty() { + anyhow::bail!("unrecognized features: {unknown_features:?}"); + } + + manifest.insert_into_table(&dep_table, &dep)?; + manifest.gc_dep(dep.toml_key()); + } + + if was_sorted { + if let Some(table) = manifest + .get_table_mut(&dep_table) + .ok() + .and_then(TomlItem::as_table_like_mut) + { + table.sort_values(); + } + } + + if options.config.locked() { + let new_raw_manifest = manifest.to_string(); + if original_raw_manifest != new_raw_manifest { + anyhow::bail!( + "the manifest file {} needs to be updated but --locked was passed to prevent this", + manifest.path.display() + ); + } + } + + if options.dry_run { + options.config.shell().warn("aborting add due to dry run")?; + } else { + manifest.write()?; + } + + Ok(()) +} + +/// Dependency entry operation +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DepOp { + /// Describes the crate + pub crate_spec: Option, + /// Dependency key, overriding the package name in crate_spec + pub rename: Option, + + /// Feature flags to activate + pub features: Option>, + /// Whether the default feature should be activated + pub default_features: Option, + + /// Whether dependency is optional + pub optional: Option, + + /// Registry for looking up dependency version + pub registry: Option, + + /// Git repo for dependency + pub path: Option, + /// Git repo for dependency + pub git: Option, + /// Specify an alternative git branch + pub branch: Option, + /// Specify a specific git rev + pub rev: Option, + /// Specify a specific git tag + pub tag: Option, +} + +fn resolve_dependency( + manifest: &LocalManifest, + arg: &DepOp, + ws: &Workspace<'_>, + section: &DepTable, + config: &Config, + registry: &mut PackageRegistry<'_>, +) -> CargoResult { + let crate_spec = arg + .crate_spec + .as_deref() + .map(CrateSpec::resolve) + .transpose()?; + let mut selected_dep = if let Some(url) = &arg.git { + let mut src = GitSource::new(url); + if let Some(branch) = &arg.branch { + src = src.set_branch(branch); + } + if let Some(tag) = &arg.tag { + src = src.set_tag(tag); + } + if let Some(rev) = &arg.rev { + src = src.set_rev(rev); + } + + let selected = if let Some(crate_spec) = &crate_spec { + if let Some(v) = crate_spec.version_req() { + // crate specifier includes a version (e.g. `docopt@0.8`) + anyhow::bail!("cannot specify a git URL (`{url}`) with a version (`{v}`)."); + } + let dependency = crate_spec.to_dependency()?.set_source(src); + let selected = select_package(&dependency, config, registry)?; + if dependency.name != selected.name { + config.shell().warn(format!( + "translating `{}` to `{}`", + dependency.name, selected.name, + ))?; + } + selected + } else { + let mut source = crate::sources::GitSource::new(src.source_id()?, config)?; + let packages = source.read_packages()?; + let package = infer_package(packages, &src)?; + Dependency::from(package.summary()) + }; + selected + } else if let Some(raw_path) = &arg.path { + let path = paths::normalize_path(&std::env::current_dir()?.join(raw_path)); + let src = PathSource::new(&path); + + let selected = if let Some(crate_spec) = &crate_spec { + if let Some(v) = crate_spec.version_req() { + // crate specifier includes a version (e.g. `docopt@0.8`) + anyhow::bail!("cannot specify a path (`{raw_path}`) with a version (`{v}`)."); + } + let dependency = crate_spec.to_dependency()?.set_source(src); + let selected = select_package(&dependency, config, registry)?; + if dependency.name != selected.name { + config.shell().warn(format!( + "translating `{}` to `{}`", + dependency.name, selected.name, + ))?; + } + selected + } else { + let source = crate::sources::PathSource::new(&path, src.source_id()?, config); + let packages = source.read_packages()?; + let package = infer_package(packages, &src)?; + Dependency::from(package.summary()) + }; + selected + } else if let Some(crate_spec) = &crate_spec { + crate_spec.to_dependency()? + } else { + anyhow::bail!("dependency name is required"); + }; + selected_dep = populate_dependency(selected_dep, arg); + + let old_dep = get_existing_dependency(manifest, selected_dep.toml_key(), section)?; + let mut dependency = if let Some(mut old_dep) = old_dep.clone() { + if old_dep.name != selected_dep.name { + // Assuming most existing keys are not relevant when the package changes + if selected_dep.optional.is_none() { + selected_dep.optional = old_dep.optional; + } + selected_dep + } else { + if selected_dep.source().is_some() { + // Overwrite with `crate_spec` + old_dep.source = selected_dep.source; + } + populate_dependency(old_dep, arg) + } + } else { + selected_dep + }; + + if dependency.source().is_none() { + // Checking for a workspace dependency happens first since a member could be specified + // in the workspace dependencies table as a dependency + if let Some(_dep) = find_workspace_dep(dependency.toml_key(), ws.root_manifest()).ok() { + dependency = dependency.set_source(WorkspaceSource::new()); + } else if let Some(package) = ws.members().find(|p| p.name().as_str() == dependency.name) { + // Only special-case workspaces when the user doesn't provide any extra + // information, otherwise, trust the user. + let mut src = PathSource::new(package.root()); + // dev-dependencies do not need the version populated + if section.kind() != DepKind::Development { + let op = ""; + let v = format!("{op}{version}", version = package.version()); + src = src.set_version(v); + } + dependency = dependency.set_source(src); + } else { + let latest = get_latest_dependency(&dependency, false, config, registry)?; + + if dependency.name != latest.name { + config.shell().warn(format!( + "translating `{}` to `{}`", + dependency.name, latest.name, + ))?; + dependency.name = latest.name; // Normalize the name + } + dependency = dependency.set_source(latest.source.expect("latest always has a source")); + } + } + + if let Some(Source::Workspace(_)) = dependency.source() { + check_invalid_ws_keys(dependency.toml_key(), arg)?; + } + + let version_required = dependency.source().and_then(|s| s.as_registry()).is_some(); + let version_optional_in_section = section.kind() == DepKind::Development; + let preserve_existing_version = old_dep + .as_ref() + .map(|d| d.version().is_some()) + .unwrap_or(false); + if !version_required && !preserve_existing_version && version_optional_in_section { + // dev-dependencies do not need the version populated + dependency = dependency.clear_version(); + } + + let query = dependency.query(config)?; + let query = match query { + MaybeWorkspace::Workspace(_workspace) => { + let dep = find_workspace_dep(dependency.toml_key(), ws.root_manifest())?; + if let Some(features) = dep.features.clone() { + dependency = dependency.set_inherited_features(features); + } + let query = dep.query(config)?; + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("This should have been caught when parsing a workspace root") + } + MaybeWorkspace::Other(query) => query, + } + } + MaybeWorkspace::Other(query) => query, + }; + + let dependency = populate_available_features(dependency, &query, registry)?; + + Ok(dependency) +} + +/// When { workspace = true } you cannot define other keys that configure +/// the source of the dependency such as `version`, `registry`, `registry-index`, +/// `path`, `git`, `branch`, `tag`, `rev`, or `package`. You can also not define +/// `default-features`. +/// +/// Only `default-features`, `registry` and `rename` need to be checked +/// for currently. This is because `git` and its associated keys, `path`, and +/// `version` should all bee checked before this is called. `rename` is checked +/// for as it turns into `package` +fn check_invalid_ws_keys(toml_key: &str, arg: &DepOp) -> CargoResult<()> { + fn err_msg(toml_key: &str, flag: &str, field: &str) -> String { + format!( + "cannot override workspace dependency with `{flag}`, \ + either change `workspace.dependencies.{toml_key}.{field}` \ + or define the dependency exclusively in the package's manifest" + ) + } + + if arg.default_features.is_some() { + anyhow::bail!( + "{}", + err_msg(toml_key, "--default-features", "default-features") + ) + } + if arg.registry.is_some() { + anyhow::bail!("{}", err_msg(toml_key, "--registry", "registry")) + } + // rename is `package` + if arg.rename.is_some() { + anyhow::bail!("{}", err_msg(toml_key, "--rename", "package")) + } + Ok(()) +} + +/// Provide the existing dependency for the target table +/// +/// If it doesn't exist but exists in another table, let's use that as most likely users +/// want to use the same version across all tables unless they are renaming. +fn get_existing_dependency( + manifest: &LocalManifest, + dep_key: &str, + section: &DepTable, +) -> CargoResult> { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] + enum Key { + Error, + Dev, + Build, + Normal, + Existing, + } + + let mut possible: Vec<_> = manifest + .get_dependency_versions(dep_key) + .map(|(path, dep)| { + let key = if path == *section { + (Key::Existing, true) + } else if dep.is_err() { + (Key::Error, path.target().is_some()) + } else { + let key = match path.kind() { + DepKind::Normal => Key::Normal, + DepKind::Build => Key::Build, + DepKind::Development => Key::Dev, + }; + (key, path.target().is_some()) + }; + (key, dep) + }) + .collect(); + possible.sort_by_key(|(key, _)| *key); + let (key, dep) = if let Some(item) = possible.pop() { + item + } else { + return Ok(None); + }; + let mut dep = dep?; + + if key.0 != Key::Existing { + // When the dep comes from a different section, we only care about the source and not any + // of the other fields, like `features` + let unrelated = dep; + dep = Dependency::new(&unrelated.name); + dep.source = unrelated.source.clone(); + dep.registry = unrelated.registry.clone(); + + // dev-dependencies do not need the version populated when path is set though we + // should preserve it if the user chose to populate it. + let version_required = unrelated.source().and_then(|s| s.as_registry()).is_some(); + let version_optional_in_section = section.kind() == DepKind::Development; + if !version_required && version_optional_in_section { + dep = dep.clear_version(); + } + } + + Ok(Some(dep)) +} + +fn get_latest_dependency( + dependency: &Dependency, + _flag_allow_prerelease: bool, + config: &Config, + registry: &mut PackageRegistry<'_>, +) -> CargoResult { + let query = dependency.query(config)?; + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("registry dependencies required, found a workspace dependency"); + } + MaybeWorkspace::Other(query) => { + let possibilities = loop { + match registry.query_vec(&query, QueryKind::Fuzzy) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + }; + let latest = possibilities + .iter() + .max_by_key(|s| { + // Fallback to a pre-release if no official release is available by sorting them as + // less. + let stable = s.version().pre.is_empty(); + (stable, s.version()) + }) + .ok_or_else(|| { + anyhow::format_err!( + "the crate `{dependency}` could not be found in registry index." + ) + })?; + let mut dep = Dependency::from(latest); + if let Some(reg_name) = dependency.registry.as_deref() { + dep = dep.set_registry(reg_name); + } + Ok(dep) + } + } +} + +fn select_package( + dependency: &Dependency, + config: &Config, + registry: &mut PackageRegistry<'_>, +) -> CargoResult { + let query = dependency.query(config)?; + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("path or git dependency expected, found workspace dependency"); + } + MaybeWorkspace::Other(query) => { + let possibilities = loop { + // Exact to avoid returning all for path/git + match registry.query_vec(&query, QueryKind::Exact) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + }; + match possibilities.len() { + 0 => { + let source = dependency + .source() + .expect("source should be resolved before here"); + anyhow::bail!("the crate `{dependency}` could not be found at `{source}`") + } + 1 => { + let mut dep = Dependency::from(&possibilities[0]); + if let Some(reg_name) = dependency.registry.as_deref() { + dep = dep.set_registry(reg_name); + } + Ok(dep) + } + _ => { + let source = dependency + .source() + .expect("source should be resolved before here"); + anyhow::bail!( + "unexpectedly found multiple copies of crate `{dependency}` at `{source}`" + ) + } + } + } + } +} + +fn infer_package(mut packages: Vec, src: &dyn std::fmt::Display) -> CargoResult { + let package = match packages.len() { + 0 => { + anyhow::bail!("no packages found at `{src}`"); + } + 1 => packages.pop().expect("match ensured element is present"), + _ => { + let mut names: Vec<_> = packages + .iter() + .map(|p| p.name().as_str().to_owned()) + .collect(); + names.sort_unstable(); + anyhow::bail!("multiple packages found at `{src}`: {}", names.join(", ")); + } + }; + Ok(package) +} + +fn populate_dependency(mut dependency: Dependency, arg: &DepOp) -> Dependency { + if let Some(registry) = &arg.registry { + if registry.is_empty() { + dependency.registry = None; + } else { + dependency.registry = Some(registry.to_owned()); + } + } + if let Some(value) = arg.optional { + if value { + dependency.optional = Some(true); + } else { + dependency.optional = None; + } + } + if let Some(value) = arg.default_features { + if value { + dependency.default_features = None; + } else { + dependency.default_features = Some(false); + } + } + if let Some(value) = arg.features.as_ref() { + dependency = dependency.extend_features(value.iter().cloned()); + } + + if let Some(rename) = &arg.rename { + dependency = dependency.set_rename(rename); + } + + dependency +} + +/// Track presentation-layer information with the editable representation of a `[dependencies]` +/// entry (Dependency) +pub struct DependencyUI { + /// Editable representation of a `[depednencies]` entry + dep: Dependency, + /// The version of the crate that we pulled `available_features` from + available_version: Option, + /// The widest set of features compatible with `Dependency`s version requirement + available_features: BTreeMap>, +} + +impl DependencyUI { + fn new(dep: Dependency) -> Self { + Self { + dep, + available_version: None, + available_features: Default::default(), + } + } + + fn apply_summary(&mut self, summary: &Summary) { + self.available_version = Some(summary.version().clone()); + self.available_features = summary + .features() + .iter() + .map(|(k, v)| { + ( + k.as_str().to_owned(), + v.iter() + .filter_map(|v| match v { + FeatureValue::Feature(f) => Some(f.as_str().to_owned()), + FeatureValue::Dep { .. } | FeatureValue::DepFeature { .. } => None, + }) + .collect::>(), + ) + }) + .collect(); + } +} + +impl<'s> From<&'s Summary> for DependencyUI { + fn from(other: &'s Summary) -> Self { + let dep = Dependency::from(other); + let mut dep = Self::new(dep); + dep.apply_summary(other); + dep + } +} + +impl std::fmt::Display for DependencyUI { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.dep.fmt(f) + } +} + +impl std::ops::Deref for DependencyUI { + type Target = Dependency; + + fn deref(&self) -> &Self::Target { + &self.dep + } +} + +/// Lookup available features +fn populate_available_features( + dependency: Dependency, + query: &crate::core::dependency::Dependency, + registry: &mut PackageRegistry<'_>, +) -> CargoResult { + let mut dependency = DependencyUI::new(dependency); + + if !dependency.available_features.is_empty() { + return Ok(dependency); + } + + let possibilities = loop { + match registry.query_vec(&query, QueryKind::Fuzzy) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + }; + // Ensure widest feature flag compatibility by picking the earliest version that could show up + // in the lock file for a given version requirement. + let lowest_common_denominator = possibilities + .iter() + .min_by_key(|s| { + // Fallback to a pre-release if no official release is available by sorting them as + // more. + let is_pre = !s.version().pre.is_empty(); + (is_pre, s.version()) + }) + .ok_or_else(|| { + anyhow::format_err!("the crate `{dependency}` could not be found in registry index.") + })?; + dependency.apply_summary(&lowest_common_denominator); + + Ok(dependency) +} + +fn print_msg(shell: &mut Shell, dep: &DependencyUI, section: &[String]) -> CargoResult<()> { + use std::fmt::Write; + + if matches!(shell.verbosity(), crate::core::shell::Verbosity::Quiet) { + return Ok(()); + } + + let mut message = String::new(); + write!(message, "{}", dep.name)?; + match dep.source() { + Some(Source::Registry(src)) => { + if src.version.chars().next().unwrap_or('0').is_ascii_digit() { + write!(message, " v{}", src.version)?; + } else { + write!(message, " {}", src.version)?; + } + } + Some(Source::Path(_)) => { + write!(message, " (local)")?; + } + Some(Source::Git(_)) => { + write!(message, " (git)")?; + } + Some(Source::Workspace(_)) => { + write!(message, " (workspace)")?; + } + None => {} + } + write!(message, " to")?; + if dep.optional().unwrap_or(false) { + write!(message, " optional")?; + } + let section = if section.len() == 1 { + section[0].clone() + } else { + format!("{} for target `{}`", §ion[2], §ion[1]) + }; + write!(message, " {section}")?; + write!(message, ".")?; + shell.status("Adding", message)?; + + let mut activated: IndexSet<_> = dep.features.iter().flatten().map(|s| s.as_str()).collect(); + if dep.default_features().unwrap_or(true) { + activated.insert("default"); + } + activated.extend(dep.inherited_features.iter().flatten().map(|s| s.as_str())); + let mut walk: VecDeque<_> = activated.iter().cloned().collect(); + while let Some(next) = walk.pop_front() { + walk.extend( + dep.available_features + .get(next) + .into_iter() + .flatten() + .map(|s| s.as_str()), + ); + activated.extend( + dep.available_features + .get(next) + .into_iter() + .flatten() + .map(|s| s.as_str()), + ); + } + activated.remove("default"); + activated.sort(); + let mut deactivated = dep + .available_features + .keys() + .filter(|f| !activated.contains(f.as_str()) && *f != "default") + .collect::>(); + deactivated.sort(); + if !activated.is_empty() || !deactivated.is_empty() { + let prefix = format!("{:>13}", " "); + let suffix = if let Some(version) = &dep.available_version { + let mut version = version.clone(); + version.build = Default::default(); + let version = version.to_string(); + // Avoid displaying the version if it will visually look like the version req that we + // showed earlier + let version_req = dep + .version() + .and_then(|v| semver::VersionReq::parse(v).ok()) + .and_then(|v| precise_version(&v)); + if version_req.as_deref() != Some(version.as_str()) { + format!(" as of v{version}") + } else { + "".to_owned() + } + } else { + "".to_owned() + }; + shell.write_stderr( + format_args!("{}Features{}:\n", prefix, suffix), + &ColorSpec::new(), + )?; + for feat in activated { + shell.write_stderr(&prefix, &ColorSpec::new())?; + shell.write_stderr('+', &ColorSpec::new().set_bold(true).set_fg(Some(Green)))?; + shell.write_stderr(format_args!(" {}\n", feat), &ColorSpec::new())?; + } + for feat in deactivated { + shell.write_stderr(&prefix, &ColorSpec::new())?; + shell.write_stderr('-', &ColorSpec::new().set_bold(true).set_fg(Some(Red)))?; + shell.write_stderr(format_args!(" {}\n", feat), &ColorSpec::new())?; + } + } + + Ok(()) +} + +// Based on Iterator::is_sorted from nightly std; remove in favor of that when stabilized. +fn is_sorted(mut it: impl Iterator) -> bool { + let mut last = match it.next() { + Some(e) => e, + None => return true, + }; + + for curr in it { + if curr < last { + return false; + } + last = curr; + } + + true +} + +fn find_workspace_dep(toml_key: &str, root_manifest: &Path) -> CargoResult { + let manifest = LocalManifest::try_new(root_manifest)?; + let manifest = manifest + .data + .as_item() + .as_table_like() + .context("could not make `manifest.data` into a table")?; + let workspace = manifest + .get("workspace") + .context("could not find `workspace`")? + .as_table_like() + .context("could not make `manifest.data.workspace` into a table")?; + let dependencies = workspace + .get("dependencies") + .context("could not find `dependencies` table in `workspace`")? + .as_table_like() + .context("could not make `dependencies` into a table")?; + let dep_item = dependencies.get(toml_key).context(format!( + "could not find {} in `workspace.dependencies`", + toml_key + ))?; + Dependency::from_toml(root_manifest.parent().unwrap(), toml_key, dep_item) +} + +/// Convert a `semver::VersionReq` into a rendered `semver::Version` if all fields are fully +/// specified. +fn precise_version(version_req: &semver::VersionReq) -> Option { + version_req + .comparators + .iter() + .filter(|c| { + matches!( + c.op, + // Only ops we can determine a precise version from + semver::Op::Exact + | semver::Op::GreaterEq + | semver::Op::LessEq + | semver::Op::Tilde + | semver::Op::Caret + | semver::Op::Wildcard + ) + }) + .filter_map(|c| { + // Only do it when full precision is specified + c.minor.and_then(|minor| { + c.patch.map(|patch| semver::Version { + major: c.major, + minor, + patch, + pre: c.pre.clone(), + build: Default::default(), + }) + }) + }) + .max() + .map(|v| v.to_string()) +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_clean.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_clean.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_clean.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_clean.rs 2022-10-20 06:00:42.000000000 +0000 @@ -5,7 +5,7 @@ use crate::util::errors::CargoResult; use crate::util::interning::InternedString; use crate::util::lev_distance; -use crate::util::Config; +use crate::util::{Config, Progress, ProgressStyle}; use anyhow::Context as _; use cargo_util::paths; @@ -34,7 +34,7 @@ // If the doc option is set, we just want to delete the doc directory. if opts.doc { target_dir = target_dir.join("doc"); - return rm_rf(&target_dir.into_path_unlocked(), config); + return clean_entire_folder(&target_dir.into_path_unlocked(), config); } let profiles = Profiles::new(ws, opts.requested_profile)?; @@ -53,7 +53,7 @@ // Note that we don't bother grabbing a lock here as we're just going to // blow it all away anyway. if opts.spec.is_empty() { - return rm_rf(&target_dir.into_path_unlocked(), config); + return clean_entire_folder(&target_dir.into_path_unlocked(), config); } // Clean specific packages. @@ -133,13 +133,15 @@ } let packages = pkg_set.get_many(pkg_ids)?; + let mut progress = CleaningPackagesBar::new(config, packages.len()); for pkg in packages { let pkg_dir = format!("{}-*", pkg.name()); + progress.on_cleaning_package(&pkg.name())?; // Clean fingerprints. for (_, layout) in &layouts_with_host { let dir = escape_glob_path(layout.fingerprint())?; - rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config)?; + rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config, &mut progress)?; } for target in pkg.targets() { @@ -147,7 +149,7 @@ // Get both the build_script_build and the output directory. for (_, layout) in &layouts_with_host { let dir = escape_glob_path(layout.build())?; - rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config)?; + rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config, &mut progress)?; } continue; } @@ -178,33 +180,33 @@ let dir_glob = escape_glob_path(dir)?; let dir_glob = Path::new(&dir_glob); - rm_rf_glob(&dir_glob.join(&hashed_name), config)?; - rm_rf(&dir.join(&unhashed_name), config)?; + rm_rf_glob(&dir_glob.join(&hashed_name), config, &mut progress)?; + rm_rf(&dir.join(&unhashed_name), config, &mut progress)?; // Remove dep-info file generated by rustc. It is not tracked in // file_types. It does not have a prefix. let hashed_dep_info = dir_glob.join(format!("{}-*.d", crate_name)); - rm_rf_glob(&hashed_dep_info, config)?; + rm_rf_glob(&hashed_dep_info, config, &mut progress)?; let unhashed_dep_info = dir.join(format!("{}.d", crate_name)); - rm_rf(&unhashed_dep_info, config)?; + rm_rf(&unhashed_dep_info, config, &mut progress)?; // Remove split-debuginfo files generated by rustc. let split_debuginfo_obj = dir_glob.join(format!("{}.*.o", crate_name)); - rm_rf_glob(&split_debuginfo_obj, config)?; + rm_rf_glob(&split_debuginfo_obj, config, &mut progress)?; let split_debuginfo_dwo = dir_glob.join(format!("{}.*.dwo", crate_name)); - rm_rf_glob(&split_debuginfo_dwo, config)?; + rm_rf_glob(&split_debuginfo_dwo, config, &mut progress)?; // Remove the uplifted copy. if let Some(uplift_dir) = uplift_dir { let uplifted_path = uplift_dir.join(file_type.uplift_filename(target)); - rm_rf(&uplifted_path, config)?; + rm_rf(&uplifted_path, config, &mut progress)?; // Dep-info generated by Cargo itself. let dep_info = uplifted_path.with_extension("d"); - rm_rf(&dep_info, config)?; + rm_rf(&dep_info, config, &mut progress)?; } } // TODO: what to do about build_script_build? let dir = escape_glob_path(layout.incremental())?; let incremental = Path::new(&dir).join(format!("{}-*", crate_name)); - rm_rf_glob(&incremental, config)?; + rm_rf_glob(&incremental, config, &mut progress)?; } } } @@ -220,29 +222,134 @@ Ok(glob::Pattern::escape(pattern)) } -fn rm_rf_glob(pattern: &Path, config: &Config) -> CargoResult<()> { +fn rm_rf_glob( + pattern: &Path, + config: &Config, + progress: &mut dyn CleaningProgressBar, +) -> CargoResult<()> { // TODO: Display utf8 warning to user? Or switch to globset? let pattern = pattern .to_str() .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?; for path in glob::glob(pattern)? { - rm_rf(&path?, config)?; + rm_rf(&path?, config, progress)?; } Ok(()) } -fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> { - let m = fs::symlink_metadata(path); - if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) { - config - .shell() - .verbose(|shell| shell.status("Removing", path.display()))?; - paths::remove_dir_all(path).with_context(|| "could not remove build directory")?; - } else if m.is_ok() { - config - .shell() - .verbose(|shell| shell.status("Removing", path.display()))?; - paths::remove_file(path).with_context(|| "failed to remove build artifact")?; +fn rm_rf(path: &Path, config: &Config, progress: &mut dyn CleaningProgressBar) -> CargoResult<()> { + if fs::symlink_metadata(path).is_err() { + return Ok(()); } + + config + .shell() + .verbose(|shell| shell.status("Removing", path.display()))?; + progress.display_now()?; + + for entry in walkdir::WalkDir::new(path).contents_first(true) { + let entry = entry?; + progress.on_clean()?; + if entry.file_type().is_dir() { + paths::remove_dir(entry.path()).with_context(|| "could not remove build directory")?; + } else { + paths::remove_file(entry.path()).with_context(|| "failed to remove build artifact")?; + } + } + Ok(()) } + +fn clean_entire_folder(path: &Path, config: &Config) -> CargoResult<()> { + let num_paths = walkdir::WalkDir::new(path).into_iter().count(); + let mut progress = CleaningFolderBar::new(config, num_paths); + rm_rf(path, config, &mut progress) +} + +trait CleaningProgressBar { + fn display_now(&mut self) -> CargoResult<()>; + fn on_clean(&mut self) -> CargoResult<()>; +} + +struct CleaningFolderBar<'cfg> { + bar: Progress<'cfg>, + max: usize, + cur: usize, +} + +impl<'cfg> CleaningFolderBar<'cfg> { + fn new(cfg: &'cfg Config, max: usize) -> Self { + Self { + bar: Progress::with_style("Cleaning", ProgressStyle::Percentage, cfg), + max, + cur: 0, + } + } + + fn cur_progress(&self) -> usize { + std::cmp::min(self.cur, self.max) + } +} + +impl<'cfg> CleaningProgressBar for CleaningFolderBar<'cfg> { + fn display_now(&mut self) -> CargoResult<()> { + self.bar.tick_now(self.cur_progress(), self.max, "") + } + + fn on_clean(&mut self) -> CargoResult<()> { + self.cur += 1; + self.bar.tick(self.cur_progress(), self.max, "") + } +} + +struct CleaningPackagesBar<'cfg> { + bar: Progress<'cfg>, + max: usize, + cur: usize, + num_files_folders_cleaned: usize, + package_being_cleaned: String, +} + +impl<'cfg> CleaningPackagesBar<'cfg> { + fn new(cfg: &'cfg Config, max: usize) -> Self { + Self { + bar: Progress::with_style("Cleaning", ProgressStyle::Ratio, cfg), + max, + cur: 0, + num_files_folders_cleaned: 0, + package_being_cleaned: String::new(), + } + } + + fn on_cleaning_package(&mut self, package: &str) -> CargoResult<()> { + self.cur += 1; + self.package_being_cleaned = String::from(package); + self.bar + .tick(self.cur_progress(), self.max, &self.format_message()) + } + + fn cur_progress(&self) -> usize { + std::cmp::min(self.cur, self.max) + } + + fn format_message(&self) -> String { + format!( + ": {}, {} files/folders cleaned", + self.package_being_cleaned, self.num_files_folders_cleaned + ) + } +} + +impl<'cfg> CleaningProgressBar for CleaningPackagesBar<'cfg> { + fn display_now(&mut self) -> CargoResult<()> { + self.bar + .tick_now(self.cur_progress(), self.max, &self.format_message()) + } + + fn on_clean(&mut self) -> CargoResult<()> { + self.bar + .tick(self.cur_progress(), self.max, &self.format_message())?; + self.num_files_folders_cleaned += 1; + Ok(()) + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_compile.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_compile.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_compile.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_compile.rs 2022-10-20 06:00:42.000000000 +0000 @@ -23,6 +23,7 @@ //! repeats until the queue is empty. use std::collections::{BTreeSet, HashMap, HashSet}; +use std::fmt::Write; use std::hash::{Hash, Hasher}; use std::sync::Arc; @@ -174,13 +175,13 @@ }; if specs.is_empty() { if ws.is_virtual() { - anyhow::bail!( + bail!( "manifest path `{}` contains no package: The manifest is virtual, \ and the workspace has no members.", ws.root().display() ) } - anyhow::bail!("no packages to compile") + bail!("no packages to compile") } Ok(specs) } @@ -401,19 +402,8 @@ } = resolve; let std_resolve_features = if let Some(crates) = &config.cli_unstable().build_std { - if build_config.build_plan { - config - .shell() - .warn("-Zbuild-std does not currently fully support --build-plan")?; - } - if build_config.requested_kinds[0].is_host() { - // TODO: This should eventually be fixed. Unfortunately it is not - // easy to get the host triple in BuildConfig. Consider changing - // requested_target to an enum, or some other approach. - anyhow::bail!("-Zbuild-std requires --target"); - } let (std_package_set, std_resolve, std_features) = - standard_lib::resolve_std(ws, &target_data, &build_config.requested_kinds, crates)?; + standard_lib::resolve_std(ws, &target_data, &build_config, crates)?; pkg_set.add_set(std_package_set); Some((std_resolve, std_features)) } else { @@ -546,23 +536,15 @@ &profiles, interner, )? + .into_iter() + // Proc macros should not be scraped for functions, since they only export macros + .filter(|unit| !unit.target.proc_macro()) + .collect::>() } None => Vec::new(), }; - let std_roots = if let Some(crates) = &config.cli_unstable().build_std { - // Only build libtest if it looks like it is needed. - let mut crates = crates.clone(); - if !crates.iter().any(|c| c == "test") - && units - .iter() - .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) - { - // Only build libtest when libstd is built (libtest depends on libstd) - if crates.iter().any(|c| c == "std") { - crates.push("test".to_string()); - } - } + let std_roots = if let Some(crates) = standard_lib::std_crates(config, Some(&units)) { let (std_resolve, std_features) = std_resolve_features.as_ref().unwrap(); standard_lib::generate_std_roots( &crates, @@ -642,6 +624,12 @@ if rustdoc_document_private_items || unit.target.is_bin() { let mut args = extra_args.take().unwrap_or_default(); args.push("--document-private-items".into()); + if unit.target.is_bin() { + // This warning only makes sense if it's possible to document private items + // sometimes and ignore them at other times. But cargo consistently passes + // `--document-private-items`, so the warning isn't useful. + args.push("-Arustdoc::private-intra-doc-links".into()); + } extra_args = Some(args); } @@ -674,12 +662,34 @@ continue; } + let guidance = if ws.is_ephemeral() { + if ws.ignore_lock() { + "Try re-running cargo install with `--locked`".to_string() + } else { + String::new() + } + } else if !unit.is_local() { + format!( + "Either upgrade to rustc {} or newer, or use\n\ + cargo update -p {}@{} --precise ver\n\ + where `ver` is the latest version of `{}` supporting rustc {}", + version, + unit.pkg.name(), + unit.pkg.version(), + unit.pkg.name(), + current_version, + ) + } else { + String::new() + }; + anyhow::bail!( "package `{}` cannot be built because it requires rustc {} or newer, \ - while the currently active rustc version is {}", + while the currently active rustc version is {}\n{}", unit.pkg, version, current_version, + guidance, ); } } @@ -815,7 +825,7 @@ /// Constructs a filter that includes all test targets. /// /// Being different from the behavior of [`CompileFilter::Default`], this - /// function only recongnizes test targets, which means cargo might compile + /// function only recognizes test targets, which means cargo might compile /// all targets with `tested` flag on, whereas [`CompileFilter::Default`] /// may include additional example targets to ensure they can be compiled. /// @@ -1517,19 +1527,40 @@ }; if proposals.is_empty() { - let targets = packages.iter().flat_map(|pkg| { - pkg.targets() - .iter() - .filter(|target| is_expected_kind(target)) - }); - let suggestion = closest_msg(target_name, targets, |t| t.name()); - anyhow::bail!( - "no {} target {} `{}`{}", - target_desc, - if is_glob { "matches pattern" } else { "named" }, - target_name, - suggestion - ); + let targets = packages + .iter() + .flat_map(|pkg| { + pkg.targets() + .iter() + .filter(|target| is_expected_kind(target)) + }) + .collect::>(); + let suggestion = closest_msg(target_name, targets.iter(), |t| t.name()); + if !suggestion.is_empty() { + anyhow::bail!( + "no {} target {} `{}`{}", + target_desc, + if is_glob { "matches pattern" } else { "named" }, + target_name, + suggestion + ); + } else { + let mut msg = String::new(); + writeln!( + msg, + "no {} target {} `{}`.", + target_desc, + if is_glob { "matches pattern" } else { "named" }, + target_name, + )?; + if !targets.is_empty() { + writeln!(msg, "Available {} targets:", target_desc)?; + for target in targets { + writeln!(msg, " {}", target.name())?; + } + } + anyhow::bail!(msg); + } } Ok(proposals) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_config.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_config.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_config.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_config.rs 2022-10-20 06:00:42.000000000 +0000 @@ -17,7 +17,7 @@ impl ConfigFormat { /// For clap. - pub const POSSIBLE_VALUES: &'static [&'static str] = &["toml", "json", "json-value"]; + pub const POSSIBLE_VALUES: [&'static str; 3] = ["toml", "json", "json-value"]; } impl FromStr for ConfigFormat { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_fetch.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_fetch.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_fetch.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_fetch.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,3 +1,4 @@ +use crate::core::compiler::standard_lib; use crate::core::compiler::{BuildConfig, CompileMode, RustcTargetData}; use crate::core::{PackageSet, Resolve, Workspace}; use crate::ops; @@ -17,7 +18,7 @@ options: &FetchOptions<'a>, ) -> CargoResult<(Resolve, PackageSet<'a>)> { ws.emit_warnings()?; - let (packages, resolve) = ops::resolve_ws(ws)?; + let (mut packages, resolve) = ops::resolve_ws(ws)?; let jobs = Some(1); let keep_going = false; @@ -64,6 +65,14 @@ .map(|(id, _deps)| id); deps_to_fetch.extend(deps); } + + // If -Zbuild-std was passed, download dependencies for the standard library. + // We don't know ahead of time what jobs we'll be running, so tell `std_crates` that. + if let Some(crates) = standard_lib::std_crates(config, None) { + let (std_package_set, _, _) = standard_lib::resolve_std(ws, &data, &build_config, &crates)?; + packages.add_set(std_package_set); + } + packages.get_many(to_download)?; Ok((resolve, packages)) diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_generate_lockfile.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_generate_lockfile.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_generate_lockfile.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_generate_lockfile.rs 2022-10-20 06:00:42.000000000 +0000 @@ -36,6 +36,25 @@ } pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> { + // Currently this is only a warning, but after a transition period this will become + // a hard error. + // See https://github.com/rust-lang/cargo/issues/10919#issuecomment-1214464756. + // We should declare the `precise` and `aggressive` arguments + // require the `package` argument in the clap. + if opts.aggressive && opts.to_update.is_empty() { + ws.config().shell().warn( + "aggressive is only supported with \"--package \", \ + this will become a hard error in a future release.", + )?; + } + + if opts.precise.is_some() && opts.to_update.is_empty() { + ws.config().shell().warn( + "precise is only supported with \"--package \", \ + this will become a hard error in a future release.", + )?; + } + if opts.aggressive && opts.precise.is_some() { anyhow::bail!("cannot specify both aggressive and precise simultaneously") } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_install.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_install.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_install.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_install.rs 2022-10-20 06:00:42.000000000 +0000 @@ -5,7 +5,8 @@ use crate::core::compiler::{CompileKind, DefaultExecutor, Executor, Freshness, UnitOutput}; use crate::core::{Dependency, Edition, Package, PackageId, Source, SourceId, Workspace}; -use crate::ops::common_for_install_and_uninstall::*; +use crate::ops::CompileFilter; +use crate::ops::{common_for_install_and_uninstall::*, FilterRule}; use crate::sources::{GitSource, PathSource, SourceConfigMap}; use crate::util::errors::CargoResult; use crate::util::{Config, Filesystem, Rustc, ToSemver, VersionReqExt}; @@ -272,7 +273,7 @@ Ok(duplicates) } - fn install_one(mut self) -> CargoResult<()> { + fn install_one(mut self) -> CargoResult { self.config.shell().status("Installing", &self.pkg)?; let dst = self.root.join("bin").into_path_unlocked(); @@ -322,7 +323,43 @@ }) .collect::>()?; if binaries.is_empty() { - bail!("no binaries are available for install using the selected features"); + // Cargo already warns the user if they use a target specifier that matches nothing, + // but we want to error if the user asked for a _particular_ binary to be installed, + // and we didn't end up installing it. + // + // NOTE: This _should_ be impossible to hit since --bin=does_not_exist will fail on + // target selection, and --bin=requires_a without --features=a will fail with "target + // .. requires the features ..". But rather than assume that's the case, we define the + // behavior for this fallback case as well. + if let CompileFilter::Only { bins, examples, .. } = &self.opts.filter { + let mut any_specific = false; + if let FilterRule::Just(ref v) = bins { + if !v.is_empty() { + any_specific = true; + } + } + if let FilterRule::Just(ref v) = examples { + if !v.is_empty() { + any_specific = true; + } + } + if any_specific { + bail!("no binaries are available for install using the selected features"); + } + } + + // If there _are_ binaries available, but none were selected given the current set of + // features, let the user know. + // + // Note that we know at this point that _if_ bins or examples is set to `::Just`, + // they're `::Just([])`, which is `FilterRule::none()`. + if self.pkg.targets().iter().any(|t| t.is_executable()) { + self.config + .shell() + .warn("none of the package's binaries are available for install using the selected features")?; + } + + return Ok(false); } // This is primarily to make testing easier. binaries.sort_unstable(); @@ -455,7 +492,7 @@ executables(successful_bins.iter()) ), )?; - Ok(()) + Ok(true) } else { if !to_install.is_empty() { self.config.shell().status( @@ -481,7 +518,7 @@ ), )?; } - Ok(()) + Ok(true) } } @@ -493,36 +530,21 @@ // duplicate "Updating", but since `source` is taken by value, then it // wouldn't be available for `compile_ws`. let (pkg_set, resolve) = ops::resolve_ws(&self.ws)?; - let mut sources = pkg_set.sources_mut(); - - // Checking the yanked status involves taking a look at the registry and - // maybe updating files, so be sure to lock it here. - let _lock = self.ws.config().acquire_package_cache_lock()?; - - for pkg_id in resolve.iter() { - if let Some(source) = sources.get_mut(pkg_id.source_id()) { - if source.is_yanked(pkg_id)? { - self.ws.config().shell().warn(format!( - "package `{}` in Cargo.lock is yanked in registry `{}`, \ - consider running without --locked", - pkg_id, - pkg_id.source_id().display_registry_name() - ))?; - } - } - } - - Ok(()) + ops::check_yanked( + self.ws.config(), + &pkg_set, + &resolve, + "consider running without --locked", + ) } } pub fn install( config: &Config, root: Option<&str>, - krates: Vec<&str>, + krates: Vec<(&str, Option<&str>)>, source_id: SourceId, from_cwd: bool, - vers: Option<&str>, opts: &ops::CompileOptions, force: bool, no_track: bool, @@ -532,23 +554,19 @@ let map = SourceConfigMap::new(config)?; let (installed_anything, scheduled_error) = if krates.len() <= 1 { + let (krate, vers) = krates + .into_iter() + .next() + .map(|(k, v)| (Some(k), v)) + .unwrap_or((None, None)); let installable_pkg = InstallablePackage::new( - config, - root, - map, - krates.into_iter().next(), - source_id, - from_cwd, - vers, - opts, - force, - no_track, - true, + config, root, map, krate, source_id, from_cwd, vers, opts, force, no_track, true, )?; + let mut installed_anything = true; if let Some(installable_pkg) = installable_pkg { - installable_pkg.install_one()?; + installed_anything = installable_pkg.install_one()?; } - (true, false) + (installed_anything, false) } else { let mut succeeded = vec![]; let mut failed = vec![]; @@ -558,7 +576,7 @@ let pkgs_to_install: Vec<_> = krates .into_iter() - .filter_map(|krate| { + .filter_map(|(krate, vers)| { let root = root.clone(); let map = map.clone(); match InstallablePackage::new( @@ -601,8 +619,10 @@ for (krate, result) in install_results { match result { - Ok(()) => { - succeeded.push(krate); + Ok(installed) => { + if installed { + succeeded.push(krate); + } } Err(e) => { crate::display_error(&e, &mut config.shell()); @@ -731,14 +751,14 @@ let first = v .chars() .next() - .ok_or_else(|| format_err!("no version provided for the `--vers` flag"))?; + .ok_or_else(|| format_err!("no version provided for the `--version` flag"))?; let is_req = "<>=^~".contains(first) || v.contains('*'); if is_req { match v.parse::() { Ok(v) => Ok(v), Err(_) => bail!( - "the `--vers` provided, `{}`, is \ + "the `--version` provided, `{}`, is \ not a valid semver version requirement\n\n\ Please have a look at \ https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html \ @@ -751,7 +771,7 @@ Ok(v) => Ok(VersionReq::exact(&v)), Err(e) => { let mut msg = format!( - "the `--vers` provided, `{}`, is \ + "the `--version` provided, `{}`, is \ not a valid semver version: {}\n", v, e ); diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_new.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_new.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_new.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_new.rs 2022-10-20 06:00:42.000000000 +0000 @@ -10,8 +10,7 @@ use std::fmt; use std::io::{BufRead, BufReader, ErrorKind}; use std::path::{Path, PathBuf}; -use std::process::Command; -use std::str::{from_utf8, FromStr}; +use std::str::FromStr; use toml_edit::easy as toml; #[derive(Clone, Copy, Debug, PartialEq)] @@ -254,8 +253,7 @@ if restricted_names::is_non_ascii_name(name) { shell.warn(format!( "the name `{}` contains non-ASCII characters\n\ - Support for non-ASCII crate names is experimental and only valid \ - on the nightly toolchain.", + Non-ASCII crate names are not supported by Rust.", name ))?; } @@ -809,11 +807,17 @@ " } else { b"\ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + #[cfg(test)] mod tests { + use super::*; + #[test] fn it_works() { - let result = 2 + 2; + let result = add(2, 2); assert_eq!(result, 4); } } @@ -824,14 +828,12 @@ paths::write(&path_of_source_file, default_file_content)?; // Format the newly created source file - match Command::new("rustfmt").arg(&path_of_source_file).output() { - Err(e) => log::warn!("failed to call rustfmt: {}", e), - Ok(output) => { - if !output.status.success() { - log::warn!("rustfmt failed: {:?}", from_utf8(&output.stdout)); - } - } - }; + if let Err(e) = cargo_util::ProcessBuilder::new("rustfmt") + .arg(&path_of_source_file) + .exec_with_output() + { + log::warn!("failed to call rustfmt: {:#}", e); + } } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_package.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_package.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_package.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_package.rs 2022-10-20 06:00:42.000000000 +0000 @@ -5,6 +5,7 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::Arc; +use std::task::Poll; use crate::core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor}; use crate::core::resolver::CliFeatures; @@ -29,13 +30,14 @@ pub check_metadata: bool, pub allow_dirty: bool, pub verify: bool, - pub jobs: Option, + pub jobs: Option, pub keep_going: bool, pub to_package: ops::Packages, pub targets: Vec, pub cli_features: CliFeatures, } +const ORIGINAL_MANIFEST_FILE: &str = "Cargo.toml.orig"; const VCS_INFO_FILE: &str = ".cargo_vcs_info.json"; struct ArchiveFile { @@ -219,8 +221,8 @@ match rel_str.as_ref() { "Cargo.toml" => { result.push(ArchiveFile { - rel_path: PathBuf::from("Cargo.toml.orig"), - rel_str: "Cargo.toml.orig".to_string(), + rel_path: PathBuf::from(ORIGINAL_MANIFEST_FILE), + rel_str: ORIGINAL_MANIFEST_FILE.to_string(), contents: FileContents::OnDisk(src_file), }); result.push(ArchiveFile { @@ -230,10 +232,9 @@ }); } "Cargo.lock" => continue, - VCS_INFO_FILE => anyhow::bail!( - "invalid inclusion of reserved file name \ - {} in package source", - VCS_INFO_FILE + VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow::bail!( + "invalid inclusion of reserved file name {} in package source", + rel_str ), _ => { result.push(ArchiveFile { @@ -260,46 +261,16 @@ } if let Some(license_file) = &pkg.manifest().metadata().license_file { let license_path = Path::new(license_file); - let abs_license_path = paths::normalize_path(&pkg.root().join(license_path)); - if abs_license_path.exists() { - match abs_license_path.strip_prefix(&pkg.root()) { - Ok(rel_license_path) => { - if !result.iter().any(|ar| ar.rel_path == rel_license_path) { - result.push(ArchiveFile { - rel_path: rel_license_path.to_path_buf(), - rel_str: rel_license_path - .to_str() - .expect("everything was utf8") - .to_string(), - contents: FileContents::OnDisk(abs_license_path), - }); - } - } - Err(_) => { - // The license exists somewhere outside of the package. - let license_name = license_path.file_name().unwrap(); - if result - .iter() - .any(|ar| ar.rel_path.file_name().unwrap() == license_name) - { - ws.config().shell().warn(&format!( - "license-file `{}` appears to be a path outside of the package, \ - but there is already a file named `{}` in the root of the package. \ - The archived crate will contain the copy in the root of the package. \ - Update the license-file to point to the path relative \ - to the root of the package to remove this warning.", - license_file, - license_name.to_str().unwrap() - ))?; - } else { - result.push(ArchiveFile { - rel_path: PathBuf::from(license_name), - rel_str: license_name.to_str().unwrap().to_string(), - contents: FileContents::OnDisk(abs_license_path), - }); - } - } - } + let abs_file_path = paths::normalize_path(&pkg.root().join(license_path)); + if abs_file_path.exists() { + check_for_file_and_add( + "license-file", + license_path, + abs_file_path, + pkg, + &mut result, + ws, + )?; } else { let rel_msg = if license_path.is_absolute() { "".to_string() @@ -316,11 +287,69 @@ ))?; } } + if let Some(readme) = &pkg.manifest().metadata().readme { + let readme_path = Path::new(readme); + let abs_file_path = paths::normalize_path(&pkg.root().join(readme_path)); + if abs_file_path.exists() { + check_for_file_and_add("readme", readme_path, abs_file_path, pkg, &mut result, ws)?; + } + } result.sort_unstable_by(|a, b| a.rel_path.cmp(&b.rel_path)); Ok(result) } +fn check_for_file_and_add( + label: &str, + file_path: &Path, + abs_file_path: PathBuf, + pkg: &Package, + result: &mut Vec, + ws: &Workspace<'_>, +) -> CargoResult<()> { + match abs_file_path.strip_prefix(&pkg.root()) { + Ok(rel_file_path) => { + if !result.iter().any(|ar| ar.rel_path == rel_file_path) { + result.push(ArchiveFile { + rel_path: rel_file_path.to_path_buf(), + rel_str: rel_file_path + .to_str() + .expect("everything was utf8") + .to_string(), + contents: FileContents::OnDisk(abs_file_path), + }) + } + } + Err(_) => { + // The file exists somewhere outside of the package. + let file_name = file_path.file_name().unwrap(); + if result + .iter() + .any(|ar| ar.rel_path.file_name().unwrap() == file_name) + { + ws.config().shell().warn(&format!( + "{} `{}` appears to be a path outside of the package, \ + but there is already a file named `{}` in the root of the package. \ + The archived crate will contain the copy in the root of the package. \ + Update the {} to point to the path relative \ + to the root of the package to remove this warning.", + label, + file_path.display(), + file_name.to_str().unwrap(), + label, + ))?; + } else { + result.push(ArchiveFile { + rel_path: PathBuf::from(file_name), + rel_str: file_name.to_str().unwrap().to_string(), + contents: FileContents::OnDisk(abs_file_path), + }) + } + } + } + Ok(()) +} + /// Construct `Cargo.lock` for the package to be published. fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult { let config = ws.config(); @@ -346,7 +375,12 @@ if let Some(orig_resolve) = orig_resolve { compare_resolve(config, tmp_ws.current()?, &orig_resolve, &new_resolve)?; } - check_yanked(config, &pkg_set, &new_resolve)?; + check_yanked( + config, + &pkg_set, + &new_resolve, + "consider updating to a version that is not yanked", + )?; ops::resolve_to_string(&tmp_ws, &mut new_resolve) } @@ -688,22 +722,45 @@ Ok(()) } -fn check_yanked(config: &Config, pkg_set: &PackageSet<'_>, resolve: &Resolve) -> CargoResult<()> { +pub fn check_yanked( + config: &Config, + pkg_set: &PackageSet<'_>, + resolve: &Resolve, + hint: &str, +) -> CargoResult<()> { // Checking the yanked status involves taking a look at the registry and // maybe updating files, so be sure to lock it here. let _lock = config.acquire_package_cache_lock()?; let mut sources = pkg_set.sources_mut(); - for pkg_id in resolve.iter() { - if let Some(source) = sources.get_mut(pkg_id.source_id()) { - if source.is_yanked(pkg_id)? { - config.shell().warn(format!( - "package `{}` in Cargo.lock is yanked in registry `{}`, \ - consider updating to a version that is not yanked", - pkg_id, - pkg_id.source_id().display_registry_name() - ))?; + let mut pending: Vec = resolve.iter().collect(); + let mut results = Vec::new(); + for (_id, source) in sources.sources_mut() { + source.invalidate_cache(); + } + while !pending.is_empty() { + pending.retain(|pkg_id| { + if let Some(source) = sources.get_mut(pkg_id.source_id()) { + match source.is_yanked(*pkg_id) { + Poll::Ready(result) => results.push((*pkg_id, result)), + Poll::Pending => return true, + } } + false + }); + for (_id, source) in sources.sources_mut() { + source.block_until_ready()?; + } + } + + for (pkg_id, is_yanked) in results { + if is_yanked? { + config.shell().warn(format!( + "package `{}` in Cargo.lock is yanked in registry `{}`, {}", + pkg_id, + pkg_id.source_id().display_registry_name(), + hint + ))?; } } Ok(()) diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_read_manifest.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_read_manifest.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_read_manifest.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_read_manifest.rs 2022-10-20 06:00:42.000000000 +0000 @@ -183,11 +183,16 @@ v.insert(pkg); } Entry::Occupied(_) => { - info!( - "skipping nested package `{}` found at `{}`", - pkg.name(), - path.to_string_lossy() - ); + // We can assume a package with publish = false isn't intended to be seen + // by users so we can hide the warning about those since the user is unlikely + // to care about those cases. + if pkg.publish().is_none() { + let _ = config.shell().warn(format!( + "skipping duplicate package `{}` found at `{}`", + pkg.name(), + path.display() + )); + } } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_test.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_test.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/cargo_test.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/cargo_test.rs 2022-10-20 06:00:42.000000000 +0000 @@ -3,9 +3,11 @@ use crate::core::{TargetKind, Workspace}; use crate::ops; use crate::util::errors::CargoResult; -use crate::util::{add_path_args, CargoTestError, Config, Test}; +use crate::util::{add_path_args, CliError, CliResult, Config}; +use anyhow::format_err; use cargo_util::{ProcessBuilder, ProcessError}; use std::ffi::OsString; +use std::fmt::Write; use std::path::{Path, PathBuf}; pub struct TestOptions { @@ -14,55 +16,87 @@ pub no_fail_fast: bool, } -pub fn run_tests( - ws: &Workspace<'_>, - options: &TestOptions, - test_args: &[&str], -) -> CargoResult> { - let compilation = compile_tests(ws, options)?; +/// The kind of test. +/// +/// This is needed because `Unit` does not track whether or not something is a +/// benchmark. +#[derive(Copy, Clone)] +enum TestKind { + Test, + Bench, + Doctest, +} - if options.no_run { - display_no_run_information(ws, test_args, &compilation, "unittests")?; - return Ok(None); - } - let (test, mut errors) = run_unit_tests(ws.config(), options, test_args, &compilation)?; +/// A unit that failed to run. +struct UnitTestError { + unit: Unit, + kind: TestKind, +} - // 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))); +impl UnitTestError { + /// Returns the CLI args needed to target this unit. + fn cli_args(&self, ws: &Workspace<'_>, opts: &ops::CompileOptions) -> String { + let mut args = if opts.spec.needs_spec_flag(ws) { + format!("-p {} ", self.unit.pkg.name()) + } else { + String::new() + }; + let mut add = |which| write!(args, "--{which} {}", self.unit.target.name()).unwrap(); + + match self.kind { + TestKind::Test | TestKind::Bench => match self.unit.target.kind() { + TargetKind::Lib(_) => args.push_str("--lib"), + TargetKind::Bin => add("bin"), + TargetKind::Test => add("test"), + TargetKind::Bench => add("bench"), + TargetKind::ExampleLib(_) | TargetKind::ExampleBin => add("example"), + TargetKind::CustomBuild => panic!("unexpected CustomBuild kind"), + }, + TestKind::Doctest => args.push_str("--doc"), + } + args } +} - let (doctest, docerrors) = run_doc_tests(ws, options, test_args, &compilation)?; - let test = if docerrors.is_empty() { test } else { doctest }; - errors.extend(docerrors); - if errors.is_empty() { - Ok(None) - } else { - Ok(Some(CargoTestError::new(test, errors))) +/// Compiles and runs tests. +/// +/// On error, the returned [`CliError`] will have the appropriate process exit +/// code that Cargo should use. +pub fn run_tests(ws: &Workspace<'_>, options: &TestOptions, test_args: &[&str]) -> CliResult { + let compilation = compile_tests(ws, options)?; + + if options.no_run { + if !options.compile_opts.build_config.emit_json() { + display_no_run_information(ws, test_args, &compilation, "unittests")?; + } + return Ok(()); } + let mut errors = run_unit_tests(ws, options, test_args, &compilation, TestKind::Test)?; + + let doctest_errors = run_doc_tests(ws, options, test_args, &compilation)?; + errors.extend(doctest_errors); + no_fail_fast_err(ws, &options.compile_opts, &errors) } -pub fn run_benches( - ws: &Workspace<'_>, - options: &TestOptions, - args: &[&str], -) -> CargoResult> { +/// Compiles and runs benchmarks. +/// +/// On error, the returned [`CliError`] will have the appropriate process exit +/// code that Cargo should use. +pub fn run_benches(ws: &Workspace<'_>, options: &TestOptions, args: &[&str]) -> CliResult { let compilation = compile_tests(ws, options)?; if options.no_run { - display_no_run_information(ws, args, &compilation, "benches")?; - return Ok(None); + if !options.compile_opts.build_config.emit_json() { + display_no_run_information(ws, args, &compilation, "benches")?; + } + return Ok(()); } let mut args = args.to_vec(); args.push("--bench"); - let (test, errors) = run_unit_tests(ws.config(), options, &args, &compilation)?; - - match errors.len() { - 0 => Ok(None), - _ => Ok(Some(CargoTestError::new(test, errors))), - } + let errors = run_unit_tests(ws, options, &args, &compilation, TestKind::Bench)?; + no_fail_fast_err(ws, &options.compile_opts, &errors) } fn compile_tests<'a>(ws: &Workspace<'a>, options: &TestOptions) -> CargoResult> { @@ -72,12 +106,17 @@ } /// Runs the unit and integration tests of a package. +/// +/// Returns a `Vec` of tests that failed when `--no-fail-fast` is used. +/// If `--no-fail-fast` is *not* used, then this returns an `Err`. fn run_unit_tests( - config: &Config, + ws: &Workspace<'_>, options: &TestOptions, test_args: &[&str], compilation: &Compilation<'_>, -) -> CargoResult<(Test, Vec)> { + test_kind: TestKind, +) -> Result, CliError> { + let config = ws.config(); let cwd = config.cwd(); let mut errors = Vec::new(); @@ -104,46 +143,32 @@ .shell() .verbose(|shell| shell.status("Running", &cmd))?; - let result = cmd.exec(); - - if let Err(e) = result { - let e = e.downcast::()?; - errors.push(( - unit.target.kind().clone(), - unit.target.name().to_string(), - unit.pkg.name().to_string(), - e, - )); + if let Err(e) = cmd.exec() { + let code = fail_fast_code(&e); + let unit_err = UnitTestError { + unit: unit.clone(), + kind: test_kind, + }; + report_test_error(ws, &options.compile_opts, &unit_err, e); + errors.push(unit_err); if !options.no_fail_fast { - break; + return Err(CliError::code(code)); } } } - - if errors.len() == 1 { - let (kind, name, pkg_name, e) = errors.pop().unwrap(); - Ok(( - Test::UnitTest { - kind, - name, - pkg_name, - }, - vec![e], - )) - } else { - Ok(( - Test::Multiple, - errors.into_iter().map(|(_, _, _, e)| e).collect(), - )) - } + Ok(errors) } +/// Runs doc tests. +/// +/// Returns a `Vec` of tests that failed when `--no-fail-fast` is used. +/// If `--no-fail-fast` is *not* used, then this returns an `Err`. fn run_doc_tests( ws: &Workspace<'_>, options: &TestOptions, test_args: &[&str], compilation: &Compilation<'_>, -) -> CargoResult<(Test, Vec)> { +) -> Result, CliError> { let config = ws.config(); let mut errors = Vec::new(); let doctest_xcompile = config.cli_unstable().doctest_xcompile; @@ -200,11 +225,12 @@ p.arg(unit.target.src_path().path().unwrap()); } + if let CompileKind::Target(target) = unit.kind { + // use `rustc_target()` to properly handle JSON target paths + p.arg("--target").arg(target.rustc_target()); + } + if doctest_xcompile { - if let CompileKind::Target(target) = unit.kind { - // use `rustc_target()` to properly handle JSON target paths - p.arg("--target").arg(target.rustc_target()); - } p.arg("-Zunstable-options"); p.arg("--enable-per-target-ignores"); if let Some((runtool, runtool_args)) = compilation.target_runner(unit.kind) { @@ -251,16 +277,24 @@ .shell() .verbose(|shell| shell.status("Running", p.to_string()))?; if let Err(e) = p.exec() { - let e = e.downcast::()?; - errors.push(e); + let code = fail_fast_code(&e); + let unit_err = UnitTestError { + unit: unit.clone(), + kind: TestKind::Doctest, + }; + report_test_error(ws, &options.compile_opts, &unit_err, e); + errors.push(unit_err); if !options.no_fail_fast { - return Ok((Test::Doc, errors)); + return Err(CliError::code(code)); } } } - Ok((Test::Doc, errors)) + Ok(errors) } +/// Displays human-readable descriptions of the test executables. +/// +/// This is used when `cargo test --no-run` is used. fn display_no_run_information( ws: &Workspace<'_>, test_args: &[&str], @@ -296,6 +330,11 @@ return Ok(()); } +/// Creates a [`ProcessBuilder`] for executing a single test. +/// +/// Returns a tuple `(exe_display, process)` where `exe_display` is a string +/// to display that describes the executable path in a human-readable form. +/// `process` is the `ProcessBuilder` to use for executing the test. fn cmd_builds( config: &Config, cwd: &Path, @@ -334,3 +373,67 @@ Ok((exe_display, cmd)) } + +/// Returns the error code to use when *not* using `--no-fail-fast`. +/// +/// Cargo will return the error code from the test process itself. If some +/// other error happened (like a failure to launch the process), then it will +/// return a standard 101 error code. +/// +/// When using `--no-fail-fast`, Cargo always uses the 101 exit code (since +/// there may not be just one process to report). +fn fail_fast_code(error: &anyhow::Error) -> i32 { + if let Some(proc_err) = error.downcast_ref::() { + if let Some(code) = proc_err.code { + return code; + } + } + 101 +} + +/// Returns the `CliError` when using `--no-fail-fast` and there is at least +/// one error. +fn no_fail_fast_err( + ws: &Workspace<'_>, + opts: &ops::CompileOptions, + errors: &[UnitTestError], +) -> CliResult { + // TODO: This could be improved by combining the flags on a single line when feasible. + let args: Vec<_> = errors + .iter() + .map(|unit_err| format!(" `{}`", unit_err.cli_args(ws, opts))) + .collect(); + let message = match errors.len() { + 0 => return Ok(()), + 1 => format!("1 target failed:\n{}", args.join("\n")), + n => format!("{n} targets failed:\n{}", args.join("\n")), + }; + Err(anyhow::Error::msg(message).into()) +} + +/// Displays an error on the console about a test failure. +fn report_test_error( + ws: &Workspace<'_>, + opts: &ops::CompileOptions, + unit_err: &UnitTestError, + test_error: anyhow::Error, +) { + let which = match unit_err.kind { + TestKind::Test => "test failed", + TestKind::Bench => "bench failed", + TestKind::Doctest => "doctest failed", + }; + + let mut err = format_err!("{}, to rerun pass `{}`", which, unit_err.cli_args(ws, opts)); + // Don't show "process didn't exit successfully" for simple errors. + // libtest exits with 101 for normal errors. + let is_simple = test_error + .downcast_ref::() + .and_then(|proc_err| proc_err.code) + .map_or(false, |code| code == 101); + if !is_simple { + err = test_error.context(err); + } + + crate::display_error(&err, &mut ws.config().shell()); +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/common_for_install_and_uninstall.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/common_for_install_and_uninstall.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/common_for_install_and_uninstall.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/common_for_install_and_uninstall.rs 2022-10-20 06:00:42.000000000 +0000 @@ -11,7 +11,7 @@ use toml_edit::easy as toml; use crate::core::compiler::Freshness; -use crate::core::{Dependency, FeatureValue, Package, PackageId, Source, SourceId}; +use crate::core::{Dependency, FeatureValue, Package, PackageId, QueryKind, Source, SourceId}; use crate::ops::{self, CompileFilter, CompileOptions}; use crate::sources::PathSource; use crate::util::errors::CargoResult; @@ -540,7 +540,7 @@ } let deps = loop { - match source.query_vec(&dep)? { + match source.query_vec(&dep, QueryKind::Exact)? { Poll::Ready(deps) => break deps, Poll::Pending => source.block_until_ready()?, } @@ -553,8 +553,20 @@ None => { let is_yanked: bool = if dep.version_req().is_exact() { let version: String = dep.version_req().to_string(); - PackageId::new(dep.package_name(), &version[1..], source.source_id()) - .map_or(false, |pkg_id| source.is_yanked(pkg_id).unwrap_or(false)) + if let Ok(pkg_id) = + PackageId::new(dep.package_name(), &version[1..], source.source_id()) + { + source.invalidate_cache(); + loop { + match source.is_yanked(pkg_id) { + Poll::Ready(Ok(is_yanked)) => break is_yanked, + Poll::Ready(Err(_)) => break false, + Poll::Pending => source.block_until_ready()?, + } + } + } else { + false + } } else { false }; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/fix.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/fix.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/fix.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/fix.rs 2022-10-20 06:00:42.000000000 +0000 @@ -39,13 +39,12 @@ //! show them to the user. use std::collections::{BTreeSet, HashMap, HashSet}; -use std::env; use std::ffi::OsString; use std::path::{Path, PathBuf}; -use std::process::{self, Command, ExitStatus}; -use std::str; +use std::process::{self, ExitStatus}; +use std::{env, fs, str}; -use anyhow::{bail, Context, Error}; +use anyhow::{bail, Context as _}; use cargo_util::{exit_status_to_string, is_simple_exit_code, paths, ProcessBuilder}; use log::{debug, trace, warn}; use rustfix::diagnostics::Diagnostic; @@ -122,6 +121,9 @@ let rustc = ws.config().load_global_rustc(Some(ws))?; wrapper.arg(&rustc.path); + // This is calling rustc in cargo fix-proxy-mode, so it also need to retry. + // The argfile handling are located at `FixArgs::from_args`. + wrapper.retry_with_argfile(true); // primary crates are compiled using a cargo subprocess to do extra work of applying fixes and // repeating build until there are no more changes to be applied @@ -331,20 +333,23 @@ Ok(()) } +/// Provide the lock address when running in proxy mode +/// +/// Returns `None` if `fix` is not being run (not in proxy mode). Returns +/// `Some(...)` if in `fix` proxy mode +pub fn fix_get_proxy_lock_addr() -> Option { + env::var(FIX_ENV).ok() +} + /// Entry point for `cargo` running as a proxy for `rustc`. /// /// This is called every time `cargo` is run to check if it is in proxy mode. /// -/// Returns `false` if `fix` is not being run (not in proxy mode). Returns -/// `true` if in `fix` proxy mode, and the fix was complete without any -/// warnings or errors. If there are warnings or errors, this does not return, +/// If there are warnings or errors, this does not return, /// and the process exits with the corresponding `rustc` exit code. -pub fn fix_maybe_exec_rustc(config: &Config) -> CargoResult { - let lock_addr = match env::var(FIX_ENV) { - Ok(s) => s, - Err(_) => return Ok(false), - }; - +/// +/// See [`fix_get_proxy_lock_addr`] +pub fn fix_exec_rustc(config: &Config, lock_addr: &str) -> CargoResult<()> { let args = FixArgs::get()?; trace!("cargo-fix as rustc got file {:?}", args.file); @@ -352,10 +357,17 @@ .map(PathBuf::from) .ok(); let mut rustc = ProcessBuilder::new(&args.rustc).wrapped(workspace_rustc.as_ref()); + rustc.retry_with_argfile(true); rustc.env_remove(FIX_ENV); + args.apply(&mut rustc); trace!("start rustfixing {:?}", args.file); - let fixes = rustfix_crate(&lock_addr, &rustc, &args.file, &args, config)?; + let json_error_rustc = { + let mut cmd = rustc.clone(); + cmd.arg("--error-format=json"); + cmd + }; + let fixes = rustfix_crate(&lock_addr, &json_error_rustc, &args.file, &args, config)?; // Ok now we have our final goal of testing out the changes that we applied. // If these changes went awry and actually started to cause the crate to @@ -366,11 +378,8 @@ // 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() { - let mut cmd = rustc.build_command(); - args.apply(&mut cmd); - cmd.arg("--error-format=json"); - debug!("calling rustc for final verification: {:?}", cmd); - let output = cmd.output().context("failed to spawn rustc")?; + debug!("calling rustc for final verification: {json_error_rustc}"); + let output = json_error_rustc.output()?; if output.status.success() { for (path, file) in fixes.files.iter() { @@ -386,7 +395,7 @@ // any. If stderr is empty then there's no need for the final exec at // the end, we just bail out here. if output.status.success() && output.stderr.is_empty() { - return Ok(true); + return Ok(()); } // Otherwise, if our rustc just failed, then that means that we broke the @@ -399,7 +408,18 @@ paths::write(path, &file.original_code)?; } } - log_failed_fix(&output.stderr, output.status)?; + + let krate = { + let mut iter = json_error_rustc.get_args(); + let mut krate = None; + while let Some(arg) = iter.next() { + if arg == "--crate-name" { + krate = iter.next().and_then(|s| s.to_owned().into_string().ok()); + } + } + krate + }; + log_failed_fix(krate, &output.stderr, output.status)?; } } @@ -407,15 +427,13 @@ // - If the fix failed, show the original warnings and suggestions. // - If `--broken-code`, show the error messages. // - If the fix succeeded, show any remaining warnings. - let mut cmd = rustc.build_command(); - args.apply(&mut cmd); for arg in args.format_args { // Add any json/error format arguments that Cargo wants. This allows // things like colored output to work correctly. - cmd.arg(arg); + rustc.arg(arg); } - debug!("calling rustc to display remaining diagnostics: {:?}", cmd); - exit_with(cmd.status().context("failed to spawn rustc")?); + debug!("calling rustc to display remaining diagnostics: {rustc}"); + exit_with(rustc.status()?); } #[derive(Default)] @@ -439,7 +457,7 @@ filename: &Path, args: &FixArgs, config: &Config, -) -> Result { +) -> CargoResult { if !args.can_run_rustfix(config)? { // This fix should not be run. Skipping... return Ok(FixedCrate::default()); @@ -502,7 +520,7 @@ // We'll generate new errors below. file.errors_applying_fixes.clear(); } - rustfix_and_fix(&mut fixes, rustc, filename, args, config)?; + rustfix_and_fix(&mut fixes, rustc, filename, config)?; let mut progress_yet_to_be_made = false; for (path, file) in fixes.files.iter_mut() { if file.errors_applying_fixes.is_empty() { @@ -543,26 +561,14 @@ fixes: &mut FixedCrate, rustc: &ProcessBuilder, filename: &Path, - args: &FixArgs, config: &Config, -) -> Result<(), Error> { +) -> CargoResult<()> { // If not empty, filter by these lints. // TODO: implement a way to specify this. let only = HashSet::new(); - let mut cmd = rustc.build_command(); - cmd.arg("--error-format=json"); - args.apply(&mut cmd); - debug!( - "calling rustc to collect suggestions and validate previous fixes: {:?}", - cmd - ); - let output = cmd.output().with_context(|| { - format!( - "failed to execute `{}`", - rustc.get_program().to_string_lossy() - ) - })?; + debug!("calling rustc to collect suggestions and validate previous fixes: {rustc}"); + let output = rustc.output()?; // If rustc didn't succeed for whatever reasons then we're very likely to be // looking at otherwise broken code. Let's not make things accidentally @@ -703,7 +709,7 @@ process::exit(status.code().unwrap_or(3)); } -fn log_failed_fix(stderr: &[u8], status: ExitStatus) -> Result<(), Error> { +fn log_failed_fix(krate: Option, stderr: &[u8], status: ExitStatus) -> CargoResult<()> { let stderr = str::from_utf8(stderr).context("failed to parse rustc stderr as utf-8")?; let diagnostics = stderr @@ -725,19 +731,6 @@ .filter(|x| !x.starts_with('{')) .map(|x| x.to_string()), ); - let mut krate = None; - let mut prev_dash_dash_krate_name = false; - for arg in env::args() { - if prev_dash_dash_krate_name { - krate = Some(arg.clone()); - } - - if arg == "--crate-name" { - prev_dash_dash_krate_name = true; - } else { - prev_dash_dash_krate_name = false; - } - } let files = files.into_iter().collect(); let abnormal_exit = if status.code().map_or(false, is_simple_exit_code) { @@ -784,36 +777,66 @@ } impl FixArgs { - fn get() -> Result { - let rustc = env::args_os() + fn get() -> CargoResult { + Self::from_args(env::args_os()) + } + + // This is a separate function so that we can use it in tests. + fn from_args(argv: impl IntoIterator) -> CargoResult { + let mut argv = argv.into_iter(); + let mut rustc = argv .nth(1) .map(PathBuf::from) - .ok_or_else(|| anyhow::anyhow!("expected rustc as first argument"))?; + .ok_or_else(|| anyhow::anyhow!("expected rustc or `@path` as first argument"))?; let mut file = None; let mut enabled_edition = None; let mut other = Vec::new(); let mut format_args = Vec::new(); - for arg in env::args_os().skip(2) { + let mut handle_arg = |arg: OsString| -> CargoResult<()> { let path = PathBuf::from(arg); if path.extension().and_then(|s| s.to_str()) == Some("rs") && path.exists() { file = Some(path); - continue; + return Ok(()); } if let Some(s) = path.to_str() { if let Some(edition) = s.strip_prefix("--edition=") { enabled_edition = Some(edition.parse()?); - continue; + return Ok(()); } if s.starts_with("--error-format=") || s.starts_with("--json=") { // Cargo may add error-format in some cases, but `cargo // fix` wants to add its own. format_args.push(s.to_string()); - continue; + return Ok(()); } } other.push(path.into()); + Ok(()) + }; + + if let Some(argfile_path) = rustc.to_str().unwrap_or_default().strip_prefix("@") { + // Because cargo in fix-proxy-mode might hit the command line size limit, + // cargo fix need handle `@path` argfile for this special case. + if argv.next().is_some() { + bail!("argfile `@path` cannot be combined with other arguments"); + } + let contents = fs::read_to_string(argfile_path) + .with_context(|| format!("failed to read argfile at `{argfile_path}`"))?; + let mut iter = contents.lines().map(OsString::from); + rustc = iter + .next() + .map(PathBuf::from) + .ok_or_else(|| anyhow::anyhow!("expected rustc as first argument"))?; + for arg in iter { + handle_arg(arg)?; + } + } else { + for arg in argv { + handle_arg(arg)?; + } } + let file = file.ok_or_else(|| anyhow::anyhow!("could not find .rs file in rustc args"))?; let idioms = env::var(IDIOMS_ENV).is_ok(); @@ -834,7 +857,7 @@ }) } - fn apply(&self, cmd: &mut Command) { + fn apply(&self, cmd: &mut ProcessBuilder) { cmd.arg(&self.file); cmd.args(&self.other); if self.prepare_for_edition.is_some() { @@ -925,3 +948,46 @@ .and(Ok(true)) } } + +#[cfg(test)] +mod tests { + use super::FixArgs; + use std::ffi::OsString; + use std::io::Write as _; + use std::path::PathBuf; + + #[test] + fn get_fix_args_from_argfile() { + let mut temp = tempfile::Builder::new().tempfile().unwrap(); + let main_rs = tempfile::Builder::new().suffix(".rs").tempfile().unwrap(); + + let content = format!("/path/to/rustc\n{}\nfoobar\n", main_rs.path().display()); + temp.write_all(content.as_bytes()).unwrap(); + + let argfile = format!("@{}", temp.path().display()); + let args = ["cargo", &argfile]; + let fix_args = FixArgs::from_args(args.map(|x| x.into())).unwrap(); + assert_eq!(fix_args.rustc, PathBuf::from("/path/to/rustc")); + assert_eq!(fix_args.file, main_rs.path()); + assert_eq!(fix_args.other, vec![OsString::from("foobar")]); + } + + #[test] + fn get_fix_args_from_argfile_with_extra_arg() { + let mut temp = tempfile::Builder::new().tempfile().unwrap(); + let main_rs = tempfile::Builder::new().suffix(".rs").tempfile().unwrap(); + + let content = format!("/path/to/rustc\n{}\nfoobar\n", main_rs.path().display()); + temp.write_all(content.as_bytes()).unwrap(); + + let argfile = format!("@{}", temp.path().display()); + let args = ["cargo", &argfile, "boo!"]; + match FixArgs::from_args(args.map(|x| x.into())) { + Err(e) => assert_eq!( + e.to_string(), + "argfile `@path` cannot be combined with other arguments" + ), + Ok(_) => panic!("should fail"), + } + } +} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -13,13 +13,13 @@ pub use self::cargo_install::{install, install_list}; pub use self::cargo_new::{init, new, NewOptions, VersionControl}; pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions}; -pub use self::cargo_package::{package, package_one, PackageOpts}; +pub use self::cargo_package::{check_yanked, package, package_one, PackageOpts}; pub use self::cargo_pkgid::pkgid; pub use self::cargo_read_manifest::{read_package, read_packages}; pub use self::cargo_run::run; pub use self::cargo_test::{run_benches, run_tests, TestOptions}; pub use self::cargo_uninstall::uninstall; -pub use self::fix::{fix, fix_maybe_exec_rustc, FixOptions}; +pub use self::fix::{fix, fix_exec_rustc, fix_get_proxy_lock_addr, FixOptions}; pub use self::lockfile::{load_pkg_lockfile, resolve_to_string, write_pkg_lockfile}; pub use self::registry::HttpTimeout; pub use self::registry::{configure_http_handle, http_handle, http_handle_and_timeout}; @@ -32,6 +32,7 @@ }; pub use self::vendor::{vendor, VendorOptions}; +pub mod cargo_add; mod cargo_clean; mod cargo_compile; pub mod cargo_config; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/registry.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/registry.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/registry.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/registry.rs 2022-10-20 06:00:42.000000000 +0000 @@ -23,6 +23,7 @@ use crate::core::source::Source; use crate::core::{Package, SourceId, Workspace}; use crate::ops; +use crate::ops::Packages; use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_DOMAIN, CRATES_IO_REGISTRY}; use crate::util::config::{self, Config, SslVersionConfig, SslVersionConfigRange}; use crate::util::errors::CargoResult; @@ -47,13 +48,13 @@ impl RegistryConfig { /// Returns `true` if the credential is [`None`]. /// - /// [`None`]: Credential::None + /// [`None`]: Self::None pub fn is_none(&self) -> bool { matches!(self, Self::None) } /// Returns `true` if the credential is [`Token`]. /// - /// [`Token`]: Credential::Token + /// [`Token`]: Self::Token pub fn is_token(&self) -> bool { matches!(self, Self::Token(..)) } @@ -79,7 +80,7 @@ pub index: Option, pub verify: bool, pub allow_dirty: bool, - pub jobs: Option, + pub jobs: Option, pub keep_going: bool, pub to_publish: ops::Packages, pub targets: Vec, @@ -90,7 +91,24 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { let specs = opts.to_publish.to_package_id_specs(ws)?; + if specs.len() > 1 { + bail!("the `-p` argument must be specified to select a single package to publish") + } + if Packages::Default == opts.to_publish && ws.is_virtual() { + bail!("the `-p` argument must be specified in the root of a virtual workspace") + } + let member_ids = ws.members().map(|p| p.package_id()); + // Check that the spec matches exactly one member. + specs[0].query(member_ids)?; let mut pkgs = ws.members_with_features(&specs, &opts.cli_features)?; + // In `members_with_features_old`, it will add "current" package (determined by the cwd) + // So we need filter + pkgs = pkgs + .into_iter() + .filter(|(m, _)| specs.iter().any(|spec| spec.matches(m.package_id()))) + .collect(); + // Double check. It is safe theoretically, unless logic has updated. + assert_eq!(pkgs.len(), 1); let (pkg, cli_features) = pkgs.pop().unwrap(); @@ -513,6 +531,13 @@ None }; let handle = http_handle(config)?; + // Workaround for the sparse+https://index.crates.io replacement index. Use the non-replaced + // source_id so that the original (github) url is used when publishing a crate. + let sid = if sid.is_default_registry() { + SourceId::crates_io(config)? + } else { + sid + }; Ok((Registry::new_handle(api_host, token, handle), reg_cfg, sid)) } @@ -896,10 +921,9 @@ let (mut registry, _, _) = registry(config, token, index.as_deref(), reg.as_deref(), true, true)?; + let package_spec = format!("{}@{}", name, version); if undo { - config - .shell() - .status("Unyank", format!("{}:{}", name, version))?; + config.shell().status("Unyank", package_spec)?; registry.unyank(&name, &version).with_context(|| { format!( "failed to undo a yank from the registry at {}", @@ -907,9 +931,7 @@ ) })?; } else { - config - .shell() - .status("Yank", format!("{}:{}", name, version))?; + config.shell().status("Yank", package_spec)?; registry .yank(&name, &version) .with_context(|| format!("failed to yank from the registry at {}", registry.host()))?; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/resolve.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/resolve.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/resolve.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/resolve.rs 2022-10-20 06:00:42.000000000 +0000 @@ -209,7 +209,7 @@ Ok(resolve) } -/// Resolves 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 @@ -386,21 +386,19 @@ let keep = |p: &PackageId| pre_patch_keep(p) && !avoid_patch_ids.contains(p); let dev_deps = ws.require_optional_deps() || has_dev_units == HasDevUnits::Yes; - // In the case where a previous instance of resolve is available, we - // want to lock as many packages as possible to the previous version - // without disturbing the graph structure. + if let Some(r) = previous { trace!("previous: {:?}", r); + + // In the case where a previous instance of resolve is available, we + // want to lock as many packages as possible to the previous version + // without disturbing the graph structure. register_previous_locks(ws, registry, r, &keep, dev_deps); - } - // Prefer to use anything in the previous lock file, aka we want to have conservative updates. - for r in previous { - for id in r.iter() { - if keep(&id) { - debug!("attempting to prefer {}", id); - version_prefs.prefer_package_id(id); - } + // Prefer to use anything in the previous lock file, aka we want to have conservative updates. + for id in r.iter().filter(keep) { + debug!("attempting to prefer {}", id); + version_prefs.prefer_package_id(id); } } @@ -408,6 +406,12 @@ registry.lock_patches(); } + // Some packages are already loaded when setting up a workspace. This + // makes it so anything that was already loaded will not be loaded again. + // Without this there were cases where members would be parsed multiple times + ws.preload(registry); + + // In case any members were not already loaded or the Workspace is_ephemeral. for member in ws.members() { registry.add_sources(Some(member.package_id().source_id()))?; } @@ -790,7 +794,7 @@ writeln!(msg, "Patch `{}` {}", unused, MESSAGE)?; write!( msg, - "Perhaps you misspell the source URL being patched.\n\ + "Perhaps you misspelled the source URL being patched.\n\ Possible URLs for `[patch.]`:", )?; for id in ids.iter() { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/ops/vendor.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/vendor.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/ops/vendor.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/ops/vendor.rs 2022-10-20 06:00:42.000000000 +0000 @@ -60,7 +60,7 @@ #[serde(rename_all = "lowercase", untagged)] enum VendorSource { Directory { - directory: PathBuf, + directory: String, }, Registry { registry: Option, @@ -298,7 +298,10 @@ config.insert( merged_source_name.to_string(), VendorSource::Directory { - directory: opts.destination.to_path_buf(), + // Windows-flavour paths are valid here on Windows but Unix. + // This backslash normalization is for making output paths more + // cross-platform compatible. + directory: opts.destination.to_string_lossy().replace("\\", "/"), }, ); } else if !dest_dir_already_exists { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/config.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/config.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/config.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/config.rs 2022-10-20 06:00:42.000000000 +0000 @@ -91,6 +91,15 @@ replace_with: None, }, )?; + if config.cli_unstable().sparse_registry { + base.add( + CRATES_IO_REGISTRY, + SourceConfig { + id: SourceId::crates_io_maybe_sparse_http(config)?, + replace_with: None, + }, + )?; + } Ok(base) } @@ -248,7 +257,7 @@ check_not_set("rev", def.rev)?; } if name == CRATES_IO_REGISTRY && srcs.is_empty() { - srcs.push(SourceId::crates_io(self.config)?); + srcs.push(SourceId::crates_io_maybe_sparse_http(self.config)?); } match srcs.len() { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/directory.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/directory.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/directory.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/directory.rs 2022-10-20 06:00:42.000000000 +0000 @@ -4,7 +4,7 @@ use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::errors::CargoResult; use crate::util::Config; @@ -46,28 +46,21 @@ } impl<'cfg> Source for DirectorySource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - if !self.updated { - return Poll::Pending; - } - let packages = self.packages.values().map(|p| &p.0); - let matches = packages.filter(|pkg| dep.matches(pkg.summary())); - for summary in matches.map(|pkg| pkg.summary().clone()) { - f(summary); - } - Poll::Ready(Ok(())) - } - - fn fuzzy_query( + fn query( &mut self, - _dep: &Dependency, + dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if !self.updated { return Poll::Pending; } let packages = self.packages.values().map(|p| &p.0); - for summary in packages.map(|pkg| pkg.summary().clone()) { + let matches = packages.filter(|pkg| match kind { + QueryKind::Exact => dep.matches(pkg.summary()), + QueryKind::Fuzzy => true, + }); + for summary in matches.map(|pkg| pkg.summary().clone()) { f(summary); } Poll::Ready(Ok(())) @@ -219,8 +212,8 @@ fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {} - fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult { - Ok(false) + fn is_yanked(&mut self, _pkg: PackageId) -> Poll> { + Poll::Ready(Ok(false)) } fn invalidate_cache(&mut self) { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/git/source.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/git/source.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/git/source.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/git/source.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,4 +1,4 @@ -use crate::core::source::{MaybePackage, Source, SourceId}; +use crate::core::source::{MaybePackage, QueryKind, Source, SourceId}; use crate::core::GitReference; use crate::core::{Dependency, Package, PackageId, Summary}; use crate::sources::git::utils::GitRemote; @@ -7,6 +7,7 @@ use crate::util::hex::short_hash; use crate::util::Config; use anyhow::Context; +use cargo_util::paths::exclude_from_backups_and_indexing; use log::trace; use std::fmt::{self, Debug, Formatter}; use std::task::Poll; @@ -85,21 +86,14 @@ } impl<'cfg> Source for GitSource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - if let Some(src) = self.path_source.as_mut() { - src.query(dep, f) - } else { - Poll::Pending - } - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if let Some(src) = self.path_source.as_mut() { - src.fuzzy_query(dep, f) + src.query(dep, kind, f) } else { Poll::Pending } @@ -122,8 +116,22 @@ return Ok(()); } - let git_path = self.config.git_path(); - let git_path = self.config.assert_package_cache_locked(&git_path); + let git_fs = self.config.git_path(); + // Ignore errors creating it, in case this is a read-only filesystem: + // perhaps the later operations can succeed anyhow. + let _ = git_fs.create_dir(); + let git_path = self.config.assert_package_cache_locked(&git_fs); + + // Before getting a checkout, make sure that `/git` is + // marked as excluded from indexing and backups. Older versions of Cargo + // didn't do this, so we do it here regardless of whether `` + // exists. + // + // This does not use `create_dir_all_excluded_from_backups_atomic` for + // the same reason: we want to exclude it even if the directory already + // exists. + exclude_from_backups_and_indexing(&git_path); + let db_path = git_path.join("db").join(&self.ident); let db = self.remote.db_at(&db_path).ok(); @@ -219,8 +227,8 @@ fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {} - fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult { - Ok(false) + fn is_yanked(&mut self, _pkg: PackageId) -> Poll> { + Poll::Ready(Ok(false)) } fn invalidate_cache(&mut self) {} diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/git/utils.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/git/utils.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/git/utils.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/git/utils.rs 2022-10-20 06:00:42.000000000 +0000 @@ -7,7 +7,7 @@ use anyhow::{anyhow, Context as _}; use cargo_util::{paths, ProcessBuilder}; use curl::easy::List; -use git2::{self, ErrorClass, ObjectType}; +use git2::{self, ErrorClass, ObjectType, Oid}; use log::{debug, info}; use serde::ser; use serde::Serialize; @@ -15,6 +15,7 @@ use std::fmt; use std::path::{Path, PathBuf}; use std::process::Command; +use std::str; use std::time::{Duration, Instant}; use url::Url; @@ -151,30 +152,16 @@ dest: &Path, cargo_config: &Config, ) -> CargoResult> { - let mut checkout = None; - if let Ok(repo) = git2::Repository::open(dest) { - let mut co = GitCheckout::new(dest, self, rev, repo); - if !co.is_fresh() { - // After a successful fetch operation the subsequent reset can - // fail sometimes for corrupt repositories where the fetch - // operation succeeds but the object isn't actually there in one - // way or another. In these situations just skip the error and - // try blowing away the whole repository and trying with a - // clone. - co.fetch(cargo_config)?; - match co.reset(cargo_config) { - Ok(()) => { - assert!(co.is_fresh()); - checkout = Some(co); - } - Err(e) => debug!("failed reset after fetch {:?}", e), - } - } else { - checkout = Some(co); - } - }; - let checkout = match checkout { - Some(c) => c, + // If the existing checkout exists, and it is fresh, use it. + // A non-fresh checkout can happen if the checkout operation was + // interrupted. In that case, the checkout gets deleted and a new + // clone is created. + let checkout = match git2::Repository::open(dest) + .ok() + .map(|repo| GitCheckout::new(dest, self, rev, repo)) + .filter(|co| co.is_fresh()) + { + Some(co) => co, None => GitCheckout::clone_into(dest, self, rev, cargo_config)?, }; checkout.update_submodules(cargo_config)?; @@ -311,14 +298,6 @@ } } - fn fetch(&mut self, cargo_config: &Config) -> CargoResult<()> { - info!("fetch {}", self.repo.path().display()); - let url = self.database.path.into_url()?; - let reference = GitReference::Rev(self.revision.to_string()); - fetch(&mut self.repo, url.as_str(), &reference, cargo_config)?; - Ok(()) - } - fn reset(&self, config: &Config) -> CargoResult<()> { // 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 @@ -370,6 +349,18 @@ anyhow::format_err!("non-utf8 url for submodule {:?}?", child.path()) })?; + // Skip the submodule if the config says not to update it. + if child.update_strategy() == git2::SubmoduleUpdate::None { + cargo_config.shell().status( + "Skipping", + format!( + "git submodule `{}` due to update strategy in .gitmodules", + url + ), + )?; + return Ok(()); + } + // A submodule which is listed in .gitmodules but not actually // checked out will not have a head id, so we should ignore it. let head = match child.head_id() { @@ -517,7 +508,7 @@ // // If ssh-agent authentication fails, libgit2 will keep calling this // callback asking for other authentication methods to try. Check - // cred_helper_bad to make sure we only try the git credentail helper + // cred_helper_bad to make sure we only try the git credential helper // once, to avoid looping forever. if allowed.contains(git2::CredentialType::USER_PASS_PLAINTEXT) && cred_helper_bad.is_none() { @@ -769,11 +760,15 @@ // If we're fetching from GitHub, attempt GitHub's special fast path for // testing if we've already got an up-to-date copy of the repository - match github_up_to_date(repo, url, reference, config) { - Ok(true) => return Ok(()), - Ok(false) => {} - Err(e) => debug!("failed to check github {:?}", e), - } + let oid_to_fetch = match github_fast_path(repo, url, reference, config) { + Ok(FastPathRev::UpToDate) => return Ok(()), + Ok(FastPathRev::NeedsFetch(rev)) => Some(rev), + Ok(FastPathRev::Indeterminate) => None, + Err(e) => { + debug!("failed to check github {:?}", e); + None + } + }; // We reuse repositories quite a lot, so before we go through and update the // repo check to see if it's a little too old and could benefit from a gc. @@ -805,6 +800,8 @@ GitReference::Rev(rev) => { if rev.starts_with("refs/") { refspecs.push(format!("+{0}:{0}", rev)); + } else if let Some(oid_to_fetch) = oid_to_fetch { + refspecs.push(format!("+{0}:refs/commit/{0}", oid_to_fetch)); } else { // We don't know what the rev will point to. To handle this // situation we fetch all branches and tags, and then we pray @@ -1001,15 +998,25 @@ Ok(git2::Repository::init_opts(&path, &opts)?) } +enum FastPathRev { + /// The local rev (determined by `reference.resolve(repo)`) is already up to + /// date with what this rev resolves to on GitHub's server. + UpToDate, + /// The following SHA must be fetched in order for the local rev to become + /// up to date. + NeedsFetch(Oid), + /// Don't know whether local rev is up to date. We'll fetch _all_ branches + /// and tags from the server and see what happens. + Indeterminate, +} + /// Updating the index is done pretty regularly so we want it to be as fast as /// possible. For registries hosted on GitHub (like the crates.io index) there's /// a fast path available to use [1] to tell us that there's no updates to be /// made. /// /// This function will attempt to hit that fast path and verify that the `oid` -/// is actually the current branch of the repository. If `true` is returned then -/// no update needs to be performed, but if `false` is returned then the -/// standard update logic still needs to happen. +/// is actually the current branch of the repository. /// /// [1]: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference /// @@ -1017,17 +1024,19 @@ /// just a fast path. As a result all errors are ignored in this function and we /// just return a `bool`. Any real errors will be reported through the normal /// update path above. -fn github_up_to_date( +fn github_fast_path( repo: &mut git2::Repository, url: &str, reference: &GitReference, config: &Config, -) -> CargoResult { +) -> CargoResult { let url = Url::parse(url)?; - if url.host_str() != Some("github.com") { - return Ok(false); + if !is_github(&url) { + return Ok(FastPathRev::Indeterminate); } + let local_object = reference.resolve(repo).ok(); + let github_branch_name = match reference { GitReference::Branch(branch) => branch, GitReference::Tag(tag) => tag, @@ -1035,9 +1044,33 @@ GitReference::Rev(rev) => { if rev.starts_with("refs/") { rev + } else if looks_like_commit_hash(rev) { + // `revparse_single` (used by `resolve`) is the only way to turn + // short hash -> long hash, but it also parses other things, + // like branch and tag names, which might coincidentally be + // valid hex. + // + // We only return early if `rev` is a prefix of the object found + // by `revparse_single`. Don't bother talking to GitHub in that + // case, since commit hashes are permanent. If a commit with the + // requested hash is already present in the local clone, its + // contents must be the same as what is on the server for that + // hash. + // + // If `rev` is not found locally by `revparse_single`, we'll + // need GitHub to resolve it and get a hash. If `rev` is found + // but is not a short hash of the found object, it's probably a + // branch and we also need to get a hash from GitHub, in case + // the branch has moved. + if let Some(local_object) = local_object { + if is_short_hash_of(rev, local_object) { + return Ok(FastPathRev::UpToDate); + } + } + rev } else { debug!("can't use github fast path with `rev = \"{}\"`", rev); - return Ok(false); + return Ok(FastPathRev::Indeterminate); } } }; @@ -1070,10 +1103,50 @@ handle.get(true)?; handle.url(&url)?; handle.useragent("cargo")?; - let mut headers = List::new(); - headers.append("Accept: application/vnd.github.3.sha")?; - headers.append(&format!("If-None-Match: \"{}\"", reference.resolve(repo)?))?; - handle.http_headers(headers)?; - handle.perform()?; - Ok(handle.response_code()? == 304) + handle.http_headers({ + let mut headers = List::new(); + headers.append("Accept: application/vnd.github.3.sha")?; + if let Some(local_object) = local_object { + headers.append(&format!("If-None-Match: \"{}\"", local_object))?; + } + headers + })?; + + let mut response_body = Vec::new(); + let mut transfer = handle.transfer(); + transfer.write_function(|data| { + response_body.extend_from_slice(data); + Ok(data.len()) + })?; + transfer.perform()?; + drop(transfer); // end borrow of handle so that response_code can be called + + let response_code = handle.response_code()?; + if response_code == 304 { + Ok(FastPathRev::UpToDate) + } else if response_code == 200 { + let oid_to_fetch = str::from_utf8(&response_body)?.parse::()?; + Ok(FastPathRev::NeedsFetch(oid_to_fetch)) + } else { + // Usually response_code == 404 if the repository does not exist, and + // response_code == 422 if exists but GitHub is unable to resolve the + // requested rev. + Ok(FastPathRev::Indeterminate) + } +} + +fn is_github(url: &Url) -> bool { + url.host_str() == Some("github.com") +} + +fn looks_like_commit_hash(rev: &str) -> bool { + rev.len() >= 7 && rev.chars().all(|ch| ch.is_ascii_hexdigit()) +} + +fn is_short_hash_of(rev: &str, oid: Oid) -> bool { + let long_hash = oid.to_string(); + match long_hash.get(..rev.len()) { + Some(truncated_long_hash) => truncated_long_hash.eq_ignore_ascii_case(rev), + None => false, + } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/path.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/path.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/path.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/path.rs 2022-10-20 06:00:42.000000000 +0000 @@ -4,7 +4,7 @@ use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::ops; use crate::util::{internal, CargoResult, Config}; use anyhow::Context as _; @@ -150,7 +150,7 @@ } }; - let mut filter = |path: &Path, is_dir: bool| { + let filter = |path: &Path, is_dir: bool| { let relative_path = match path.strip_prefix(root) { Ok(p) => p, Err(_) => return false, @@ -169,10 +169,10 @@ // Attempt Git-prepopulate only if no `include` (see rust-lang/cargo#4135). if no_include_option { if let Some(repo) = git_repo { - return self.list_files_git(pkg, &repo, &mut filter); + return self.list_files_git(pkg, &repo, &filter); } } - self.list_files_walk(pkg, &mut filter) + self.list_files_walk(pkg, &filter) } /// Returns `Some(git2::Repository)` if found sibling `Cargo.toml` and `.git` @@ -222,7 +222,7 @@ &self, pkg: &Package, repo: &git2::Repository, - filter: &mut dyn FnMut(&Path, bool) -> bool, + filter: &dyn Fn(&Path, bool) -> bool, ) -> CargoResult> { warn!("list_files_git {}", pkg.package_id()); let index = repo.index()?; @@ -376,7 +376,7 @@ fn list_files_walk( &self, pkg: &Package, - filter: &mut dyn FnMut(&Path, bool) -> bool, + filter: &dyn Fn(&Path, bool) -> bool, ) -> CargoResult> { let mut ret = Vec::new(); self.walk(pkg.root(), &mut ret, true, filter)?; @@ -388,7 +388,7 @@ path: &Path, ret: &mut Vec, is_root: bool, - filter: &mut dyn FnMut(&Path, bool) -> bool, + filter: &dyn Fn(&Path, bool) -> bool, ) -> CargoResult<()> { let walkdir = WalkDir::new(path) .follow_links(true) @@ -432,7 +432,11 @@ self.config.shell().warn(err)?; } Err(err) => match err.path() { - // If the error occurs with a path, simply recover from it. + // If an error occurs with a path, filter it again. + // If it is excluded, Just ignore it in this case. + // See issue rust-lang/cargo#10917 + Some(path) if !filter(path, path.is_dir()) => {} + // Otherwise, simply recover from it. // Don't worry about error skipping here, the callers would // still hit the IO error if they do access it thereafter. Some(path) => ret.push(path.to_path_buf()), @@ -497,24 +501,21 @@ } impl<'cfg> Source for PathSource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - self.update()?; - for s in self.packages.iter().map(|p| p.summary()) { - if dep.matches(s) { - f(s.clone()) - } - } - Poll::Ready(Ok(())) - } - - fn fuzzy_query( + fn query( &mut self, - _dep: &Dependency, + dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { self.update()?; for s in self.packages.iter().map(|p| p.summary()) { - f(s.clone()) + let matched = match kind { + QueryKind::Exact => dep.matches(s), + QueryKind::Fuzzy => true, + }; + if matched { + f(s.clone()) + } } Poll::Ready(Ok(())) } @@ -562,8 +563,8 @@ fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {} - fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult { - Ok(false) + fn is_yanked(&mut self, _pkg: PackageId) -> Poll> { + Poll::Ready(Ok(false)) } fn block_until_ready(&mut self) -> CargoResult<()> { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/http_remote.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/http_remote.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/http_remote.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/http_remote.rs 2022-10-20 06:00:42.000000000 +0000 @@ -14,7 +14,7 @@ use curl::easy::{HttpVersion, List}; use curl::multi::{EasyHandle, Multi}; use log::{debug, trace}; -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; @@ -98,6 +98,9 @@ progress: RefCell>>, /// Number of downloads that have successfully finished. downloads_finished: usize, + /// Number of times the caller has requested blocking. This is used for + /// an estimate of progress. + blocking_calls: usize, } struct Download { @@ -113,10 +116,6 @@ /// ETag or Last-Modified header received from the server (if any). index_version: RefCell>, - - /// Statistics updated from the progress callback in libcurl. - total: Cell, - current: Cell, } struct CompletedDownload { @@ -126,16 +125,25 @@ } impl<'cfg> HttpRegistry<'cfg> { - pub fn new(source_id: SourceId, config: &'cfg Config, name: &str) -> HttpRegistry<'cfg> { - let url = source_id - .url() - .to_string() + pub fn new( + source_id: SourceId, + config: &'cfg Config, + name: &str, + ) -> CargoResult> { + if !config.cli_unstable().sparse_registry { + anyhow::bail!("usage of sparse registries requires `-Z sparse-registry`"); + } + let url = source_id.url().as_str(); + // Ensure the url ends with a slash so we can concatenate paths. + if !url.ends_with('/') { + anyhow::bail!("registry url must end in a slash `/`: {url}") + } + let url = url .trim_start_matches("sparse+") - .trim_end_matches('/') .into_url() .expect("a url with the protocol stripped should still be valid"); - HttpRegistry { + Ok(HttpRegistry { index_path: config.registry_index_path().join(name), cache_path: config.registry_cache_path().join(name), source_id, @@ -149,17 +157,18 @@ pending_ids: HashMap::new(), results: HashMap::new(), progress: RefCell::new(Some(Progress::with_style( - "Fetching", - ProgressStyle::Ratio, + "Fetch", + ProgressStyle::Indeterminate, config, ))), downloads_finished: 0, + blocking_calls: 0, }, fresh: HashSet::new(), requested_update: false, fetch_started: false, registry_config: None, - } + }) } fn handle_http_header(buf: &[u8]) -> Option<(&str, &str)> { @@ -245,7 +254,8 @@ } fn full_url(&self, path: &Path) -> String { - format!("{}/{}", self.url, path.display()) + // self.url always ends with a slash. + format!("{}{}", self.url, path.display()) } fn is_fresh(&self, path: &Path) -> bool { @@ -447,15 +457,6 @@ Ok(buf.len()) })?; - // Same goes for the progress function -- it goes through thread-local storage. - handle.progress(true)?; - handle.progress_function(move |dl_total, dl_cur, _, _| { - tls::with(|downloads| match downloads { - Some(d) => d.progress(token, dl_total as u64, dl_cur as u64), - None => false, - }) - })?; - // And ditto for the header function. handle.header_function(move |buf| { if let Some((tag, value)) = Self::handle_http_header(buf) { @@ -484,8 +485,6 @@ data: RefCell::new(Vec::new()), path: path.to_path_buf(), index_version: RefCell::new(None), - total: Cell::new(0), - current: Cell::new(0), }; // Finally add the request we've lined up to the pool of requests that cURL manages. @@ -578,11 +577,11 @@ } fn block_until_ready(&mut self) -> CargoResult<()> { - let initial_pending_count = self.downloads.pending.len(); trace!( "block_until_ready: {} transfers pending", - initial_pending_count + self.downloads.pending.len() ); + self.downloads.blocking_calls += 1; loop { self.handle_completed_downloads()?; @@ -612,21 +611,31 @@ } impl<'cfg> Downloads<'cfg> { - fn progress(&self, token: usize, total: u64, cur: u64) -> bool { - let dl = &self.pending[&token].0; - dl.total.set(total); - dl.current.set(cur); - true - } - fn tick(&self) -> CargoResult<()> { let mut progress = self.progress.borrow_mut(); let progress = progress.as_mut().unwrap(); + // Since the sparse protocol discovers dependencies as it goes, + // it's not possible to get an accurate progress indication. + // + // As an approximation, we assume that the depth of the dependency graph + // is fixed, and base the progress on how many times the caller has asked + // for blocking. If there are actually additional dependencies, the progress + // bar will get stuck. If there are fewer dependencies, it will disappear + // early. It will never go backwards. + // + // The status text also contains the number of completed & pending requests, which + // gives an better indication of forward progress. + let approximate_tree_depth = 10; + progress.tick( - self.downloads_finished, - self.downloads_finished + self.pending.len(), - "", + self.blocking_calls.min(approximate_tree_depth), + approximate_tree_depth + 1, + &format!( + " {} complete; {} pending", + self.downloads_finished, + self.pending.len() + ), ) } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/index.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/index.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/index.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/index.rs 2022-10-20 06:00:42.000000000 +0000 @@ -76,7 +76,6 @@ use log::{debug, info}; use semver::Version; use std::collections::{HashMap, HashSet}; -use std::convert::TryInto; use std::fs; use std::io::ErrorKind; use std::path::Path; @@ -410,7 +409,7 @@ Poll::Ready(Ok(self.summaries_cache.get_mut(&name).unwrap())) } - /// Clears the in-memory summmaries cache. + /// Clears the in-memory summaries cache. pub fn clear_summaries_cache(&mut self) { self.summaries_cache.clear(); } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/local.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/local.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/local.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/local.rs 2022-10-20 06:00:42.000000000 +0000 @@ -4,8 +4,8 @@ use crate::util::{Config, Filesystem}; use cargo_util::{paths, Sha256}; use std::fs::File; -use std::io::prelude::*; use std::io::SeekFrom; +use std::io::{self, prelude::*}; use std::path::Path; use std::task::Poll; @@ -54,8 +54,17 @@ _index_version: Option<&str>, ) -> Poll> { if self.updated { + let raw_data = match paths::read_bytes(&root.join(path)) { + Err(e) + if e.downcast_ref::() + .map_or(false, |ioe| ioe.kind() == io::ErrorKind::NotFound) => + { + return Poll::Ready(Ok(LoadResponse::NotFound)); + } + r => r, + }?; Poll::Ready(Ok(LoadResponse::Data { - raw_data: paths::read_bytes(&root.join(path))?, + raw_data, index_version: None, })) } else { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -167,6 +167,7 @@ use std::task::Poll; use anyhow::Context as _; +use cargo_util::paths::exclude_from_backups_and_indexing; use flate2::read::GzDecoder; use log::debug; use semver::Version; @@ -175,7 +176,7 @@ use crate::core::dependency::{DepKind, Dependency}; use crate::core::source::MaybePackage; -use crate::core::{Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::hex; use crate::util::interning::InternedString; @@ -185,6 +186,7 @@ const PACKAGE_SOURCE_LOCK: &str = ".cargo-ok"; pub const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index"; +pub const CRATES_IO_HTTP_INDEX: &str = "sparse+https://index.crates.io/"; pub const CRATES_IO_REGISTRY: &str = "crates-io"; pub const CRATES_IO_DOMAIN: &str = "crates.io"; const CRATE_TEMPLATE: &str = "{crate}"; @@ -545,13 +547,11 @@ ) -> CargoResult> { let name = short_name(source_id); let ops = if source_id.url().scheme().starts_with("sparse+") { - if !config.cli_unstable().http_registry { - anyhow::bail!("Usage of HTTP-based registries requires `-Z http-registry`"); - } - Box::new(http_remote::HttpRegistry::new(source_id, config, &name)) as Box<_> + Box::new(http_remote::HttpRegistry::new(source_id, config, &name)?) as Box<_> } else { Box::new(remote::RemoteRegistry::new(source_id, config, &name)) as Box<_> }; + Ok(RegistrySource::new( source_id, config, @@ -701,12 +701,18 @@ } impl<'cfg> Source for RegistrySource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { + fn query( + &mut self, + dep: &Dependency, + kind: QueryKind, + f: &mut dyn FnMut(Summary), + ) -> Poll> { // 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. - if dep.source_id().precise().is_some() && !self.ops.is_updated() { + if kind == QueryKind::Exact && dep.source_id().precise().is_some() && !self.ops.is_updated() + { debug!("attempting query without update"); let mut called = false; let pend = @@ -731,21 +737,16 @@ self.index .query_inner(dep, &mut *self.ops, &self.yanked_whitelist, &mut |s| { - if dep.matches(&s) { + let matched = match kind { + QueryKind::Exact => dep.matches(&s), + QueryKind::Fuzzy => true, + }; + if matched { f(s); } }) } - fn fuzzy_query( - &mut self, - dep: &Dependency, - f: &mut dyn FnMut(Summary), - ) -> Poll> { - self.index - .query_inner(dep, &mut *self.ops, &self.yanked_whitelist, f) - } - fn supports_checksums(&self) -> bool { true } @@ -801,17 +802,26 @@ self.yanked_whitelist.extend(pkgs); } - fn is_yanked(&mut self, pkg: PackageId) -> CargoResult { - self.invalidate_cache(); - loop { - match self.index.is_yanked(pkg, &mut *self.ops)? { - Poll::Ready(yanked) => return Ok(yanked), - Poll::Pending => self.block_until_ready()?, - } - } + fn is_yanked(&mut self, pkg: PackageId) -> Poll> { + self.index.is_yanked(pkg, &mut *self.ops) } fn block_until_ready(&mut self) -> CargoResult<()> { + // Before starting to work on the registry, make sure that + // `/registry` is marked as excluded from indexing and + // backups. Older versions of Cargo didn't do this, so we do it here + // regardless of whether `` exists. + // + // This does not use `create_dir_all_excluded_from_backups_atomic` for + // the same reason: we want to exclude it even if the directory already + // exists. + // + // IO errors in creating and marking it are ignored, e.g. in case we're on a + // read-only filesystem. + let registry_base = self.config.registry_base_path(); + let _ = registry_base.create_dir(); + exclude_from_backups_and_indexing(®istry_base.into_path_unlocked()); + self.ops.block_until_ready() } } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/remote.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/remote.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/registry/remote.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/registry/remote.rs 2022-10-20 06:00:42.000000000 +0000 @@ -159,6 +159,13 @@ self.config.assert_package_cache_locked(path) } + // `index_version` Is a string representing the version of the file used to construct the cached copy. + // Older versions of Cargo used the single value of the hash of the HEAD commit as a `index_version`. + // This is technically correct but a little too conservative. If a new commit is fetched all cached + // files need to be regenerated even if a particular file was not changed. + // However if an old cargo has written such a file we still know how to read it, as long as we check for that hash value. + // + // Cargo now uses a hash of the file's contents as provided by git. fn load( &mut self, _root: &Path, @@ -169,8 +176,9 @@ return Poll::Pending; } // Check if the cache is valid. - let current_version = self.current_version(); - if current_version.is_some() && current_version.as_deref() == index_version { + let git_commit_hash = self.current_version(); + if index_version.is_some() && index_version == git_commit_hash.as_deref() { + // This file was written by an old version of cargo, but it is still up-to-date. return Poll::Ready(Ok(LoadResponse::CacheValid)); } // Note that the index calls this method and the filesystem is locked @@ -179,12 +187,19 @@ fn load_helper( registry: &RemoteRegistry<'_>, path: &Path, - current_version: Option<&str>, + index_version: Option<&str>, ) -> CargoResult { let repo = registry.repo()?; let tree = registry.tree()?; let entry = tree.get_path(path); let entry = entry?; + let git_file_hash = Some(entry.id().to_string()); + + // Check if the cache is valid. + if index_version.is_some() && index_version == git_file_hash.as_deref() { + return Ok(LoadResponse::CacheValid); + } + let object = entry.to_object(repo)?; let blob = match object.as_blob() { Some(blob) => blob, @@ -193,11 +208,11 @@ Ok(LoadResponse::Data { raw_data: blob.content().to_vec(), - index_version: current_version.map(String::from), + index_version: git_file_hash, }) } - match load_helper(&self, path, current_version.as_deref()) { + match load_helper(&self, path, index_version) { Ok(result) => Poll::Ready(Ok(result)), Err(_) if !self.updated => { // If git returns an error and we haven't updated the repo, return diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/sources/replaced.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/replaced.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/sources/replaced.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/sources/replaced.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,5 @@ use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::util::errors::CargoResult; use std::task::Poll; @@ -42,32 +42,17 @@ self.inner.requires_precise() } - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - let (replace_with, to_replace) = (self.replace_with, self.to_replace); - let dep = dep.clone().map_source(to_replace, replace_with); - - self.inner - .query(&dep, &mut |summary| { - f(summary.map_source(replace_with, to_replace)) - }) - .map_err(|e| { - e.context(format!( - "failed to query replaced source {}", - self.to_replace - )) - }) - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { let (replace_with, to_replace) = (self.replace_with, self.to_replace); let dep = dep.clone().map_source(to_replace, replace_with); self.inner - .fuzzy_query(&dep, &mut |summary| { + .query(&dep, kind, &mut |summary| { f(summary.map_source(replace_with, to_replace)) }) .map_err(|e| { @@ -134,7 +119,7 @@ self.inner.add_to_yanked_whitelist(&pkgs); } - fn is_yanked(&mut self, pkg: PackageId) -> CargoResult { + fn is_yanked(&mut self, pkg: PackageId) -> Poll> { self.inner.is_yanked(pkg) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/command_prelude.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/command_prelude.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/command_prelude.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/command_prelude.rs 2022-10-20 06:00:42.000000000 +0000 @@ -20,7 +20,7 @@ pub use crate::core::compiler::CompileMode; pub use crate::{CliError, CliResult, Config}; -pub use clap::{AppSettings, Arg, ArgMatches}; +pub use clap::{value_parser, AppSettings, Arg, ArgAction, ArgMatches}; pub type App = clap::Command<'static>; @@ -36,7 +36,7 @@ exclude: &'static str, ) -> Self { self.arg_package_spec_no_all(package, all, exclude) - ._arg(opt("all", "Alias for --workspace (deprecated)")) + ._arg(flag("all", "Alias for --workspace (deprecated)")) } /// Variant of arg_package_spec that does not include the `--all` flag @@ -49,7 +49,7 @@ exclude: &'static str, ) -> Self { self.arg_package_spec_simple(package) - ._arg(opt("workspace", all)) + ._arg(flag("workspace", all)) ._arg(multi_opt("exclude", "SPEC", exclude)) } @@ -69,9 +69,10 @@ self._arg( opt("jobs", "Number of parallel jobs, defaults to # of CPUs") .short('j') - .value_name("N"), + .value_name("N") + .allow_hyphen_values(true), ) - ._arg(opt( + ._arg(flag( "keep-going", "Do not abort the build as soon as there is an error (unstable)", )) @@ -92,10 +93,10 @@ ) -> Self { self.arg_targets_lib_bin_example(lib, bin, bins, example, examples) ._arg(optional_multi_opt("test", "NAME", test)) - ._arg(opt("tests", tests)) + ._arg(flag("tests", tests)) ._arg(optional_multi_opt("bench", "NAME", bench)) - ._arg(opt("benches", benches)) - ._arg(opt("all-targets", all)) + ._arg(flag("benches", benches)) + ._arg(flag("all-targets", all)) } fn arg_targets_lib_bin_example( @@ -106,11 +107,11 @@ example: &'static str, examples: &'static str, ) -> Self { - self._arg(opt("lib", lib)) + self._arg(flag("lib", lib)) ._arg(optional_multi_opt("bin", "NAME", bin)) - ._arg(opt("bins", bins)) + ._arg(flag("bins", bins)) ._arg(optional_multi_opt("example", "NAME", example)) - ._arg(opt("examples", examples)) + ._arg(flag("examples", examples)) } fn arg_targets_bins_examples( @@ -121,9 +122,9 @@ examples: &'static str, ) -> Self { self._arg(optional_multi_opt("bin", "NAME", bin)) - ._arg(opt("bins", bins)) + ._arg(flag("bins", bins)) ._arg(optional_multi_opt("example", "NAME", example)) - ._arg(opt("examples", examples)) + ._arg(flag("examples", examples)) } fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self { @@ -132,20 +133,23 @@ } fn arg_features(self) -> Self { - self._arg(multi_opt( - "features", - "FEATURES", - "Space or comma separated list of features to activate", - )) - ._arg(opt("all-features", "Activate all available features")) - ._arg(opt( + self._arg( + multi_opt( + "features", + "FEATURES", + "Space or comma separated list of features to activate", + ) + .short('F'), + ) + ._arg(flag("all-features", "Activate all available features")) + ._arg(flag( "no-default-features", "Do not activate the `default` feature", )) } fn arg_release(self, release: &'static str) -> Self { - self._arg(opt("release", release).short('r')) + self._arg(flag("release", release).short('r')) } fn arg_profile(self, profile: &'static str) -> Self { @@ -153,7 +157,7 @@ } fn arg_doc(self, doc: &'static str) -> Self { - self._arg(opt("doc", doc)) + self._arg(flag("doc", doc)) } fn arg_target_triple(self, target: &'static str) -> Self { @@ -175,14 +179,14 @@ } fn arg_build_plan(self) -> Self { - self._arg(opt( + self._arg(flag( "build-plan", "Output the build plan in JSON (unstable)", )) } fn arg_unit_graph(self) -> Self { - self._arg(opt("unit-graph", "Output build graph in JSON (unstable)")) + self._arg(flag("unit-graph", "Output build graph in JSON (unstable)")) } fn arg_new_opts(self) -> Self { @@ -195,13 +199,13 @@ a global configuration.", ) .value_name("VCS") - .possible_values(&["git", "hg", "pijul", "fossil", "none"]), + .value_parser(["git", "hg", "pijul", "fossil", "none"]), ) - ._arg(opt("bin", "Use a binary (application) template [default]")) - ._arg(opt("lib", "Use a library template")) + ._arg(flag("bin", "Use a binary (application) template [default]")) + ._arg(flag("lib", "Use a library template")) ._arg( opt("edition", "Edition to set for the crate generated") - .possible_values(Edition::CLI_VALUES) + .value_parser(Edition::CLI_VALUES) .value_name("YEAR"), ) ._arg( @@ -218,25 +222,25 @@ } fn arg_dry_run(self, dry_run: &'static str) -> Self { - self._arg(opt("dry-run", dry_run)) + self._arg(flag("dry-run", dry_run)) } fn arg_ignore_rust_version(self) -> Self { - self._arg(opt( + self._arg(flag( "ignore-rust-version", "Ignore `rust-version` specification in packages", )) } fn arg_future_incompat_report(self) -> Self { - self._arg(opt( + self._arg(flag( "future-incompat-report", "Outputs a future incompatibility report at the end of the build", )) } fn arg_quiet(self) -> Self { - self._arg(opt("quiet", "Do not print cargo log messages").short('q')) + self._arg(flag("quiet", "Do not print cargo log messages").short('q')) } fn arg_timings(self) -> Self { @@ -257,6 +261,13 @@ } } +pub fn flag(name: &'static str, help: &'static str) -> Arg<'static> { + Arg::new(name) + .long(name) + .help(help) + .action(ArgAction::SetTrue) +} + pub fn opt(name: &'static str, help: &'static str) -> Arg<'static> { Arg::new(name).long(name).help(help) } @@ -272,7 +283,7 @@ ) -> Arg<'static> { opt(name, help) .value_name(value_name) - .multiple_occurrences(true) + .action(ArgAction::Append) .multiple_values(true) .min_values(0) .number_of_values(1) @@ -281,7 +292,7 @@ pub fn multi_opt(name: &'static str, value_name: &'static str, help: &'static str) -> Arg<'static> { opt(name, help) .value_name(value_name) - .multiple_occurrences(true) + .action(ArgAction::Append) } pub fn subcommand(name: &'static str) -> App { @@ -316,17 +327,26 @@ Ok(arg) } + fn value_of_i32(&self, name: &str) -> CargoResult> { + let arg = match self._value_of(name) { + None => None, + Some(arg) => Some(arg.parse::().map_err(|_| { + clap::Error::raw( + clap::ErrorKind::ValueValidation, + format!("Invalid value: could not parse `{}` as a number", arg), + ) + })?), + }; + Ok(arg) + } + /// Returns value of the `name` command-line argument as an absolute path fn value_of_path(&self, name: &str, config: &Config) -> Option { self._value_of(name).map(|path| config.cwd().join(path)) } fn root_manifest(&self, config: &Config) -> CargoResult { - if let Some(path) = self - ._is_valid_arg("manifest-path") - .then(|| self.value_of_path("manifest-path", config)) - .flatten() - { + if let Some(path) = self.value_of_path("manifest-path", config) { // In general, we try to avoid normalizing paths in Cargo, // but in this particular case we need it to fix #3586. let path = paths::normalize_path(&path); @@ -353,12 +373,20 @@ Ok(ws) } - fn jobs(&self) -> CargoResult> { - self.value_of_u32("jobs") + fn jobs(&self) -> CargoResult> { + self.value_of_i32("jobs") + } + + fn verbose(&self) -> u32 { + self._count("verbose") + } + + fn dry_run(&self) -> bool { + self.flag("dry-run") } fn keep_going(&self) -> bool { - self._is_present("keep-going") + self.flag("keep-going") } fn targets(&self) -> Vec { @@ -380,7 +408,7 @@ (Some(name @ ("dev" | "test" | "bench" | "check")), ProfileChecking::LegacyRustc) // `cargo fix` and `cargo check` has legacy handling of this profile name | (Some(name @ "test"), ProfileChecking::LegacyTestOnly) => { - if self._is_present("release") { + if self.flag("release") { config.shell().warn( "the `--release` flag should not be specified with the `--profile` flag\n\ The `--release` flag will be ignored.\n\ @@ -404,11 +432,7 @@ ) }; - let name = match ( - self.is_valid_and_present("release"), - self.is_valid_and_present("debug"), - specified_profile, - ) { + let name = match (self.flag("release"), self.flag("debug"), specified_profile) { (false, false, None) => default, (true, _, None | Some("release")) => "release", (true, _, Some(name)) => return Err(conflict("release", "release", name)), @@ -434,13 +458,9 @@ fn packages_from_flags(&self) -> CargoResult { Packages::from_flags( // TODO Integrate into 'workspace' - self.is_valid_and_present("workspace") || self.is_valid_and_present("all"), - self._is_valid_arg("exclude") - .then(|| self._values_of("exclude")) - .unwrap_or_default(), - self._is_valid_arg("package") - .then(|| self._values_of("package")) - .unwrap_or_default(), + self.flag("workspace") || self.flag("all"), + self._values_of("exclude"), + self._values_of("package"), ) } @@ -523,11 +543,11 @@ )?; build_config.message_format = message_format.unwrap_or(MessageFormat::Human); build_config.requested_profile = self.get_profile_name(config, "dev", profile_checking)?; - build_config.build_plan = self.is_valid_and_present("build-plan"); - build_config.unit_graph = self.is_valid_and_present("unit-graph"); - build_config.future_incompat_report = self.is_valid_and_present("future-incompat-report"); + build_config.build_plan = self.flag("build-plan"); + build_config.unit_graph = self.flag("unit-graph"); + build_config.future_incompat_report = self.flag("future-incompat-report"); - if self.is_valid_and_present("timings") { + if self._contains("timings") { for timing_output in self._values_of("timings") { for timing_output in timing_output.split(',') { let timing_output = timing_output.to_ascii_lowercase(); @@ -575,32 +595,28 @@ cli_features: self.cli_features()?, spec, filter: CompileFilter::from_raw_arguments( - self.is_valid_and_present("lib"), + self.flag("lib"), self._values_of("bin"), - self.is_valid_and_present("bins"), - self._is_valid_arg("test") - .then(|| self._values_of("test")) - .unwrap_or_default(), - self.is_valid_and_present("tests"), + self.flag("bins"), + self._values_of("test"), + self.flag("tests"), self._values_of("example"), - self.is_valid_and_present("examples"), - self._is_valid_arg("bench") - .then(|| self._values_of("bench")) - .unwrap_or_default(), - self.is_valid_and_present("benches"), - self.is_valid_and_present("all-targets"), + self.flag("examples"), + self._values_of("bench"), + self.flag("benches"), + self.flag("all-targets"), ), target_rustdoc_args: None, target_rustc_args: None, target_rustc_crate_types: None, local_rustdoc_args: None, rustdoc_document_private_items: false, - honor_rust_version: !self.is_valid_and_present("ignore-rust-version"), + honor_rust_version: !self.flag("ignore-rust-version"), }; if let Some(ws) = workspace { self.check_optional_opts(ws, &opts)?; - } else if self._is_valid_arg("package") && self.is_present_with_zero_values("package") { + } else if self.is_present_with_zero_values("package") { // As for cargo 0.50.0, this won't occur but if someone sneaks in // we can still provide this informative message for them. anyhow::bail!( @@ -616,8 +632,8 @@ fn cli_features(&self) -> CargoResult { CliFeatures::from_command_line( &self._values_of("features"), - self._is_present("all-features"), - !self._is_present("no-default-features"), + self.flag("all-features"), + !self.flag("no-default-features"), ) } @@ -648,8 +664,8 @@ }); NewOptions::new( vcs, - self._is_present("bin"), - self._is_present("lib"), + self.flag("bin"), + self.flag("lib"), self.value_of_path("path", config).unwrap(), self._value_of("name").map(|s| s.to_string()), self._value_of("edition").map(|s| s.to_string()), @@ -687,7 +703,7 @@ workspace: &Workspace<'_>, compile_opts: &CompileOptions, ) -> CargoResult<()> { - if self._is_valid_arg("package") && self.is_present_with_zero_values("package") { + if self.is_present_with_zero_values("package") { print_available_packages(workspace)? } @@ -699,11 +715,11 @@ print_available_binaries(workspace, compile_opts)?; } - if self._is_valid_arg("bench") && self.is_present_with_zero_values("bench") { + if self.is_present_with_zero_values("bench") { print_available_benches(workspace, compile_opts)?; } - if self._is_valid_arg("test") && self.is_present_with_zero_values("test") { + if self.is_present_with_zero_values("test") { print_available_tests(workspace, compile_opts)?; } @@ -711,12 +727,10 @@ } fn is_present_with_zero_values(&self, name: &str) -> bool { - self._is_present(name) && self._value_of(name).is_none() + self._contains(name) && self._value_of(name).is_none() } - fn is_valid_and_present(&self, name: &str) -> bool { - self._is_valid_arg(name) && self._is_present(name) - } + fn flag(&self, name: &str) -> bool; fn _value_of(&self, name: &str) -> Option<&str>; @@ -726,40 +740,46 @@ fn _values_of_os(&self, name: &str) -> Vec; - fn _is_present(&self, name: &str) -> bool; + fn _count(&self, name: &str) -> u32; - fn _is_valid_arg(&self, name: &str) -> bool; + fn _contains(&self, name: &str) -> bool; } impl<'a> ArgMatchesExt for ArgMatches { + fn flag(&self, name: &str) -> bool { + ignore_unknown(self.try_get_one::(name)) + .copied() + .unwrap_or(false) + } + fn _value_of(&self, name: &str) -> Option<&str> { - self.value_of(name) + ignore_unknown(self.try_get_one::(name)).map(String::as_str) } fn _value_of_os(&self, name: &str) -> Option<&OsStr> { - self.value_of_os(name) + ignore_unknown(self.try_get_one::(name)).map(OsString::as_os_str) } fn _values_of(&self, name: &str) -> Vec { - self.values_of(name) + ignore_unknown(self.try_get_many::(name)) .unwrap_or_default() - .map(|s| s.to_string()) + .cloned() .collect() } fn _values_of_os(&self, name: &str) -> Vec { - self.values_of_os(name) + ignore_unknown(self.try_get_many::(name)) .unwrap_or_default() - .map(|s| s.to_os_string()) + .cloned() .collect() } - fn _is_present(&self, name: &str) -> bool { - self.is_present(name) + fn _count(&self, name: &str) -> u32 { + *ignore_unknown(self.try_get_one::(name)).expect("defaulted by clap") as u32 } - fn _is_valid_arg(&self, name: &str) -> bool { - self.is_valid_arg(name) + fn _contains(&self, name: &str) -> bool { + ignore_unknown(self.try_contains_id(name)) } } @@ -771,6 +791,17 @@ args._values_of_os(name) } +#[track_caller] +fn ignore_unknown(r: Result) -> T { + match r { + Ok(t) => t, + Err(clap::parser::MatchesError::UnknownArgument { .. }) => Default::default(), + Err(e) => { + panic!("Mismatch between definition and access: {}", e); + } + } +} + #[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum CommandInfo { BuiltIn { about: Option }, diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/config/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/config/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/config/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/config/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -68,7 +68,7 @@ use self::ConfigValue as CV; use crate::core::compiler::rustdoc::RustdocExternMap; use crate::core::shell::Verbosity; -use crate::core::{features, CliUnstable, Shell, SourceId, Workspace}; +use crate::core::{features, CliUnstable, Shell, SourceId, Workspace, WorkspaceRootConfig}; use crate::ops; use crate::util::errors::CargoResult; use crate::util::toml as cargo_toml; @@ -202,6 +202,8 @@ /// NOTE: this should be set before `configure()`. If calling this from an integration test, /// consider using `ConfigBuilder::enable_nightly_features` instead. pub nightly_features_allowed: bool, + /// WorkspaceRootConfigs that have been found + pub ws_roots: RefCell>, } impl Config { @@ -285,6 +287,7 @@ progress_config: ProgressConfig::default(), env_config: LazyCell::new(), nightly_features_allowed: matches!(&*features::channel(), "nightly" | "dev"), + ws_roots: RefCell::new(HashMap::new()), } } @@ -315,19 +318,24 @@ self.home_path.join("git") } + /// Gets the Cargo base directory for all registry information (`/registry`). + pub fn registry_base_path(&self) -> Filesystem { + self.home_path.join("registry") + } + /// Gets the Cargo registry index directory (`/registry/index`). pub fn registry_index_path(&self) -> Filesystem { - self.home_path.join("registry").join("index") + self.registry_base_path().join("index") } /// Gets the Cargo registry cache directory (`/registry/path`). pub fn registry_cache_path(&self) -> Filesystem { - self.home_path.join("registry").join("cache") + self.registry_base_path().join("cache") } /// Gets the Cargo registry source directory (`/registry/src`). pub fn registry_source_path(&self) -> Filesystem { - self.home_path.join("registry").join("src") + self.registry_base_path().join("src") } /// Gets the default Cargo registry. @@ -887,7 +895,6 @@ self.unstable_flags_cli = Some(unstable_flags.to_vec()); } if !cli_config.is_empty() { - self.unstable_flags.fail_if_stable_opt("--config", 6699)?; self.cli_config = Some(cli_config.iter().map(|s| s.to_string()).collect()); self.merge_cli_args()?; } @@ -1160,6 +1167,7 @@ Some(cli_args) => cli_args, None => return Ok(loaded_args), }; + let mut seen = HashSet::new(); for arg in cli_args { let arg_as_path = self.cwd.join(arg); let tmp_table = if !arg.is_empty() && arg_as_path.exists() { @@ -1170,9 +1178,8 @@ anyhow::format_err!("config path {:?} is not utf-8", arg_as_path) })? .to_string(); - let value = CV::String(str_path, Definition::Cli); - let map = HashMap::from([("include".to_string(), value)]); - CV::Table(map, Definition::Cli) + self._load_file(&self.cwd().join(&str_path), &mut seen, true) + .with_context(|| format!("failed to load config from `{}`", str_path))? } else { // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys) // expressions followed by a value that's not an "inline table" @@ -1244,10 +1251,28 @@ ); } - let toml_v = toml::from_document(doc).with_context(|| { + let toml_v: toml::Value = toml::from_document(doc).with_context(|| { format!("failed to parse value from --config argument `{arg}`") })?; + if toml_v + .get("registry") + .and_then(|v| v.as_table()) + .and_then(|t| t.get("token")) + .is_some() + { + bail!("registry.token cannot be set through --config for security reasons"); + } else if let Some((k, _)) = toml_v + .get("registries") + .and_then(|v| v.as_table()) + .and_then(|t| t.iter().find(|(_, v)| v.get("token").is_some())) + { + bail!( + "registries.{}.token cannot be set through --config for security reasons", + k + ); + } + CV::from_toml(Definition::Cli, toml_v) .with_context(|| format!("failed to convert --config argument `{arg}`"))? }; @@ -2170,7 +2195,7 @@ pub target_dir: Option, pub incremental: Option, pub target: Option, - pub jobs: Option, + pub jobs: Option, pub rustflags: Option, pub rustdocflags: Option, pub rustc_wrapper: Option, @@ -2223,13 +2248,7 @@ }; let values = match &self.inner.val { BuildTargetConfigInner::One(s) => vec![map(s)], - BuildTargetConfigInner::Many(v) => { - if !config.cli_unstable().multitarget { - bail!("specifying an array in `build.target` config value requires `-Zmultitarget`") - } else { - v.iter().map(map).collect() - } - } + BuildTargetConfigInner::Many(v) => v.iter().map(map).collect(), }; Ok(values) } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/config/target.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/config/target.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/config/target.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/config/target.rs 2022-10-20 06:00:42.000000000 +0000 @@ -120,7 +120,7 @@ // Links do not support environment variables. let target_key = ConfigKey::from_str(prefix); let links_overrides = match config.get_table(&target_key)? { - Some(links) => parse_links_overrides(&target_key, links.val)?, + Some(links) => parse_links_overrides(&target_key, links.val, config)?, None => BTreeMap::new(), }; Ok(TargetConfig { @@ -134,8 +134,14 @@ fn parse_links_overrides( target_key: &ConfigKey, links: HashMap, + config: &Config, ) -> CargoResult> { let mut links_overrides = BTreeMap::new(); + let extra_check_cfg = match config.cli_unstable().check_cfg { + Some((_, _, _, output)) => output, + None => false, + }; + for (lib_name, value) in links { // Skip these keys, it shares the namespace with `TargetConfig`. match lib_name.as_str() { @@ -200,6 +206,17 @@ let list = value.list(key)?; output.cfgs.extend(list.iter().map(|v| v.0.clone())); } + "rustc-check-cfg" => { + if extra_check_cfg { + let list = value.list(key)?; + output.check_cfgs.extend(list.iter().map(|v| v.0.clone())); + } else { + config.shell().warn(format!( + "target config `{}.{}` requires -Zcheck-cfg=output flag", + target_key, key + ))?; + } + } "rustc-env" => { for (name, val) in value.table(key)?.0 { let val = val.string(name)?.0; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/dependency_queue.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/dependency_queue.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/dependency_queue.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/dependency_queue.rs 2022-10-20 06:00:42.000000000 +0000 @@ -149,15 +149,15 @@ /// /// A package is ready to be built when it has 0 un-built dependencies. If /// `None` is returned then no packages are ready to be built. - pub fn dequeue(&mut self) -> Option<(N, V)> { - let key = self + pub fn dequeue(&mut self) -> Option<(N, V, usize)> { + let (key, priority) = self .dep_map .iter() .filter(|(_, (deps, _))| deps.is_empty()) - .map(|(key, _)| key.clone()) - .max_by_key(|k| self.priority[k])?; + .map(|(key, _)| (key.clone(), self.priority[key])) + .max_by_key(|(_, priority)| *priority)?; let (_, data) = self.dep_map.remove(&key).unwrap(); - Some((key, data)) + Some((key, data, priority)) } /// Returns `true` if there are remaining packages to be built. @@ -213,19 +213,19 @@ q.queue(5, (), vec![(4, ()), (3, ())], 1); q.queue_finished(); - assert_eq!(q.dequeue(), Some((1, ()))); - assert_eq!(q.dequeue(), Some((3, ()))); + assert_eq!(q.dequeue(), Some((1, (), 5))); + assert_eq!(q.dequeue(), Some((3, (), 4))); assert_eq!(q.dequeue(), None); q.finish(&3, &()); assert_eq!(q.dequeue(), None); q.finish(&1, &()); - assert_eq!(q.dequeue(), Some((2, ()))); + assert_eq!(q.dequeue(), Some((2, (), 4))); assert_eq!(q.dequeue(), None); q.finish(&2, &()); - assert_eq!(q.dequeue(), Some((4, ()))); + assert_eq!(q.dequeue(), Some((4, (), 3))); assert_eq!(q.dequeue(), None); q.finish(&4, &()); - assert_eq!(q.dequeue(), Some((5, ()))); + assert_eq!(q.dequeue(), Some((5, (), 2))); } #[test] @@ -238,16 +238,16 @@ q.queue(4, (), vec![(2, ()), (3, ())], 1); q.queue_finished(); - assert_eq!(q.dequeue(), Some((3, ()))); - assert_eq!(q.dequeue(), Some((1, ()))); + assert_eq!(q.dequeue(), Some((3, (), 9))); + assert_eq!(q.dequeue(), Some((1, (), 4))); assert_eq!(q.dequeue(), None); q.finish(&3, &()); assert_eq!(q.dequeue(), None); q.finish(&1, &()); - assert_eq!(q.dequeue(), Some((2, ()))); + assert_eq!(q.dequeue(), Some((2, (), 3))); assert_eq!(q.dequeue(), None); q.finish(&2, &()); - assert_eq!(q.dequeue(), Some((4, ()))); + assert_eq!(q.dequeue(), Some((4, (), 2))); assert_eq!(q.dequeue(), None); q.finish(&4, &()); assert_eq!(q.dequeue(), None); diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/diagnostic_server.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/diagnostic_server.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/diagnostic_server.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/diagnostic_server.rs 2022-10-20 06:00:42.000000000 +0000 @@ -18,7 +18,7 @@ use crate::util::errors::CargoResult; use crate::util::Config; -const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER"; +const DIAGNOSTICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER"; const PLEASE_REPORT_THIS_BUG: &str = "This likely indicates a bug in either rustc or cargo itself,\n\ and we would appreciate a bug report! You're likely to see \n\ @@ -63,7 +63,7 @@ impl Message { pub fn post(&self) -> Result<(), Error> { let addr = - env::var(DIAGNOSICS_SERVER_VAR).context("diagnostics collector misconfigured")?; + env::var(DIAGNOSTICS_SERVER_VAR).context("diagnostics collector misconfigured")?; let mut client = TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?; @@ -240,7 +240,7 @@ } pub fn configure(&self, process: &mut ProcessBuilder) { - process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string()); + process.env(DIAGNOSTICS_SERVER_VAR, self.addr.to_string()); } pub fn start(self, on_message: F) -> Result diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/errors.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/errors.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/errors.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/errors.rs 2022-10-20 06:00:42.000000000 +0000 @@ -1,9 +1,6 @@ #![allow(unknown_lints)] -use crate::core::{TargetKind, Workspace}; -use crate::ops::CompileOptions; use anyhow::Error; -use cargo_util::ProcessError; use std::fmt; use std::path::PathBuf; @@ -198,91 +195,6 @@ impl<'a> ::std::iter::FusedIterator for ManifestCauses<'a> {} // ============================================================================= -// Cargo test errors. - -/// Error when testcases fail -#[derive(Debug)] -pub struct CargoTestError { - pub test: Test, - pub desc: String, - pub code: Option, - pub causes: Vec, -} - -impl fmt::Display for CargoTestError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.desc.fmt(f) - } -} - -impl std::error::Error for CargoTestError {} - -#[derive(Debug)] -pub enum Test { - Multiple, - Doc, - UnitTest { - kind: TargetKind, - name: String, - pkg_name: String, - }, -} - -impl CargoTestError { - pub fn new(test: Test, errors: Vec) -> Self { - if errors.is_empty() { - panic!("Cannot create CargoTestError from empty Vec") - } - let desc = errors - .iter() - .map(|error| error.desc.clone()) - .collect::>() - .join("\n"); - CargoTestError { - test, - desc, - code: errors[0].code, - causes: errors, - } - } - - pub fn hint(&self, ws: &Workspace<'_>, opts: &CompileOptions) -> String { - match self.test { - Test::UnitTest { - ref kind, - ref name, - ref pkg_name, - } => { - let pkg_info = if opts.spec.needs_spec_flag(ws) { - format!("-p {} ", pkg_name) - } else { - String::new() - }; - - match *kind { - TargetKind::Bench => { - format!("test failed, to rerun pass '{}--bench {}'", pkg_info, name) - } - TargetKind::Bin => { - format!("test failed, to rerun pass '{}--bin {}'", pkg_info, name) - } - TargetKind::Lib(_) => format!("test failed, to rerun pass '{}--lib'", pkg_info), - TargetKind::Test => { - format!("test failed, to rerun pass '{}--test {}'", pkg_info, name) - } - TargetKind::ExampleBin | TargetKind::ExampleLib(_) => { - format!("test failed, to rerun pass '{}--example {}", pkg_info, name) - } - _ => "test failed.".into(), - } - } - Test::Doc => "test failed, to rerun pass '--doc'".into(), - _ => "test failed.".into(), - } - } -} - -// ============================================================================= // CLI errors pub type CliResult = Result<(), CliError>; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/flock.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/flock.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/flock.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/flock.rs 2022-10-20 06:00:42.000000000 +0000 @@ -378,7 +378,6 @@ // For targets in which they are the same, the duplicate pattern causes a warning. #[allow(unreachable_patterns)] Some(libc::ENOTSUP | libc::EOPNOTSUPP) => true, - #[cfg(target_os = "linux")] Some(libc::ENOSYS) => true, _ => false, } diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -6,8 +6,8 @@ pub(crate) use self::counter::MetricsCounter; pub use self::dependency_queue::DependencyQueue; pub use self::diagnostic_server::RustfixDiagnosticServer; -pub use self::errors::{internal, CargoResult, CliResult, Test}; -pub use self::errors::{CargoTestError, CliError}; +pub use self::errors::CliError; +pub use self::errors::{internal, CargoResult, CliResult}; pub use self::flock::{FileLock, Filesystem}; pub use self::graph::Graph; pub use self::hasher::StableHasher; diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/progress.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/progress.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/progress.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/progress.rs 2022-10-20 06:00:42.000000000 +0000 @@ -15,6 +15,7 @@ pub enum ProgressStyle { Percentage, Ratio, + Indeterminate, } struct Throttle { @@ -253,6 +254,7 @@ let stats = match self.style { ProgressStyle::Percentage => format!(" {:6.02}%", pct * 100.0), ProgressStyle::Ratio => format!(" {}/{}", cur, max), + ProgressStyle::Indeterminate => String::new(), }; let extra_len = stats.len() + 2 /* [ and ] */ + 15 /* status header */; let display_width = match self.width().checked_sub(extra_len) { diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/rustc.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/rustc.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/rustc.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/rustc.rs 2022-10-20 06:00:42.000000000 +0000 @@ -93,18 +93,24 @@ /// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`. pub fn process(&self) -> ProcessBuilder { - ProcessBuilder::new(self.path.as_path()).wrapped(self.wrapper.as_ref()) + let mut cmd = ProcessBuilder::new(self.path.as_path()).wrapped(self.wrapper.as_ref()); + cmd.retry_with_argfile(true); + cmd } /// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`. pub fn workspace_process(&self) -> ProcessBuilder { - ProcessBuilder::new(self.path.as_path()) + let mut cmd = ProcessBuilder::new(self.path.as_path()) .wrapped(self.workspace_wrapper.as_ref()) - .wrapped(self.wrapper.as_ref()) + .wrapped(self.wrapper.as_ref()); + cmd.retry_with_argfile(true); + cmd } pub fn process_no_wrapper(&self) -> ProcessBuilder { - ProcessBuilder::new(&self.path) + let mut cmd = ProcessBuilder::new(&self.path); + cmd.retry_with_argfile(true); + cmd } /// Gets the output for the given command. @@ -231,10 +237,7 @@ } else { debug!("rustc info cache miss"); debug!("running {}", cmd); - let output = cmd - .build_command() - .output() - .with_context(|| format!("could not execute process {} (never executed)", cmd))?; + let output = cmd.output()?; let stdout = String::from_utf8(output.stdout) .map_err(|e| anyhow::anyhow!("{}: {:?}", e, e.as_bytes())) .with_context(|| format!("`{}` didn't return utf8 output", cmd))?; @@ -351,7 +354,7 @@ fn process_fingerprint(cmd: &ProcessBuilder, extra_fingerprint: u64) -> u64 { let mut hasher = StableHasher::new(); extra_fingerprint.hash(&mut hasher); - cmd.get_args().hash(&mut hasher); + cmd.get_args().for_each(|arg| arg.hash(&mut hasher)); let mut env = cmd.get_envs().iter().collect::>(); env.sort_unstable(); env.hash(&mut hasher); diff -Nru cargo-0.62.0ubuntu0libgit2/src/cargo/util/toml/mod.rs cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/toml/mod.rs --- cargo-0.62.0ubuntu0libgit2/src/cargo/util/toml/mod.rs 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/cargo/util/toml/mod.rs 2022-10-20 06:00:42.000000000 +0000 @@ -3,11 +3,12 @@ use std::marker::PhantomData; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::str; +use std::str::{self, FromStr}; use anyhow::{anyhow, bail, Context as _}; use cargo_platform::Platform; use cargo_util::paths; +use lazycell::LazyCell; use log::{debug, trace}; use semver::{self, VersionReq}; use serde::de; @@ -20,10 +21,10 @@ use crate::core::dependency::{Artifact, ArtifactTarget, DepKind}; use crate::core::manifest::{ManifestMetadata, TargetSourcePath, Warnings}; use crate::core::resolver::ResolveBehavior; -use crate::core::{Dependency, Manifest, PackageId, Summary, Target}; use crate::core::{ - Edition, EitherManifest, Feature, Features, InheritableFields, VirtualManifest, Workspace, + find_workspace_root, resolve_relative_path, Dependency, Manifest, PackageId, Summary, Target, }; +use crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest, Workspace}; use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig}; use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::util::errors::{CargoResult, ManifestError}; @@ -35,6 +36,9 @@ mod targets; use self::targets::targets; +pub use toml_edit::de::Error as TomlDeError; +pub use toml_edit::TomlError as TomlEditError; + /// Loads a `Cargo.toml` from a file on disk. /// /// This could result in a real or virtual manifest being returned. @@ -129,8 +133,9 @@ } if let TomlDependency::Workspace(_) = dep { bail!( - "`workspace.dependencies.{}` specified `{{ workspace = true }}`, but \ - workspace dependencies cannot do this", + "{} was specified as `workspace.dependencies.{}.workspace = true`, but \ + workspace dependencies cannot specify `workspace = true`", + name, name ); } @@ -224,7 +229,7 @@ /// In the simple format, only a version is specified, eg. /// `package = ""` Simple(String), - /// `package = { workspace = true }` + /// `package.workspace = true` Workspace(TomlWorkspaceDependency), /// The simple format is equivalent to a detailed dependency /// specifying only a version, eg. @@ -376,7 +381,7 @@ package: Option, public: Option, - /// One ore more of 'bin', 'cdylib', 'staticlib', 'bin:'. + /// One or more of `bin`, `cdylib`, `staticlib`, `bin:`. artifact: Option, /// If set, the artifact should also be a dependency lib: Option, @@ -650,6 +655,16 @@ } } + if let Some(StringOrBool::String(arg)) = &self.lto { + if arg == "true" || arg == "false" { + bail!( + "`lto` setting of string `\"{arg}\"` for `{name}` profile is not \ + a valid setting, must be a boolean (`true`/`false`) or a string \ + (`\"thin\"`/`\"fat\"`/`\"off\"`) or omitted.", + ); + } + } + Ok(()) } @@ -989,7 +1004,7 @@ deserializer.deserialize_any(Visitor) } -/// Enum that allows for the parsing of { workspace = true } in a Cargo.toml +/// Enum that allows for the parsing of `field.workspace = true` in a Cargo.toml /// /// It allows for things to be inherited from a workspace or defined as needed #[derive(Deserialize, Serialize, Clone, Debug)] @@ -1002,25 +1017,65 @@ impl MaybeWorkspace { fn resolve<'a>( self, - cargo_features: &Features, label: &str, get_ws_field: impl FnOnce() -> CargoResult, ) -> CargoResult { match self { MaybeWorkspace::Defined(value) => Ok(value), - MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => { - cargo_features.require(Feature::workspace_inheritance())?; - get_ws_field().context(format!( - "error inheriting `{}` from workspace root manifest's `workspace.{}`", + MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => get_ws_field() + .context(format!( + "error inheriting `{}` from workspace root manifest's `workspace.package.{}`", label, label - )) - } + )), MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!( "`workspace=false` is unsupported for `package.{}`", label, )), } } + fn as_defined(&self) -> Option<&T> { + match self { + MaybeWorkspace::Workspace(_) => None, + MaybeWorkspace::Defined(defined) => Some(defined), + } + } +} + +fn maybe_workspace_vec_string<'de, D>( + deserializer: D, +) -> Result>>, D::Error> +where + D: de::Deserializer<'de>, +{ + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = Option>>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("vector of strings") + } + + fn visit_seq(self, v: V) -> Result + where + V: de::SeqAccess<'de>, + { + let seq = de::value::SeqAccessDeserializer::new(v); + let defined = Vec::::deserialize(seq).map(MaybeWorkspace::Defined)?; + Ok(Some(defined)) + } + + fn visit_map(self, map: V) -> Result + where + V: de::MapAccess<'de>, + { + let mvd = de::value::MapAccessDeserializer::new(map); + let workspace = TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace)?; + Ok(Some(workspace)) + } + } + + deserializer.deserialize_any(Visitor) } #[derive(Deserialize, Serialize, Clone, Debug)] @@ -1038,10 +1093,12 @@ #[serde(rename_all = "kebab-case")] pub struct TomlProject { edition: Option>, - rust_version: Option, + rust_version: Option>, name: InternedString, #[serde(deserialize_with = "version_trim_whitespace")] version: MaybeWorkspace, + #[serde(default)] + #[serde(deserialize_with = "maybe_workspace_vec_string")] authors: Option>>, build: Option, metabuild: Option, @@ -1050,8 +1107,12 @@ #[serde(rename = "forced-target")] forced_target: Option, links: Option, - exclude: Option>, - include: Option>, + #[serde(default)] + #[serde(deserialize_with = "maybe_workspace_vec_string")] + exclude: Option>>, + #[serde(default)] + #[serde(deserialize_with = "maybe_workspace_vec_string")] + include: Option>>, publish: Option>, workspace: Option, im_a_teapot: Option, @@ -1065,11 +1126,15 @@ description: Option>, homepage: Option>, documentation: Option>, - readme: Option, + readme: Option>, + #[serde(default)] + #[serde(deserialize_with = "maybe_workspace_vec_string")] keywords: Option>>, + #[serde(default)] + #[serde(deserialize_with = "maybe_workspace_vec_string")] categories: Option>>, license: Option>, - license_file: Option, + license_file: Option>, repository: Option>, resolver: Option, @@ -1087,26 +1152,203 @@ resolver: Option, // Properties that can be inherited by members. + package: Option, + dependencies: Option>, + + // Note that this field must come last due to the way toml serialization + // works which requires tables to be emitted after all values. + metadata: Option, +} + +/// A group of fields that are inheritable by members of the workspace +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct InheritableFields { + // We use skip here since it will never be present when deserializing + // and we don't want it present when serializing + #[serde(skip)] dependencies: Option>, version: Option, authors: Option>, description: Option, + homepage: Option, documentation: Option, readme: Option, - homepage: Option, - repository: Option, + keywords: Option>, + categories: Option>, license: Option, #[serde(rename = "license-file")] license_file: Option, - keywords: Option>, - categories: Option>, + repository: Option, publish: Option, edition: Option, badges: Option>>, + exclude: Option>, + include: Option>, + #[serde(rename = "rust-version")] + rust_version: Option, + // We use skip here since it will never be present when deserializing + // and we don't want it present when serializing + #[serde(skip)] + ws_root: PathBuf, +} - // Note that this field must come last due to the way toml serialization - // works which requires tables to be emitted after all values. - metadata: Option, +impl InheritableFields { + pub fn update_deps(&mut self, deps: Option>) { + self.dependencies = deps; + } + + pub fn update_ws_path(&mut self, ws_root: PathBuf) { + self.ws_root = ws_root; + } + + pub fn dependencies(&self) -> CargoResult> { + self.dependencies.clone().map_or( + Err(anyhow!("`workspace.dependencies` was not defined")), + |d| Ok(d), + ) + } + + pub fn get_dependency(&self, name: &str) -> CargoResult { + self.dependencies.clone().map_or( + Err(anyhow!("`workspace.dependencies` was not defined")), + |deps| { + deps.get(name).map_or( + Err(anyhow!( + "`dependency.{}` was not found in `workspace.dependencies`", + name + )), + |dep| Ok(dep.clone()), + ) + }, + ) + } + + pub fn version(&self) -> CargoResult { + self.version.clone().map_or( + Err(anyhow!("`workspace.package.version` was not defined")), + |d| Ok(d), + ) + } + + pub fn authors(&self) -> CargoResult> { + self.authors.clone().map_or( + Err(anyhow!("`workspace.package.authors` was not defined")), + |d| Ok(d), + ) + } + + pub fn description(&self) -> CargoResult { + self.description.clone().map_or( + Err(anyhow!("`workspace.package.description` was not defined")), + |d| Ok(d), + ) + } + + pub fn homepage(&self) -> CargoResult { + self.homepage.clone().map_or( + Err(anyhow!("`workspace.package.homepage` was not defined")), + |d| Ok(d), + ) + } + + pub fn documentation(&self) -> CargoResult { + self.documentation.clone().map_or( + Err(anyhow!("`workspace.package.documentation` was not defined")), + |d| Ok(d), + ) + } + + pub fn readme(&self, package_root: &Path) -> CargoResult { + readme_for_project(self.ws_root.as_path(), self.readme.clone()).map_or( + Err(anyhow!("`workspace.package.readme` was not defined")), + |readme| { + let rel_path = + resolve_relative_path("readme", &self.ws_root, package_root, &readme)?; + Ok(StringOrBool::String(rel_path)) + }, + ) + } + + pub fn keywords(&self) -> CargoResult> { + self.keywords.clone().map_or( + Err(anyhow!("`workspace.package.keywords` was not defined")), + |d| Ok(d), + ) + } + + pub fn categories(&self) -> CargoResult> { + self.categories.clone().map_or( + Err(anyhow!("`workspace.package.categories` was not defined")), + |d| Ok(d), + ) + } + + pub fn license(&self) -> CargoResult { + self.license.clone().map_or( + Err(anyhow!("`workspace.package.license` was not defined")), + |d| Ok(d), + ) + } + + pub fn license_file(&self, package_root: &Path) -> CargoResult { + self.license_file.clone().map_or( + Err(anyhow!("`workspace.package.license_file` was not defined")), + |d| resolve_relative_path("license-file", &self.ws_root, package_root, &d), + ) + } + + pub fn repository(&self) -> CargoResult { + self.repository.clone().map_or( + Err(anyhow!("`workspace.package.repository` was not defined")), + |d| Ok(d), + ) + } + + pub fn publish(&self) -> CargoResult { + self.publish.clone().map_or( + Err(anyhow!("`workspace.package.publish` was not defined")), + |d| Ok(d), + ) + } + + pub fn edition(&self) -> CargoResult { + self.edition.clone().map_or( + Err(anyhow!("`workspace.package.edition` was not defined")), + |d| Ok(d), + ) + } + + pub fn rust_version(&self) -> CargoResult { + self.rust_version.clone().map_or( + Err(anyhow!("`workspace.package.rust-version` was not defined")), + |d| Ok(d), + ) + } + + pub fn badges(&self) -> CargoResult>> { + self.badges.clone().map_or( + Err(anyhow!("`workspace.package.badges` was not defined")), + |d| Ok(d), + ) + } + + pub fn exclude(&self) -> CargoResult> { + self.exclude.clone().map_or( + Err(anyhow!("`workspace.package.exclude` was not defined")), + |d| Ok(d), + ) + } + + pub fn include(&self) -> CargoResult> { + self.include.clone().map_or( + Err(anyhow!("`workspace.package.include` was not defined")), + |d| Ok(d), + ) + } + + pub fn ws_root(&self) -> &PathBuf { + &self.ws_root + } } impl TomlProject { @@ -1147,21 +1389,68 @@ .unwrap() .clone(); package.workspace = None; - package.resolver = ws.resolve_behavior().to_manifest(); + let current_resolver = package + .resolver + .as_ref() + .map(|r| ResolveBehavior::from_manifest(r)) + .unwrap_or_else(|| { + package + .edition + .as_ref() + .and_then(|e| e.as_defined()) + .map(|e| Edition::from_str(e)) + .unwrap_or(Ok(Edition::Edition2015)) + .map(|e| e.default_resolve_behavior()) + })?; + if ws.resolve_behavior() != current_resolver { + // This ensures the published crate if built as a root (e.g. `cargo install`) will + // use the same resolver behavior it was tested with in the workspace. + // To avoid forcing a higher MSRV we don't explicitly set this if it would implicitly + // result in the same thing. + package.resolver = Some(ws.resolve_behavior().to_manifest()); + } if let Some(license_file) = &package.license_file { + let license_file = license_file + .as_defined() + .context("license file should have been resolved before `prepare_for_publish()`")?; let license_path = Path::new(&license_file); let abs_license_path = paths::normalize_path(&package_root.join(license_path)); if abs_license_path.strip_prefix(package_root).is_err() { // This path points outside of the package root. `cargo package` // will copy it into the root, so adjust the path to this location. - package.license_file = Some( + package.license_file = Some(MaybeWorkspace::Defined( license_path .file_name() .unwrap() .to_str() .unwrap() .to_string(), - ); + )); + } + } + + if let Some(readme) = &package.readme { + let readme = readme + .as_defined() + .context("readme should have been resolved before `prepare_for_publish()`")?; + match readme { + StringOrBool::String(readme) => { + let readme_path = Path::new(&readme); + let abs_readme_path = paths::normalize_path(&package_root.join(readme_path)); + if abs_readme_path.strip_prefix(package_root).is_err() { + // This path points outside of the package root. `cargo package` + // will copy it into the root, so adjust the path to this location. + package.readme = Some(MaybeWorkspace::Defined(StringOrBool::String( + readme_path + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(), + ))); + } + } + StringOrBool::Bool(_) => {} } } let all = |_d: &TomlDependency| true; @@ -1283,13 +1572,30 @@ package_root: &Path, config: &Config, ) -> CargoResult<(Manifest, Vec)> { - // This is for later when we try to find the workspace root - fn get_ws(inheritable: Option<&InheritableFields>) -> CargoResult<&InheritableFields> { - match inheritable { - Some(inheritable) => Ok(inheritable), - None => Err(anyhow!( - "inheriting from a parent workspace is not implemented yet", - )), + fn get_ws( + config: &Config, + resolved_path: &Path, + workspace_config: &WorkspaceConfig, + ) -> CargoResult { + match workspace_config { + WorkspaceConfig::Root(root) => Ok(root.inheritable().clone()), + WorkspaceConfig::Member { + root: Some(ref path_to_root), + } => { + let path = resolved_path + .parent() + .unwrap() + .join(path_to_root) + .join("Cargo.toml"); + let root_path = paths::normalize_path(&path); + inheritable_from_path(config, root_path) + } + WorkspaceConfig::Member { root: None } => { + match find_workspace_root(&resolved_path, config)? { + Some(path_to_root) => inheritable_from_path(config, path_to_root), + None => Err(anyhow!("failed to find a workspace root")), + } + } } } @@ -1306,33 +1612,23 @@ let project = &mut project.ok_or_else(|| anyhow!("no `package` section found"))?; let workspace_config = match (me.workspace.as_ref(), project.workspace.as_ref()) { - (Some(config), None) => { - let inheritable = InheritableFields::new( - config.dependencies.clone(), - config.version.clone(), - config.authors.clone(), - config.description.clone(), - config.homepage.clone(), - config.documentation.clone(), - config.readme.clone(), - config.keywords.clone(), - config.categories.clone(), - config.license.clone(), - config.license_file.clone(), - config.repository.clone(), - config.publish.clone(), - config.edition.clone(), - config.badges.clone(), - ); - - WorkspaceConfig::Root(WorkspaceRootConfig::new( + (Some(toml_config), None) => { + let mut inheritable = toml_config.package.clone().unwrap_or_default(); + inheritable.update_ws_path(package_root.to_path_buf()); + inheritable.update_deps(toml_config.dependencies.clone()); + let ws_root_config = WorkspaceRootConfig::new( package_root, - &config.members, - &config.default_members, - &config.exclude, - &Some(inheritable.clone()), - &config.metadata, - )) + &toml_config.members, + &toml_config.default_members, + &toml_config.exclude, + &Some(inheritable), + &toml_config.metadata, + ); + config + .ws_roots + .borrow_mut() + .insert(package_root.to_path_buf(), ws_root_config.clone()); + WorkspaceConfig::Root(ws_root_config) } (None, root) => WorkspaceConfig::Member { root: root.cloned(), @@ -1343,8 +1639,6 @@ ), }; - let inheritable = workspace_config.inheritable(); - let package_name = project.name.trim(); if package_name.is_empty() { bail!("package name cannot be an empty string") @@ -1352,10 +1646,16 @@ validate_package_name(package_name, "package name", "")?; + let resolved_path = package_root.join("Cargo.toml"); + + let inherit_cell: LazyCell = LazyCell::new(); + let inherit = + || inherit_cell.try_borrow_with(|| get_ws(config, &resolved_path, &workspace_config)); + let version = project .version .clone() - .resolve(&features, "version", || get_ws(inheritable)?.version())?; + .resolve("version", || inherit()?.version())?; project.version = MaybeWorkspace::Defined(version.clone()); @@ -1363,7 +1663,7 @@ let edition = if let Some(edition) = project.edition.clone() { let edition: Edition = edition - .resolve(&features, "edition", || get_ws(inheritable)?.edition())? + .resolve("edition", || inherit()?.edition())? .parse() .with_context(|| "failed to parse the `edition` key")?; project.edition = Some(MaybeWorkspace::Defined(edition.to_string())); @@ -1386,7 +1686,10 @@ } let rust_version = if let Some(rust_version) = &project.rust_version { - let req = match semver::VersionReq::parse(rust_version) { + let rust_version = rust_version + .clone() + .resolve("rust_version", || inherit()?.rust_version())?; + let req = match semver::VersionReq::parse(&rust_version) { // Exclude semver operators like `^` and pre-release identifiers Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req, _ => bail!("`rust-version` must be a value like \"1.32\""), @@ -1476,21 +1779,26 @@ }; fn process_dependencies( - features: &Features, cx: &mut Context<'_, '_>, new_deps: Option<&BTreeMap>, kind: Option, - inheritable: Option<&InheritableFields>, + workspace_config: &WorkspaceConfig, + inherit_cell: &LazyCell, ) -> CargoResult>> { let dependencies = match new_deps { Some(dependencies) => dependencies, None => return Ok(None), }; + + let inherit = || { + inherit_cell.try_borrow_with(|| { + get_ws(cx.config, &cx.root.join("Cargo.toml"), &workspace_config) + }) + }; + let mut deps: BTreeMap = BTreeMap::new(); for (n, v) in dependencies.iter() { - let resolved = v - .clone() - .resolve(features, n, || get_ws(inheritable)?.get_dependency(n))?; + let resolved = v.clone().resolve(n, cx, || inherit())?; let dep = resolved.to_dependency(n, cx, kind)?; validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?; cx.deps.push(dep); @@ -1501,11 +1809,11 @@ // Collect the dependencies. let dependencies = process_dependencies( - &features, &mut cx, me.dependencies.as_ref(), None, - inheritable, + &workspace_config, + &inherit_cell, )?; if me.dev_dependencies.is_some() && me.dev_dependencies2.is_some() { warn_on_deprecated("dev-dependencies", package_name, "package", cx.warnings); @@ -1515,11 +1823,11 @@ .as_ref() .or_else(|| me.dev_dependencies2.as_ref()); let dev_deps = process_dependencies( - &features, &mut cx, dev_deps, Some(DepKind::Development), - inheritable, + &workspace_config, + &inherit_cell, )?; if me.build_dependencies.is_some() && me.build_dependencies2.is_some() { warn_on_deprecated("build-dependencies", package_name, "package", cx.warnings); @@ -1529,11 +1837,11 @@ .as_ref() .or_else(|| me.build_dependencies2.as_ref()); let build_deps = process_dependencies( - &features, &mut cx, build_deps, Some(DepKind::Build), - inheritable, + &workspace_config, + &inherit_cell, )?; let mut target: BTreeMap = BTreeMap::new(); @@ -1544,11 +1852,11 @@ Some(platform) }; let deps = process_dependencies( - &features, &mut cx, platform.dependencies.as_ref(), None, - inheritable, + &workspace_config, + &inherit_cell, ) .unwrap(); if platform.build_dependencies.is_some() && platform.build_dependencies2.is_some() { @@ -1559,11 +1867,11 @@ .as_ref() .or_else(|| platform.build_dependencies2.as_ref()); let build_deps = process_dependencies( - &features, &mut cx, build_deps, Some(DepKind::Build), - inheritable, + &workspace_config, + &inherit_cell, ) .unwrap(); if platform.dev_dependencies.is_some() && platform.dev_dependencies2.is_some() { @@ -1574,11 +1882,11 @@ .as_ref() .or_else(|| platform.dev_dependencies2.as_ref()); let dev_deps = process_dependencies( - &features, &mut cx, dev_deps, Some(DepKind::Development), - inheritable, + &workspace_config, + &inherit_cell, ) .unwrap(); target.insert( @@ -1617,8 +1925,18 @@ } } - let exclude = project.exclude.clone().unwrap_or_default(); - let include = project.include.clone().unwrap_or_default(); + let exclude = project + .exclude + .clone() + .map(|mw| mw.resolve("exclude", || inherit()?.exclude())) + .transpose()? + .unwrap_or_default(); + let include = project + .include + .clone() + .map(|mw| mw.resolve("include", || inherit()?.include())) + .transpose()? + .unwrap_or_default(); let empty_features = BTreeMap::new(); let summary = Summary::new( @@ -1633,68 +1951,63 @@ description: project .description .clone() - .map(|mw| { - mw.resolve(&features, "description", || { - get_ws(inheritable)?.description() - }) - }) + .map(|mw| mw.resolve("description", || inherit()?.description())) .transpose()?, homepage: project .homepage .clone() - .map(|mw| mw.resolve(&features, "homepage", || get_ws(inheritable)?.homepage())) + .map(|mw| mw.resolve("homepage", || inherit()?.homepage())) .transpose()?, documentation: project .documentation .clone() - .map(|mw| { - mw.resolve(&features, "documentation", || { - get_ws(inheritable)?.documentation() - }) - }) + .map(|mw| mw.resolve("documentation", || inherit()?.documentation())) .transpose()?, - readme: readme_for_project(package_root, project), + readme: readme_for_project( + package_root, + project + .readme + .clone() + .map(|mw| mw.resolve("readme", || inherit()?.readme(package_root))) + .transpose()?, + ), authors: project .authors .clone() - .map(|mw| mw.resolve(&features, "authors", || get_ws(inheritable)?.authors())) + .map(|mw| mw.resolve("authors", || inherit()?.authors())) .transpose()? .unwrap_or_default(), license: project .license .clone() - .map(|mw| mw.resolve(&features, "license", || get_ws(inheritable)?.license())) + .map(|mw| mw.resolve("license", || inherit()?.license())) + .transpose()?, + license_file: project + .license_file + .clone() + .map(|mw| mw.resolve("license", || inherit()?.license_file(package_root))) .transpose()?, - license_file: project.license_file.clone(), repository: project .repository .clone() - .map(|mw| { - mw.resolve(&features, "repository", || { - get_ws(inheritable)?.repository() - }) - }) + .map(|mw| mw.resolve("repository", || inherit()?.repository())) .transpose()?, keywords: project .keywords .clone() - .map(|mw| mw.resolve(&features, "keywords", || get_ws(inheritable)?.keywords())) + .map(|mw| mw.resolve("keywords", || inherit()?.keywords())) .transpose()? .unwrap_or_default(), categories: project .categories .clone() - .map(|mw| { - mw.resolve(&features, "categories", || { - get_ws(inheritable)?.categories() - }) - }) + .map(|mw| mw.resolve("categories", || inherit()?.categories())) .transpose()? .unwrap_or_default(), badges: me .badges .clone() - .map(|mw| mw.resolve(&features, "badges", || get_ws(inheritable)?.badges())) + .map(|mw| mw.resolve("badges", || inherit()?.badges())) .transpose()? .unwrap_or_default(), links: project.links.clone(), @@ -1711,6 +2024,10 @@ .documentation .clone() .map(|documentation| MaybeWorkspace::Defined(documentation)); + project.readme = metadata + .readme + .clone() + .map(|readme| MaybeWorkspace::Defined(StringOrBool::String(readme))); project.authors = project .authors .as_ref() @@ -1719,6 +2036,10 @@ .license .clone() .map(|license| MaybeWorkspace::Defined(license)); + project.license_file = metadata + .license_file + .clone() + .map(|license_file| MaybeWorkspace::Defined(license_file)); project.repository = metadata .repository .clone() @@ -1731,17 +2052,25 @@ .categories .as_ref() .map(|_| MaybeWorkspace::Defined(metadata.categories.clone())); + project.rust_version = rust_version.clone().map(|rv| MaybeWorkspace::Defined(rv)); + project.exclude = project + .exclude + .as_ref() + .map(|_| MaybeWorkspace::Defined(exclude.clone())); + project.include = project + .include + .as_ref() + .map(|_| MaybeWorkspace::Defined(include.clone())); let profiles = me.profile.clone(); if let Some(profiles) = &profiles { profiles.validate(&features, &mut warnings)?; } - let publish = project.publish.clone().map(|publish| { - publish - .resolve(&features, "publish", || get_ws(inheritable)?.publish()) - .unwrap() - }); + let publish = project + .publish + .clone() + .map(|publish| publish.resolve("publish", || inherit()?.publish()).unwrap()); project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p)); @@ -1933,32 +2262,23 @@ .map(|r| ResolveBehavior::from_manifest(r)) .transpose()?; let workspace_config = match me.workspace { - Some(ref config) => { - let inheritable = InheritableFields::new( - config.dependencies.clone(), - config.version.clone(), - config.authors.clone(), - config.description.clone(), - config.homepage.clone(), - config.documentation.clone(), - config.readme.clone(), - config.keywords.clone(), - config.categories.clone(), - config.license.clone(), - config.license_file.clone(), - config.repository.clone(), - config.publish.clone(), - config.edition.clone(), - config.badges.clone(), - ); - WorkspaceConfig::Root(WorkspaceRootConfig::new( + Some(ref toml_config) => { + let mut inheritable = toml_config.package.clone().unwrap_or_default(); + inheritable.update_ws_path(root.to_path_buf()); + inheritable.update_deps(toml_config.dependencies.clone()); + let ws_root_config = WorkspaceRootConfig::new( root, - &config.members, - &config.default_members, - &config.exclude, + &toml_config.members, + &toml_config.default_members, + &toml_config.exclude, &Some(inheritable), - &config.metadata, - )) + &toml_config.metadata, + ); + config + .ws_roots + .borrow_mut() + .insert(root.to_path_buf(), ws_root_config.clone()); + WorkspaceConfig::Root(ws_root_config) } None => { bail!("virtual manifests must be configured with [workspace]"); @@ -2073,9 +2393,39 @@ } } +fn inheritable_from_path( + config: &Config, + workspace_path: PathBuf, +) -> CargoResult { + // Workspace path should have Cargo.toml at the end + let workspace_path_root = workspace_path.parent().unwrap(); + + // Let the borrow exit scope so that it can be picked up if there is a need to + // read a manifest + if let Some(ws_root) = config.ws_roots.borrow().get(workspace_path_root) { + return Ok(ws_root.inheritable().clone()); + }; + + let source_id = SourceId::for_path(workspace_path_root)?; + let (man, _) = read_manifest(&workspace_path, source_id, config)?; + match man.workspace_config() { + WorkspaceConfig::Root(root) => { + config + .ws_roots + .borrow_mut() + .insert(workspace_path, root.clone()); + Ok(root.inheritable().clone()) + } + _ => bail!( + "root of a workspace inferred but wasn't a root: {}", + workspace_path.display() + ), + } +} + /// Returns the name of the README file for a `TomlProject`. -fn readme_for_project(package_root: &Path, project: &TomlProject) -> Option { - match &project.readme { +pub fn readme_for_project(package_root: &Path, readme: Option) -> Option { + match &readme { None => default_readme_from_package_root(package_root), Some(value) => match value { StringOrBool::Bool(false) => None, @@ -2175,13 +2525,15 @@ TomlDependency::Workspace(w) => w.optional.unwrap_or(false), } } +} +impl TomlDependency { fn resolve<'a>( self, - cargo_features: &Features, label: &str, - get_ws_dependency: impl FnOnce() -> CargoResult>, - ) -> CargoResult> { + cx: &mut Context<'_, '_>, + get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>, + ) -> CargoResult { match self { TomlDependency::Detailed(d) => Ok(TomlDependency::Detailed(d)), TomlDependency::Simple(s) => Ok(TomlDependency::Simple(s)), @@ -2190,18 +2542,30 @@ features, optional, }) => { - cargo_features.require(Feature::workspace_inheritance())?; - get_ws_dependency().context(format!( + let inheritable = get_inheritable()?; + inheritable.get_dependency(label).context(format!( "error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`", label, label )).map(|dep| { match dep { - TomlDependency::Simple(s) => TomlDependency::Simple(s), + TomlDependency::Simple(s) => { + if optional.is_some() || features.is_some() { + Ok(TomlDependency::Detailed(DetailedTomlDependency { + version: Some(s), + optional, + features, + ..Default::default() + })) + } else { + Ok(TomlDependency::Simple(s)) + } + }, TomlDependency::Detailed(d) => { let mut dep = d.clone(); dep.add_features(features); dep.update_optional(optional); - TomlDependency::Detailed(dep) + dep.resolve_path(label,inheritable.ws_root(), cx.root)?; + Ok(TomlDependency::Detailed(dep)) }, TomlDependency::Workspace(_) => { unreachable!( @@ -2212,7 +2576,7 @@ ) }, } - }) + })? } TomlDependency::Workspace(TomlWorkspaceDependency { workspace: false, .. @@ -2467,7 +2831,9 @@ } Ok(dep) } +} +impl DetailedTomlDependency { fn add_features(&mut self, features: Option>) { self.features = match (self.features.clone(), features.clone()) { (Some(dep_feat), Some(inherit_feat)) => Some( @@ -2485,6 +2851,23 @@ fn update_optional(&mut self, optional: Option) { self.optional = optional; } + + fn resolve_path( + &mut self, + name: &str, + root_path: &Path, + package_root: &Path, + ) -> CargoResult<()> { + if let Some(rel_path) = &self.path { + self.path = Some(resolve_relative_path( + name, + root_path, + package_root, + rel_path, + )?) + } + Ok(()) + } } #[derive(Default, Serialize, Deserialize, Debug, Clone)] diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/release.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/release.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/release.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/release.md 2022-10-20 06:00:42.000000000 +0000 @@ -28,6 +28,46 @@ [`dist` bootstrap module]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/dist.rs +## Submodule updates + +Cargo is tracked in the [rust-lang/rust] repository using a [git submodule]. +It is updated manually about once a week by a Cargo team member. +However, anyone is welcome to update it as needed. + +[@ehuss] has a tool called [subup](https://github.com/ehuss/subup) to automate the process of updating the submodule, updating the lockfile, running tests, and creating a PR. +Running the tests ahead-of-time helps avoid long cycle times waiting for bors if there are any errors. +Subup will also provide a message to include in the PR with a list of all PRs it covers. +Posting this in the PR message also helps create reference links on each Cargo PR to the submodule update PR to help track when it gets merged. + +The following is an example of the command to run in a local clone of rust-lang/rust to run a certain set of tests of things that are likely to get broken by a Cargo update: + +```bash +subup --up-branch update-cargo \ + --commit-message "Update cargo" \ + --test="src/tools/linkchecker tidy \ + src/tools/cargo \ + src/tools/rustfmt \ + src/tools/rls" \ + src/tools/cargo +``` + +If doing a [beta backport](#beta-backports), the command is similar, but needs to point to the correct branches: + +```bash +subup --up-branch update-beta-cargo \ + --rust-branch beta \ + --set-config rust.channel=beta \ + --commit-message "[beta] Update cargo" \ + --test="src/tools/linkchecker tidy \ + src/tools/cargo \ + src/tools/rustfmt \ + src/tools/rls" \ + rust-1.63.0:src/tools/cargo +``` + +[@ehuss]: https://github.com/ehuss/ +[git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules + ## Version updates Shortly after each major release, a Cargo team member will post a PR to update @@ -53,6 +93,23 @@ avoid churning incompatible version numbers. This process should be improved in the future! +[@ehuss] has a tool called [cargo-new-release] to automate the process of doing a version bump. +It runs through several steps: +1. Creates a branch +2. Updates the version numbers +3. Creates a changelog for anything on the master branch that is not part of beta +4. Creates a changelog for anything on the beta branch + +It opens a browser tab for every PR in order to review each change. +It places each PR in the changelog with its title, but usually every PR should be rewritten to explain the change from the user's perspective. +Each PR should also be categorized as an Addition, Change, Fix, or Nightly-only change. +Most PRs are deleted, since they are not relevant to users of Cargo. +For example, remove all PRs related to Cargo internals, infrastructure, documentation, error changes, refactorings, etc. +Usually about half of the PRs get removed. +This process usually takes @ehuss about an hour to finish. + +[@ehuss]: https://github.com/ehuss/ +[cargo-new-release]: https://github.com/ehuss/cargo-new-release [`crates/` directory]: https://github.com/rust-lang/cargo/tree/master/crates ## Docs publishing diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/unstable.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/unstable.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/unstable.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/unstable.md 2022-10-20 06:00:42.000000000 +0000 @@ -42,6 +42,32 @@ [tracking issue]: https://github.com/rust-lang/cargo/labels/C-tracking-issue [tracking issue template]: https://github.com/rust-lang/cargo/issues/new?labels=C-tracking-issue&template=tracking_issue.md +## Pre-Stabilization + +Once an unstable feature is "complete", the search for users to test +and give feedback begins. Testing notes should be written up to give users an +idea of how to test the new feature. An example being the +[workspace inheritance testing notes] for workspace inheritance. Once testing +notes have been written up you should make posts in various rust communities +([rust subreddit], [users], [internals], etc). Example posts made for workspace +inheritance: [reddit post], [users post], [internals post]. The unstable feature +should also be added to [This Week in Rust]. This should be done by adding the +label `call-for-testing` to the RFC for the feature and making a comment with a +link to the testing notes and the tracking issue (as needed). If there is not an +RFC, a pull request should be made to the [TWiR repo] adding the feature to the +`Call for Testing` section ([example]). + +[workspace inheritance testing notes]: https://github.com/rust-lang/cargo/blob/6d6dd9d9be9c91390da620adf43581619c2fa90e/src/doc/src/reference/unstable.md#testing-notes +[rust subreddit]: https://www.reddit.com/r/rust/ +[users]: https://users.rust-lang.org/ +[internals]: https://internals.rust-lang.org/ +[reddit post]: https://www.reddit.com/r/rust/comments/uo8zeh/help_test_workspace_inheritance_in_preparation/ +[users post]: https://users.rust-lang.org/t/help-test-workspace-inheritance-in-preparation-for-stablization/75582 +[internals post]: https://internals.rust-lang.org/t/help-test-workspace-inheritance-in-preparation-for-stablization/16618 +[This Week in Rust]: https://this-week-in-rust.org/ +[TWiR repo]: https://github.com/rust-lang/this-week-in-rust +[example]: https://github.com/rust-lang/this-week-in-rust/pull/3256 + ## Stabilization After some period of time, typically measured in months, the feature can be diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/working-on-cargo.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/working-on-cargo.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/process/working-on-cargo.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/process/working-on-cargo.md 2022-10-20 06:00:42.000000000 +0000 @@ -122,6 +122,21 @@ The reviewer might point out changes deemed necessary. Large or tricky changes may require several passes of review and changes. +### Status labeling + +PRs will get marked with [labels] like [`S-waiting-on-review`] or [`S-waiting-on-author`] to indicate their status. +The [`@rustbot`] bot can be used by anyone to adjust the labels. +If a PR gets marked as `S-waiting-on-author`, and you have pushed new changes that you would like to be reviewed, you can write a comment on the PR with the text `@rustbot ready`. +The bot will switch the labels on the PR. + +More information about these commands can be found at the [shortcuts documentation]. + +[labels]: https://github.com/rust-lang/cargo/labels +[`S-waiting-on-review`]: https://github.com/rust-lang/cargo/labels/S-waiting-on-review +[`S-waiting-on-author`]: https://github.com/rust-lang/cargo/labels/S-waiting-on-author +[`@rustbot`]: https://github.com/rustbot +[shortcuts documentation]: https://github.com/rust-lang/triagebot/wiki/Shortcuts + ## The merging process After a reviewer has approved your PR, they will issue a command to the [bors] diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/SUMMARY.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/SUMMARY.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/SUMMARY.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/SUMMARY.md 2022-10-20 06:00:42.000000000 +0000 @@ -17,4 +17,5 @@ - [Running Tests](./tests/running.md) - [Writing Tests](./tests/writing.md) - [Benchmarking and Profiling](./tests/profiling.md) + - [Crater](./tests/crater.md) - [Design Principles](./design.md) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/tests/crater.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/tests/crater.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/tests/crater.md 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/tests/crater.md 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,122 @@ +# Crater + +[Crater](https://github.com/rust-lang/crater) is a tool for compiling and running tests for _every_ crate on [crates.io](https://crates.io) (and a few on GitHub). +It is mainly used for checking the extent of breakage when implementing potentially breaking changes and ensuring lack of breakage by running beta vs stable compiler versions. + +Essentially it runs some `cargo` command on every crate twice; once against the "start" toolchain and again against the "end" toolchain. +For example, "start" could be the stable release, and "end" could be beta. +If it passes in "start" but fails with "end", then that is reported as a regression. + +There is a bot called [craterbot] which is used to run crater on hardware managed by the rust-lang organization. + +Crater is run by the release team during the beta cycle. +If there are any regressions that look like they are caused by Cargo, they should contact the Cargo team to decide how to handle it. + +## Running crater + +If you have a change that you want to test before the beta release, or you want to test behavior that is not normally exercised by crater, you can do a manual run of crater. +Roughly the steps are: + +1. Create a branch with your changes. + + In your clone of cargo, make the changes to incorporate whatever new thing you want to test and push it to a branch on your fork on GitHub. + +2. Get a clone of + +3. Create a branch in your rust-lang/rust clone to add your changes. + +4. Change the `src/tools/cargo` submodule to point to your new branch. + + Modify `.gitmodules` to point to your clone and branch of cargo with the changes you want to test. + For example: + + ```bash + git submodule set-url src/tools/cargo https://github.com/ehuss/cargo.git + git submodule set-branch --branch my-awesome-feature src/tools/cargo + git submodule update --remote src/tools/cargo + git add .gitmodules src/tools/cargo + git commit + ``` + +5. Create an PR on rust-lang/rust. + + Push your submodule changes to GitHub and make a PR. + Start the PR title with `[EXPERIMENT]` to make it clear what the PR is for and assign yourself or @ghost. + +6. Make a "try" build. + + A "try" build creates a full release of x86_64-unknown-linux-gnu and stores it on rust-lang servers. + This can be done with a comment `@bors try` on the PR (all Cargo team members should have permission to do this). + +7. Run crater. + + Look at the [craterbot] docs to determine the command that you want to run. + There are different modes like `check-only`, `build-and-test`, `rustdoc`, etc. + + You can also choose how many crates to run against. + If you are uncertain if your cargo changes will work correctly, it might be a good idea to run against `top-100` first to check its behavior. + This will run much faster. + You can do a full run afterwards. + + After the try build finishes (which should take a couple hours), ask someone to make a crater run. + The Cargo team does not have that permission, so just ask someone on Zulip. + They will need to write a comment to `@craterbot` with the command that you have specified. + +8. Wait. + + Crater can take anywhere from a few hours to a few weeks to run depending on how long the [craterbot queue](https://crater.rust-lang.org/) is and which mode you picked and the priority of your job. + When the crater run finishes, craterbot will post a comment to the PR with a link to a report of the results. + +9. Investigate the report. + + Look through the report which contains links to build logs for any regressions or errors. + +10. Close the PR. + + Whenever you are done doing crater runs, close your PR. + +[craterbot]: https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md + + +## Advanced crater modes + +Crater only has a few built-in modes, such as running `cargo check` or `cargo test`. +You can pass extra flags with `+cargoflags`. + +More complex tests can be accomplished by customizing Cargo to perform whatever actions you want. +Since crater essentially runs `cargo check`, you can modify the `check` command to perform whichever actions you want. +For example, to test `cargo fix --edition`, [this commit](https://github.com/ehuss/cargo/commit/6901690a6f8d519efb4fabf48c1c2b94af0c3bd8) intercepted `cargo check` and modified it to instead: + +1. Only run on crates with the 2018 edition. +2. Run `cargo fix --edition`. +3. Modify the manifest to switch to the 2021 edition. +4. Run `cargo check` to verify. + +If you need to compare the before and after of a command that is not part of crater's built-in modes, that can be more difficult. +Two possible options: + +* Work with the infra team to add a new mode. +* Build two custom try builds. + Each one should modify the `cargo check` command as described above. + The "start" build should perform whichever action you want with an otherwise unmodified cargo. + The "end" build should perform whichever action you want with your modified cargo. + Then, in the `@craterbot` command, specify the start and end hashes of the two try builds. + +## Limitations + +There are some limitations of crater to consider when running Cargo: + +* A crater run without regressions is not a green light to move forward. + * A large portion of Rust code is not tested, such as closed-source projects or things otherwise not collected by crater. + * Many crates can't build in crater's environment or are otherwise broken. + * Some crates have flaky tests. +* Crater runs in an isolated environment. + * It only runs on Linux x86-64. + * It does not have network access. + * The crate source is in a read-only mount. +* Crater does several steps before running the test (using its own copy of the stable toolchain): + * It generates a lockfile using `generate-lockfile` and includes `-Zno-index-update` to prevent index updates (which makes it run much faster). + * All dependencies are downloaded ahead-of-time with `cargo fetch`. +* The built-in modes pass several flags to cargo such as `--frozen` or `--message-format=json`. + It will sometimes use `--all-targets` and sometimes not. + Check the [crater source](https://github.com/rust-lang/crater/blob/master/src/runner/test.rs) for more details on how it works. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/tests/writing.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/tests/writing.md --- cargo-0.62.0ubuntu0libgit2/src/doc/contrib/src/tests/writing.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/contrib/src/tests/writing.md 2022-10-20 06:00:42.000000000 +0000 @@ -6,96 +6,114 @@ ## Testsuite Cargo has a wide variety of integration tests that execute the `cargo` binary -and verify its behavior, located in the [`testsuite`] directory. The -[`support`] crate contains many helpers to make this process easy. +and verify its behavior, located in the [`testsuite`] directory. The +[`support`] crate and [`snapbox`] contain many helpers to make this process easy. + +There are two styles of tests that can roughly be categorized as +- functional tests + - The fixture is programmatically defined + - The assertions are regular string comparisons + - Easier to share in an issue as a code block is completely self-contained + - More resilient to insignificant changes though ui tests are easy to update when a change does occur +- ui tests + - The fixture is file-based + - The assertions use file-backed snapshots that can be updated with an env variable + - Easier to review the expected behavior of the command as more details are included + - Easier to get up and running from an existing project + - Easier to reason about as everything is just files in the repo These tests typically work by creating a temporary "project" with a `Cargo.toml` file, executing the `cargo` binary process, and checking the stdout and stderr output against the expected output. -### `cargo_test` attribute - -Cargo's tests use the `#[cargo_test]` attribute instead of `#[test]`. This -attribute injects some code which does some setup before starting the test, -creating the little "sandbox" described below. - -### Basic test structure - -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: +### Functional Tests +Generally, a functional test will be placed in `tests/testsuite/.rs` and will look roughly like: ```rust,ignore -let p = project() - .file("src/main.rs", r#"fn main() { println!("hi!"); }"#) - .build(); +#[cargo_test] +fn () { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hi!"); }"#) + .build(); + + p.cargo("run --bin foo") + .with_stderr( + "\ + [COMPILING] foo [..] + [FINISHED] [..] + [RUNNING] `target/debug/foo` + ", + ) + .with_stdout("hi!") + .run(); + } +} ``` -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 -as a home directory instead of your normal home directory. +The [`#[cargo_test]` attribute](#cargo_test-attribute) is used in place of `#[test]` to inject some setup code. -If you do not specify a `Cargo.toml` manifest using `file()`, one is -automatically created with a project name of `foo` using `basic_manifest()`. +[`ProjectBuilder`] via `project()`: +- Each project is in a separate directory in the sandbox +- If you do not specify a `Cargo.toml` manifest using `file()`, one is + automatically created with a project name of `foo` using `basic_manifest()`. + +[`Execs`] via `p.cargo(...)`: +- This executes the command and evaluates different assertions + - See [`support::compare`] for an explanation of the string pattern matching. + Patterns are used to make it easier to match against the expected output. + +#### `#[cargo_test]` attribute + +The `#[cargo_test]` attribute injects code which does some setup before starting the test. +It will create a filesystem "sandbox" under the "cargo integration test" directory for each test, such as `/path/to/cargo/target/tmp/cit/t123/`. +The sandbox will contain a `home` directory that will be used instead of your normal home directory. -To run Cargo, call the `cargo` method and make assertions on the execution: +The `#[cargo_test]` attribute takes several options that will affect how the test is generated. +They are listed in parentheses separated with commas, such as: ```rust,ignore -p.cargo("run --bin foo") - .with_stderr( - "\ -[COMPILING] foo [..] -[FINISHED] [..] -[RUNNING] `target/debug/foo` -", - ) - .with_stdout("hi!") - .run(); +#[cargo_test(nightly, reason = "-Zfoo is unstable")] ``` -This uses the [`Execs`] struct to build up a command to execute, along with -the expected output. +The options it supports are: -See [`support::compare`] for an explanation of the string pattern matching. -Patterns are used to make it easier to match against the expected output. +* `nightly` — This will cause the test to be ignored if not running on the nightly toolchain. + This is useful for tests that use unstable options in `rustc` or `rustdoc`. + These tests are run in Cargo's CI, but are disabled in rust-lang/rust's CI due to the difficulty of updating both repos simultaneously. + A `reason` field is required to explain why it is nightly-only. +* `build_std_real` — This is a "real" `-Zbuild-std` test (in the `build_std` integration test). + This only runs on nightly, and only if the environment variable `CARGO_RUN_BUILD_STD_TESTS` is set (these tests on run on Linux). +* `build_std_mock` — This is a "mock" `-Zbuild-std` test (which uses a mock standard library). + This only runs on nightly, and is disabled for windows-gnu. +* `requires_` — This indicates a command that is required to be installed to be run. + For example, `requires_rustfmt` means the test will only run if the executable `rustfmt` is installed. + These tests are *always* run on CI. + This is mainly used to avoid requiring contributors from having every dependency installed. +* `>=1.64` — This indicates that the test will only run with the given version of `rustc` or newer. + This can be used when a new `rustc` feature has been stabilized that the test depends on. + If this is specified, a `reason` is required to explain why it is being checked. -Browse the `pub` functions and modules in the [`support`] crate for a variety -of other helpful utilities. - -### Testing Nightly Features +#### Testing Nightly Features If you are testing a Cargo feature that only works on "nightly" Cargo, then -you need to call `masquerade_as_nightly_cargo` on the process builder like -this: +you need to call `masquerade_as_nightly_cargo` on the process builder and pass +the name of the feature as the reason, like this: ```rust,ignore -p.cargo("build").masquerade_as_nightly_cargo() +p.cargo("build").masquerade_as_nightly_cargo(&["print-im-a-teapot"]) ``` If you are testing a feature that only works on *nightly rustc* (such as -benchmarks), then you should exit the test if it is not running with nightly -rust, like this: +benchmarks), then you should use the `nightly` option of the `cargo_test` +attribute, like this: ```rust,ignore -if !is_nightly() { - // Add a comment here explaining why this is necessary. - return; -} +#[cargo_test(nightly, reason = "-Zfoo is unstable")] ``` -### Platform-specific Notes +This will cause the test to be ignored if not running on the nightly toolchain. -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 -Windows will fail with errors like "directory not empty" or "failed to remove" -or "access is denied". - -### Specifying Dependencies +#### Specifying Dependencies You should not write any tests that use the network such as contacting crates.io. Typically, simple path dependencies are the easiest way to add a @@ -123,6 +141,109 @@ If you need to test git dependencies, see [`support::git`] to create a git dependency. +### UI Tests + +UI Tests are a bit more spread out and generally look like: + +`tests/testsuite//mod.rs`: +```rust,ignore +mod ; +``` + +`tests/testsuite///mod.rs`: +```rust,ignore +use cargo_test_support::prelude::*; +use cargo_test_support::compare::assert_ui; +use cargo_test_support::Project; +use cargo_test_support::curr_dir; + +#[cargo_test] +fn () { + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("run") + .arg_line("--bin foo") + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path(curr_dir!().join("stdout.log")) + .stderr_matches_path(curr_dir!().join("stderr.log")); + + assert_ui().subset_matches(curr_dir!().join("out"), &project_root); +} +``` + +Then populate +- `tests/testsuite///in` with the project's directory structure +- `tests/testsuite///out` with the files you want verified +- `tests/testsuite///stdout.log` with nothing +- `tests/testsuite///stderr.log` with nothing + +`#[cargo_test]`: +- This is used in place of `#[test]` +- This attribute injects code which does some setup before starting the + test, creating a filesystem "sandbox" under the "cargo integration test" + directory for each test such as + `/path/to/cargo/target/cit/t123/` +- The sandbox will contain a `home` directory that will be used instead of your normal home directory + +`Project`: +- The project is copied from a directory in the repo +- Each project is in a separate directory in the sandbox + +[`Command`] via `Command::cargo_ui()`: +- Set up and run a command. + +[`OutputAssert`] via `Command::assert()`: +- Perform assertions on the result of the [`Command`] + +[`Assert`] via `assert_ui()`: +- Verify the command modified the file system as expected + +#### Updating Snapshots + +The project, stdout, and stderr snapshots can be updated by running with the +`SNAPSHOTS=overwrite` environment variable, like: +```console +$ SNAPSHOTS=overwrite cargo test +``` + +Be sure to check the snapshots to make sure they make sense. + +#### Testing Nightly Features + +If you are testing a Cargo feature that only works on "nightly" Cargo, then +you need to call `masquerade_as_nightly_cargo` on the process builder and pass +the name of the feature as the reason, like this: + +```rust,ignore + snapbox::cmd::Command::cargo() + .masquerade_as_nightly_cargo(&["print-im-a-teapot"]) +``` + +If you are testing a feature that only works on *nightly rustc* (such as +benchmarks), then you should use the `nightly` option of the `cargo_test` +attribute, like this: + +```rust,ignore +#[cargo_test(nightly, reason = "-Zfoo is unstable")] +``` + +This will cause the test to be ignored if not running on the nightly toolchain. + +### Platform-specific Notes + +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 +Windows will fail with errors like "directory not empty" or "failed to remove" +or "access is denied". + ## Debugging tests In some cases, you may need to dig into a test that is not working as you @@ -152,10 +273,14 @@ 3. Run with arguments: `r check` [`testsuite`]: https://github.com/rust-lang/cargo/tree/master/tests/testsuite/ -[`ProjectBuilder`]: https://github.com/rust-lang/cargo/blob/e4b65bdc80f2a293447f2f6a808fa7c84bf9a357/crates/cargo-test-support/src/lib.rs#L225-L231 -[`Execs`]: https://github.com/rust-lang/cargo/blob/e4b65bdc80f2a293447f2f6a808fa7c84bf9a357/crates/cargo-test-support/src/lib.rs#L558-L579 +[`ProjectBuilder`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/lib.rs#L196-L202 +[`Execs`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/lib.rs#L531-L550 [`support`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/lib.rs [`support::compare`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/compare.rs -[`support::registry::Package`]: https://github.com/rust-lang/cargo/blob/e4b65bdc80f2a293447f2f6a808fa7c84bf9a357/crates/cargo-test-support/src/registry.rs#L73-L149 +[`support::registry::Package`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/registry.rs#L311-L389 [`support::git`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/git.rs [Running Cargo]: ../process/working-on-cargo.md#running-cargo +[`snapbox`]: https://docs.rs/snapbox/latest/snapbox/ +[`Command`]: https://docs.rs/snapbox/latest/snapbox/cmd/struct.Command.html +[`OutputAssert`]: https://docs.rs/snapbox/latest/snapbox/cmd/struct.OutputAssert.html +[`Assert`]: https://docs.rs/snapbox/latest/snapbox/struct.Assert.html diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-add.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-add.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-add.md 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-add.md 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,162 @@ +# cargo-add(1) +{{*set actionverb="Add"}} +{{*set nouns="adds"}} + +## NAME + +cargo-add - Add dependencies to a Cargo.toml manifest file + +## SYNOPSIS + +`cargo add` [_options_] _crate_...\ +`cargo add` [_options_] `--path` _path_\ +`cargo add` [_options_] `--git` _url_ [_crate_...]\ + + +## DESCRIPTION + +This command can add or modify dependencies. + +The source for the dependency can be specified with: + +* _crate_`@`_version_: Fetch from a registry with a version constraint of "_version_" +* `--path` _path_: Fetch from the specified _path_ +* `--git` _url_: Pull from a git repo at _url_ + +If no source is specified, then a best effort will be made to select one, including: + +* Existing dependencies in other tables (like `dev-dependencies`) +* Workspace members +* Latest release in the registry + +When you add a package that is already present, the existing entry will be updated with the flags specified. + +Upon successful invocation, the enabled (`+`) and disabled (`-`) [features] of the specified +dependency will be listed in the command's output. + +[features]: ../reference/features.md + +## OPTIONS + +### Source options + +{{#options}} + +{{#option "`--git` _url_" }} +[Git URL to add the specified crate from](../reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories). +{{/option}} + +{{#option "`--branch` _branch_" }} +Branch to use when adding from git. +{{/option}} + +{{#option "`--tag` _tag_" }} +Tag to use when adding from git. +{{/option}} + +{{#option "`--rev` _sha_" }} +Specific commit to use when adding from git. +{{/option}} + +{{#option "`--path` _path_" }} +[Filesystem path](../reference/specifying-dependencies.html#specifying-path-dependencies) to local crate to add. +{{/option}} + +{{> options-registry }} + +{{/options}} + +### Section options + +{{#options}} + +{{#option "`--dev`" }} +Add as a [development dependency](../reference/specifying-dependencies.html#development-dependencies). +{{/option}} + +{{#option "`--build`" }} +Add as a [build dependency](../reference/specifying-dependencies.html#build-dependencies). +{{/option}} + +{{#option "`--target` _target_" }} +Add as a dependency to the [given target platform](../reference/specifying-dependencies.html#platform-specific-dependencies). +{{/option}} + +{{/options}} + + + + +### Dependency options + +{{#options}} + +{{#option "`--rename` _name_" }} +[Rename](../reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml) the dependency. +{{/option}} + +{{#option "`--optional`" }} +Mark the dependency as [optional](../reference/features.html#optional-dependencies). +{{/option}} + +{{#option "`--no-optional`" }} +Mark the dependency as [required](../reference/features.html#optional-dependencies). +{{/option}} + +{{#option "`--no-default-features`" }} +Disable the [default features](../reference/features.html#dependency-features). +{{/option}} + +{{#option "`--default-features`" }} +Re-enable the [default features](../reference/features.html#dependency-features). +{{/option}} + +{{#option "`--features` _features_" }} +Space or comma separated list of [features to +activate](../reference/features.html#dependency-features). When adding multiple +crates, the features for a specific crate may be enabled with +`package-name/feature-name` syntax. This flag may be specified multiple times, +which enables all specified features. +{{/option}} + +{{/options}} + + +### Display Options + +{{#options}} +{{> options-display }} +{{/options}} + +### Manifest Options + +{{#options}} +{{> options-manifest-path }} +{{/options}} + +{{> section-options-common }} + +{{> section-environment }} + +{{> section-exit-status }} + +## EXAMPLES + +1. Add `regex` as a dependency + + cargo add regex + +2. Add `trybuild` as a dev-dependency + + cargo add --dev trybuild + +3. Add an older version of `nom` as a dependency + + cargo add nom@5 + +4. Add support for serializing data structures to json with `derive`s + + cargo add serde serde_json -F serde/derive + +## SEE ALSO +{{man "cargo" 1}} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-bench.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-bench.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-bench.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-bench.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-bench(1) {{*set actionverb="Benchmark"}} {{*set nouns="benchmarks"}} +{{*set multitarget=true}} ## NAME @@ -28,10 +29,11 @@ cargo bench -- foo --exact -Benchmarks are built with the `--test` option to `rustc` which creates an -executable with a `main` function that automatically runs all functions -annotated with the `#[bench]` attribute. Cargo passes the `--bench` flag to -the test harness to tell it to run only benchmarks. +Benchmarks are built with the `--test` option to `rustc` which creates a +special executable by linking your code with libtest. The executable +automatically runs all functions annotated with the `#[bench]` attribute. +Cargo passes the `--bench` flag to the test harness to tell it to run +only benchmarks. The libtest harness may be disabled by setting `harness = false` in the target manifest settings, in which case your code will need to provide its own `main` @@ -81,6 +83,8 @@ target by name ignore the `bench` flag and will always benchmark the given target. +{{> options-targets-bin-auto-built }} + {{> options-targets }} {{> section-features }} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-build.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-build.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-build.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-build.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-build(1) {{*set actionverb="Build"}} +{{*set multitarget=true}} ## NAME @@ -23,6 +24,8 @@ binary and library targets of the selected packages. Binaries are skipped if they have `required-features` that are missing. +{{> options-targets-bin-auto-built }} + {{> options-targets }} {{> section-features }} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-check.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-check.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-check.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-check.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-check(1) {{*set actionverb="Check"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-clean.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-clean.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-clean.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-clean.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-clean(1) {{*set actionverb="Clean"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-doc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-doc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-doc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-doc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-doc(1) {{*set actionverb="Document"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-fetch.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-fetch.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-fetch.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-fetch.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-fetch(1) {{*set actionverb="Fetch"}} {{*set target-default-to-all-arch=true}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-fix.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-fix.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-fix.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-fix.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-fix(1) {{*set actionverb="Fix"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-install.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-install.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-install.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-install.md 2022-10-20 06:00:42.000000000 +0000 @@ -8,7 +8,7 @@ ## SYNOPSIS -`cargo install` [_options_] _crate_...\ +`cargo install` [_options_] _crate_[@_version_]...\ `cargo install` [_options_] `--path` _path_\ `cargo install` [_options_] `--git` _url_ [_crate_...]\ `cargo install` [_options_] `--list` diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-package.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-package.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-package.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-package.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-package(1) {{*set actionverb="Package"}} {{*set noall=true}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-pkgid.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-pkgid.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-pkgid.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-pkgid.md 2022-10-20 06:00:42.000000000 +0000 @@ -27,11 +27,11 @@ SPEC Structure | Example SPEC ---------------------------|-------------- _name_ | `bitflags` -_name_`:`_version_ | `bitflags:1.0.4` +_name_`@`_version_ | `bitflags@1.0.4` _url_ | `https://github.com/rust-lang/cargo` _url_`#`_version_ | `https://github.com/rust-lang/cargo#0.33.0` _url_`#`_name_ | `https://github.com/rust-lang/crates.io-index#bitflags` -_url_`#`_name_`:`_version_ | `https://github.com/rust-lang/cargo#crates-io:0.21.0` +_url_`#`_name_`:`_version_ | `https://github.com/rust-lang/cargo#crates-io@0.21.0` ## OPTIONS @@ -75,7 +75,7 @@ 2. Retrieve package specification for version 1.0.0 of `foo`: - cargo pkgid foo:1.0.0 + cargo pkgid foo@1.0.0 3. Retrieve package specification for `foo` from crates.io: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-publish.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-publish.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-publish.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-publish.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-publish(1) {{*set actionverb="Publish"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-rustc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-rustc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-rustc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-rustc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-rustc(1) {{*set actionverb="Build"}} +{{*set multitarget=true}} ## NAME @@ -35,6 +36,8 @@ When no target selection options are given, `cargo rustc` will build all binary and library targets of the selected package. +{{> options-targets-bin-auto-built }} + {{> options-targets }} {{> section-features }} @@ -68,6 +71,19 @@ {{> options-timings }} +{{#option "`--crate-type` _crate-type_"}} +Build for the given crate type. This flag accepts a comma-separated list of +1 or more crate types, of which the allowed values are the same as `crate-type` +field in the manifest for configurating a Cargo target. See +[`crate-type` field](../reference/cargo-targets.html#the-crate-type-field) +for possible values. + +If the manifest contains a list, and `--crate-type` is provided, +the command-line argument value will override what is in the manifest. + +This flag only works when building a `lib` or `example` library target. +{{/option}} + {{/options}} ### Output Options @@ -121,5 +137,9 @@ cargo rustc --lib -- -Z print-type-sizes +3. Override `crate-type` field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + ## SEE ALSO {{man "cargo" 1}}, {{man "cargo-build" 1}}, {{man "rustc" 1}} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-rustdoc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-rustdoc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-rustdoc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-rustdoc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,6 @@ # cargo-rustdoc(1) {{*set actionverb="Document"}} +{{*set multitarget=true}} ## NAME diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-test.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-test.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-test.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-test.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-test(1) {{*set actionverb="Test"}} {{*set nouns="tests"}} +{{*set multitarget=true}} ## NAME @@ -12,7 +13,7 @@ ## DESCRIPTION -Compile and execute unit and integration tests. +Compile and execute unit, integration, and documentation tests. 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 @@ -27,20 +28,34 @@ cargo test foo -- --test-threads 3 -Tests are built with the `--test` option to `rustc` which creates an -executable with a `main` function that automatically runs all functions -annotated with the `#[test]` attribute in multiple threads. `#[bench]` -annotated functions will also be run with one iteration to verify that they -are functional. +Tests are built with the `--test` option to `rustc` which creates a special +executable by linking your code with libtest. The executable automatically +runs all functions annotated with the `#[test]` attribute in multiple threads. +`#[bench]` annotated functions will also be run with one iteration to verify +that they are functional. + +If the package contains multiple test targets, each target compiles to a +special executable as aforementioned, and then is run serially. The libtest harness may be disabled by setting `harness = false` in the target manifest settings, in which case your code will need to provide its own `main` function to handle running tests. +### Documentation tests + Documentation tests are also run by default, which is handled by `rustdoc`. It -extracts code samples from documentation comments and executes them. See the -[rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information on -writing doc tests. +extracts code samples from documentation comments of the library target, and +then executes them. + +Different from normal test targets, each code block compiles to a doctest +executable on the fly with `rustc`. These executables run in parallel in +separate processes. The compilation of a code block is in fact a part of test +function controlled by libtest, so some options such as `--jobs` might not +take effect. Note that this execution model of doctests is not guaranteed +and may change in the future; beware of depending on it. + +See the [rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information +on writing doc tests. ## OPTIONS @@ -73,13 +88,7 @@ Doc tests for libraries may be disabled by setting `doctest = false` for the library in the manifest. -Binary targets are automatically built if there is an integration test or -benchmark. This allows an integration test to execute the binary to exercise -and test its behavior. The `CARGO_BIN_EXE_` -[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) -is set when the integration test is built so that it can use the -[`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the -executable. +{{> options-targets-bin-auto-built }} {{> options-targets }} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-yank.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-yank.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/cargo-yank.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/cargo-yank.md 2022-10-20 06:00:42.000000000 +0000 @@ -6,7 +6,8 @@ ## SYNOPSIS -`cargo yank` [_options_] `--vers` _version_ [_crate_] +`cargo yank` [_options_] _crate_@_version_\ +`cargo yank` [_options_] `--version` _version_ [_crate_] ## DESCRIPTION @@ -30,7 +31,7 @@ {{#options}} -{{#option "`--vers` _version_" }} +{{#option "`--vers` _version_" "`--version` _version_" }} The version to yank or un-yank. {{/option}} @@ -64,7 +65,7 @@ 1. Yank a crate from the index: - cargo yank --vers 1.0.7 foo + cargo yank foo@1.0.7 ## SEE ALSO {{man "cargo" 1}}, {{man "cargo-login" 1}}, {{man "cargo-publish" 1}} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-add.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-add.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-add.txt 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-add.txt 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,192 @@ +CARGO-ADD(1) + +NAME + cargo-add - Add dependencies to a Cargo.toml manifest file + +SYNOPSIS + cargo add [options] crate... + cargo add [options] --path path + cargo add [options] --git url [crate...] + +DESCRIPTION + This command can add or modify dependencies. + + The source for the dependency can be specified with: + + o crate@version: Fetch from a registry with a version constraint of + "version" + + o --path path: Fetch from the specified path + + o --git url: Pull from a git repo at url + + If no source is specified, then a best effort will be made to select + one, including: + + o Existing dependencies in other tables (like dev-dependencies) + + o Workspace members + + o Latest release in the registry + + When you add a package that is already present, the existing entry will + be updated with the flags specified. + + Upon successful invocation, the enabled (+) and disabled (-) features + of the specified + dependency will be listed in the command's output. + +OPTIONS + Source options + --git url + Git URL to add the specified crate from + . + + --branch branch + Branch to use when adding from git. + + --tag tag + Tag to use when adding from git. + + --rev sha + Specific commit to use when adding from git. + + --path path + Filesystem path + + to local crate to add. + + --registry registry + Name of the registry to use. Registry names are defined in Cargo + config files + . If not + specified, the default registry is used, which is defined by the + registry.default config key which defaults to crates-io. + + Section options + --dev + Add as a development dependency + . + + --build + Add as a build dependency + . + + --target target + Add as a dependency to the given target platform + . + + + + Dependency options + --rename name + Rename + + the dependency. + + --optional + Mark the dependency as optional + . + + --no-optional + Mark the dependency as required + . + + --no-default-features + Disable the default features + . + + --default-features + Re-enable the default features + . + + --features features + Space or comma separated list of features to activate + . + When adding multiple crates, the features for a specific crate may + be enabled with package-name/feature-name syntax. This flag may be + specified multiple times, which enables all specified features. + + Display Options + -v, --verbose + Use verbose output. May be specified twice for "very verbose" output + which includes extra output such as dependency warnings and build + script output. May also be specified with the term.verbose config + value . + + -q, --quiet + Do not print cargo log messages. May also be specified with the + term.quiet config value + . + + --color when + Control when colored output is used. Valid values: + + o auto (default): Automatically detect if color support is + available on the terminal. + + o always: Always display colors. + + o never: Never display colors. + + May also be specified with the term.color config value + . + + Manifest Options + --manifest-path path + Path to the Cargo.toml file. By default, Cargo searches for the + Cargo.toml file in the current directory or any parent directory. + + Common Options + +toolchain + If Cargo has been installed with rustup, and the first argument to + cargo begins with +, it will be interpreted as a rustup toolchain + name (such as +stable or +nightly). See the rustup documentation + for more + information about how toolchain overrides work. + + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + + -h, --help + Prints help information. + + -Z flag + Unstable (nightly-only) flags to Cargo. Run cargo -Z help for + details. + +ENVIRONMENT + See the reference + + for details on environment variables that Cargo reads. + +EXIT STATUS + o 0: Cargo succeeded. + + o 101: Cargo failed to complete. + +EXAMPLES + 1. Add regex as a dependency + + cargo add regex + + 2. Add trybuild as a dev-dependency + + cargo add --dev trybuild + + 3. Add an older version of nom as a dependency + + cargo add nom@5 + + 4. Add support for serializing data structures to json with derives + + cargo add serde serde_json -F serde/derive + +SEE ALSO + cargo(1) + diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-bench.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-bench.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-bench.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-bench.txt 2022-10-20 06:00:42.000000000 +0000 @@ -23,10 +23,11 @@ cargo bench -- foo --exact - Benchmarks are built with the --test option to rustc which creates an - executable with a main function that automatically runs all functions - annotated with the #[bench] attribute. Cargo passes the --bench flag to - the test harness to tell it to run only benchmarks. + Benchmarks are built with the --test option to rustc which creates a + special executable by linking your code with libtest. The executable + automatically runs all functions annotated with the #[bench] attribute. + Cargo passes the --bench flag to the test harness to tell it to run only + benchmarks. The libtest harness may be disabled by setting harness = false in the target manifest settings, in which case your code will need to provide @@ -117,6 +118,15 @@ options that take a target by name ignore the bench flag and will always benchmark the given target. + Binary targets are automatically built if there is an integration test + or benchmark being selected to benchmark. This allows an integration + test to execute the binary to exercise and test its behavior. The + CARGO_BIN_EXE_ environment variable + + is set when the integration test is built so that it can use the env + macro to locate the + executable. + Passing target selection flags will benchmark only the specified targets. @@ -181,7 +191,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -198,7 +208,8 @@ Benchmark for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -227,12 +238,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -299,7 +311,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -343,6 +355,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -359,7 +379,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-build.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-build.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-build.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-build.txt 2022-10-20 06:00:42.000000000 +0000 @@ -51,6 +51,15 @@ binary and library targets of the selected packages. Binaries are skipped if they have required-features that are missing. + Binary targets are automatically built if there is an integration test + or benchmark being selected to build. This allows an integration test to + execute the binary to exercise and test its behavior. The + CARGO_BIN_EXE_ environment variable + + is set when the integration test is built so that it can use the env + macro to locate the + executable. + Passing target selection flags will build only the specified targets. Note that --bin, --example, --test and --bench flags also support common @@ -114,7 +123,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -131,7 +140,8 @@ Build for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -164,12 +174,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -239,7 +250,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -293,6 +304,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -305,7 +324,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-check.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-check.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-check.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-check.txt 2022-10-20 06:00:42.000000000 +0000 @@ -120,7 +120,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -137,7 +137,8 @@ Check for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -177,12 +178,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -243,7 +245,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -287,6 +289,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -299,7 +309,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-clean.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-clean.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-clean.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-clean.txt 2022-10-20 06:00:42.000000000 +0000 @@ -43,7 +43,8 @@ Clean for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -118,6 +119,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-doc.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-doc.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-doc.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-doc.txt 2022-10-20 06:00:42.000000000 +0000 @@ -98,7 +98,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -115,7 +115,8 @@ Document for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -148,12 +149,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -214,7 +216,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -258,6 +260,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -270,7 +280,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-fetch.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-fetch.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-fetch.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-fetch.txt 2022-10-20 06:00:42.000000000 +0000 @@ -28,7 +28,8 @@ Fetch for the given architecture. The default is all architectures. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -103,6 +104,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-fix.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-fix.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-fix.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-fix.txt 2022-10-20 06:00:42.000000000 +0000 @@ -193,7 +193,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -210,7 +210,8 @@ Fix for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -250,12 +251,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -316,7 +318,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -360,6 +362,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -372,7 +382,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-generate-lockfile.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-generate-lockfile.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-generate-lockfile.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-generate-lockfile.txt 2022-10-20 06:00:42.000000000 +0000 @@ -79,6 +79,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-init.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-init.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-init.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-init.txt 2022-10-20 06:00:42.000000000 +0000 @@ -87,6 +87,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-install.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-install.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-install.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-install.txt 2022-10-20 06:00:42.000000000 +0000 @@ -4,7 +4,7 @@ cargo-install - Build and install a Rust binary SYNOPSIS - cargo install [options] crate... + cargo install [options] crate[@version]... cargo install [options] --path path cargo install [options] --git url [crate...] cargo install [options] --list @@ -157,7 +157,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -213,12 +213,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -255,7 +256,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather @@ -310,7 +313,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -323,6 +326,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-locate-project.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-locate-project.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-locate-project.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-locate-project.txt 2022-10-20 06:00:42.000000000 +0000 @@ -62,6 +62,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-login.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-login.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-login.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-login.txt 2022-10-20 06:00:42.000000000 +0000 @@ -62,6 +62,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-metadata.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-metadata.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-metadata.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-metadata.txt 2022-10-20 06:00:42.000000000 +0000 @@ -315,7 +315,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -391,6 +391,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-new.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-new.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-new.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-new.txt 2022-10-20 06:00:42.000000000 +0000 @@ -82,6 +82,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-owner.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-owner.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-owner.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-owner.txt 2022-10-20 06:00:42.000000000 +0000 @@ -89,6 +89,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-package.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-package.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-package.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-package.txt 2022-10-20 06:00:42.000000000 +0000 @@ -112,7 +112,8 @@ Package for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -139,7 +140,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -187,7 +188,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather @@ -227,6 +230,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-pkgid.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-pkgid.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-pkgid.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-pkgid.txt 2022-10-20 06:00:42.000000000 +0000 @@ -26,7 +26,7 @@ +-----------------+--------------------------------------------------+ | name | bitflags | +-----------------+--------------------------------------------------+ - | name:version | bitflags:1.0.4 | + | name@version | bitflags@1.0.4 | +-----------------+--------------------------------------------------+ | url | https://github.com/rust-lang/cargo | +-----------------+--------------------------------------------------+ @@ -36,7 +36,7 @@ | | https://github.com/rust-lang/crates.io-index#bitflags | +-----------------+--------------------------------------------------+ | | | - | url#name:version | https://github.com/rust-lang/cargo#crates-io:0.21.0 | + | url#name:version | https://github.com/rust-lang/cargo#crates-io@0.21.0 | +-----------------+--------------------------------------------------+ OPTIONS @@ -109,6 +109,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -133,7 +141,7 @@ 2. Retrieve package specification for version 1.0.0 of foo: - cargo pkgid foo:1.0.0 + cargo pkgid foo@1.0.0 3. Retrieve package specification for foo from crates.io: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-publish.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-publish.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-publish.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-publish.txt 2022-10-20 06:00:42.000000000 +0000 @@ -79,7 +79,8 @@ Publish for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -106,7 +107,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -154,7 +155,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather @@ -194,6 +197,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-run.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-run.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-run.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-run.txt 2022-10-20 06:00:42.000000000 +0000 @@ -43,7 +43,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -93,12 +93,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -159,7 +160,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -203,6 +204,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -215,7 +224,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-rustc.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-rustc.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-rustc.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-rustc.txt 2022-10-20 06:00:42.000000000 +0000 @@ -42,6 +42,15 @@ When no target selection options are given, cargo rustc will build all binary and library targets of the selected package. + Binary targets are automatically built if there is an integration test + or benchmark being selected to build. This allows an integration test to + execute the binary to exercise and test its behavior. The + CARGO_BIN_EXE_ environment variable + + is set when the integration test is built so that it can use the env + macro to locate the + executable. + Passing target selection flags will build only the specified targets. Note that --bin, --example, --test and --bench flags also support common @@ -105,7 +114,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -122,7 +131,8 @@ Build for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -172,16 +182,30 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. + --crate-type crate-type + Build for the given crate type. This flag accepts a comma-separated + list of 1 or more crate types, of which the allowed values are the + same as crate-type field in the manifest for configurating a Cargo + target. See crate-type field + + for possible values. + + If the manifest contains a list, and --crate-type is provided, the + command-line argument value will override what is in the manifest. + + This flag only works when building a lib or example library target. + Output Options --target-dir directory Directory for all generated artifacts and intermediate files. May @@ -238,7 +262,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -282,6 +306,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -294,7 +326,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather @@ -327,6 +361,10 @@ cargo rustc --lib -- -Z print-type-sizes + 3. Override crate-type field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + SEE ALSO cargo(1), cargo-build(1), rustc(1) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-rustdoc.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-rustdoc.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-rustdoc.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-rustdoc.txt 2022-10-20 06:00:42.000000000 +0000 @@ -114,7 +114,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -131,7 +131,8 @@ Document for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -164,12 +165,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -230,7 +232,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -274,6 +276,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -286,7 +296,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-search.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-search.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-search.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-search.txt 2022-10-20 06:00:42.000000000 +0000 @@ -59,6 +59,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-test.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-test.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-test.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-test.txt 2022-10-20 06:00:42.000000000 +0000 @@ -7,7 +7,7 @@ cargo test [options] [testname] [-- test-options] DESCRIPTION - Compile and execute unit and integration tests. + Compile and execute unit, integration, and documentation tests. The test filtering argument TESTNAME and all the arguments following the two dashes (--) are passed to the test binaries and thus to libtest @@ -23,20 +23,34 @@ cargo test foo -- --test-threads 3 - Tests are built with the --test option to rustc which creates an - executable with a main function that automatically runs all functions - annotated with the #[test] attribute in multiple threads. #[bench] - annotated functions will also be run with one iteration to verify that - they are functional. + Tests are built with the --test option to rustc which creates a special + executable by linking your code with libtest. The executable + automatically runs all functions annotated with the #[test] attribute in + multiple threads. #[bench] annotated functions will also be run with one + iteration to verify that they are functional. + + If the package contains multiple test targets, each target compiles to a + special executable as aforementioned, and then is run serially. The libtest harness may be disabled by setting harness = false in the target manifest settings, in which case your code will need to provide its own main function to handle running tests. + Documentation tests Documentation tests are also run by default, which is handled by - rustdoc. It extracts code samples from documentation comments and - executes them. See the rustdoc book - for more information on writing doc tests. + rustdoc. It extracts code samples from documentation comments of the + library target, and then executes them. + + Different from normal test targets, each code block compiles to a + doctest executable on the fly with rustc. These executables run in + parallel in separate processes. The compilation of a code block is in + fact a part of test function controlled by libtest, so some options such + as --jobs might not take effect. Note that this execution model of + doctests is not guaranteed and may change in the future; beware of + depending on it. + + See the rustdoc book for more + information on writing doc tests. OPTIONS Test Options @@ -116,9 +130,9 @@ the library in the manifest. Binary targets are automatically built if there is an integration test - or benchmark. This allows an integration test to execute the binary to - exercise and test its behavior. The CARGO_BIN_EXE_ environment - variable + or benchmark being selected to test. This allows an integration test to + execute the binary to exercise and test its behavior. The + CARGO_BIN_EXE_ environment variable is set when the integration test is built so that it can use the env macro to locate the @@ -191,7 +205,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -208,7 +222,8 @@ Test for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -241,12 +256,13 @@ (rather than the default) is unstable and requires -Zunstable-options. Valid output formats: - o html: Write a human-readable file cargo-timing.html to the - target/cargo-timings directory with a report of the compilation. - Also write a report to the same directory with a timestamp in the - filename if you want to look at older runs. HTML output is - suitable for human consumption only, and does not provide - machine-readable timing data. + o html (unstable, requires -Zunstable-options): Write a + human-readable file cargo-timing.html to the target/cargo-timings + directory with a report of the compilation. Also write a report + to the same directory with a timestamp in the filename if you + want to look at older runs. HTML output is suitable for human + consumption only, and does not provide machine-readable timing + data. o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. @@ -313,7 +329,7 @@ rustc's default color scheme. Cannot be used with human or short. o json-render-diagnostics: Instruct Cargo to not include rustc - diagnostics in in JSON messages printed, but instead Cargo itself + diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short. @@ -357,6 +373,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -375,7 +399,9 @@ Number of parallel jobs to run. May also be specified with the build.jobs config value . Defaults to - the number of CPUs. + the number of logical CPUs. If negative, it sets the maximum number + of parallel jobs to the number of logical CPUs plus provided value. + Should not be 0. --keep-going Build as many crates in the dependency graph as possible, rather diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-tree.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-tree.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-tree.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-tree.txt 2022-10-20 06:00:42.000000000 +0000 @@ -224,7 +224,7 @@ for more details. - --features features + -F features, --features features Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may be specified multiple times, which enables all @@ -269,6 +269,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo.txt 2022-10-20 06:00:42.000000000 +0000 @@ -188,6 +188,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-uninstall.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-uninstall.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-uninstall.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-uninstall.txt 2022-10-20 06:00:42.000000000 +0000 @@ -71,6 +71,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-update.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-update.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-update.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-update.txt 2022-10-20 06:00:42.000000000 +0000 @@ -109,6 +109,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-vendor.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-vendor.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-vendor.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-vendor.txt 2022-10-20 06:00:42.000000000 +0000 @@ -105,6 +105,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-verify-project.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-verify-project.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-verify-project.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-verify-project.txt 2022-10-20 06:00:42.000000000 +0000 @@ -82,6 +82,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-yank.txt cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-yank.txt --- cargo-0.62.0ubuntu0libgit2/src/doc/man/generated_txt/cargo-yank.txt 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/generated_txt/cargo-yank.txt 2022-10-20 06:00:42.000000000 +0000 @@ -4,7 +4,8 @@ cargo-yank - Remove a pushed crate from the index SYNOPSIS - cargo yank [options] --vers version [crate] + cargo yank [options] crate@version + cargo yank [options] --version version [crate] DESCRIPTION The yank command removes a previously published crate's version from the @@ -23,7 +24,7 @@ OPTIONS Yank Options - --vers version + --vers version, --version version The version to yank or un-yank. --undo @@ -84,6 +85,14 @@ for more information about how toolchain overrides work. + --config KEY=VALUE or PATH + Overrides a Cargo configuration value. The argument should be in + TOML syntax of KEY=VALUE, or provided as a path to an extra + configuration file. This flag may be specified multiple times. See + the command-line overrides section + + for more information. + -h, --help Prints help information. @@ -104,7 +113,7 @@ EXAMPLES 1. Yank a crate from the index: - cargo yank --vers 1.0.7 foo + cargo yank foo@1.0.7 SEE ALSO cargo(1), cargo-login(1), cargo-publish(1) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-jobs.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-jobs.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-jobs.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-jobs.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,5 +1,7 @@ {{#option "`-j` _N_" "`--jobs` _N_"}} Number of parallel jobs to run. May also be specified with the `build.jobs` [config value](../reference/config.html). Defaults to -the number of CPUs. +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0. {{/option}} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-message-format.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-message-format.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-message-format.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-message-format.md 2022-10-20 06:00:42.000000000 +0000 @@ -14,7 +14,7 @@ - `json-diagnostic-rendered-ansi`: Ensure the `rendered` field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with `human` or `short`. -- `json-render-diagnostics`: Instruct Cargo to not include rustc diagnostics in +- `json-render-diagnostics`: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with `human` or `short`. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-targets-bin-auto-built.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-targets-bin-auto-built.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-targets-bin-auto-built.md 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-targets-bin-auto-built.md 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,8 @@ +Binary targets are automatically built if there is an integration test or +benchmark being selected to {{lower actionverb}}. This allows an integration +test to execute the binary to exercise and test its behavior. +The `CARGO_BIN_EXE_` +[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) +is set when the integration test is built so that it can use the +[`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the +executable. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-target-triple.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-target-triple.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-target-triple.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-target-triple.md 2022-10-20 06:00:42.000000000 +0000 @@ -5,6 +5,7 @@ {{~/if}} The general format of the triple is `---`. Run `rustc --print target-list` for a list of supported targets. +{{~#if multitarget }} This flag may be specified multiple times. {{~/if}} This may also be specified with the `build.target` [config value](../reference/config.html). diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-timings.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-timings.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/options-timings.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/options-timings.md 2022-10-20 06:00:42.000000000 +0000 @@ -5,7 +5,7 @@ Specifying an output format (rather than the default) is unstable and requires `-Zunstable-options`. Valid output formats: -- `html`: Write a human-readable file `cargo-timing.html` to the +- `html` (unstable, requires `-Zunstable-options`): Write a human-readable file `cargo-timing.html` to the `target/cargo-timings` directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/section-features.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/section-features.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/section-features.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/section-features.md 2022-10-20 06:00:42.000000000 +0000 @@ -9,7 +9,7 @@ {{#options}} -{{#option "`--features` _features_" }} +{{#option "`-F` _features_" "`--features` _features_" }} Space or comma separated list of features to activate. Features of workspace members may be enabled with `package-name/feature-name` syntax. This flag may be specified multiple times, which enables all specified features. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/section-options-common.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/section-options-common.md --- cargo-0.62.0ubuntu0libgit2/src/doc/man/includes/section-options-common.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/man/includes/section-options-common.md 2022-10-20 06:00:42.000000000 +0000 @@ -10,6 +10,12 @@ for more information about how toolchain overrides work. {{/option}} +{{#option "`--config` _KEY=VALUE_ or _PATH_"}} +Overrides a Cargo configuration value. The argument should be in TOML syntax of `KEY=VALUE`, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the [command-line overrides section](../reference/config.html#command-line-overrides) for more information. +{{/option}} + {{#option "`-h`" "`--help`"}} Prints help information. {{/option}} diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-add.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-add.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-add.md 1970-01-01 00:00:00.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-add.md 2022-10-20 06:00:42.000000000 +0000 @@ -0,0 +1,234 @@ +# cargo-add(1) + + + +## NAME + +cargo-add - Add dependencies to a Cargo.toml manifest file + +## SYNOPSIS + +`cargo add` [_options_] _crate_...\ +`cargo add` [_options_] `--path` _path_\ +`cargo add` [_options_] `--git` _url_ [_crate_...]\ + + +## DESCRIPTION + +This command can add or modify dependencies. + +The source for the dependency can be specified with: + +* _crate_`@`_version_: Fetch from a registry with a version constraint of "_version_" +* `--path` _path_: Fetch from the specified _path_ +* `--git` _url_: Pull from a git repo at _url_ + +If no source is specified, then a best effort will be made to select one, including: + +* Existing dependencies in other tables (like `dev-dependencies`) +* Workspace members +* Latest release in the registry + +When you add a package that is already present, the existing entry will be updated with the flags specified. + +Upon successful invocation, the enabled (`+`) and disabled (`-`) [features] of the specified +dependency will be listed in the command's output. + +[features]: ../reference/features.md + +## OPTIONS + +### Source options + +
+ +
--git url
+
Git URL to add the specified crate from.
+ + +
--branch branch
+
Branch to use when adding from git.
+ + +
--tag tag
+
Tag to use when adding from git.
+ + +
--rev sha
+
Specific commit to use when adding from git.
+ + +
--path path
+
Filesystem path to local crate to add.
+ + +
--registry registry
+
Name of the registry to use. Registry names are defined in Cargo config +files. If not specified, the default registry is used, +which is defined by the registry.default config key which defaults to +crates-io.
+ + + +
+ +### Section options + +
+ +
--dev
+
Add as a development dependency.
+ + +
--build
+
Add as a build dependency.
+ + +
--target target
+
Add as a dependency to the given target platform.
+ + +
+ + + + +### Dependency options + +
+ +
--rename name
+
Rename the dependency.
+ + +
--optional
+
Mark the dependency as optional.
+ + +
--no-optional
+
Mark the dependency as required.
+ + +
--no-default-features
+
Disable the default features.
+ + +
--default-features
+
Re-enable the default features.
+ + +
--features features
+
Space or comma separated list of features to +activate. When adding multiple +crates, the features for a specific crate may be enabled with +package-name/feature-name syntax. This flag may be specified multiple times, +which enables all specified features.
+ + +
+ + +### Display Options + +
+
-v
+
--verbose
+
Use verbose output. May be specified twice for "very verbose" output which +includes extra output such as dependency warnings and build script output. +May also be specified with the term.verbose +config value.
+ + +
-q
+
--quiet
+
Do not print cargo log messages. +May also be specified with the term.quiet +config value.
+ + +
--color when
+
Control when colored output is used. Valid values:

+
    +
  • auto (default): Automatically detect if color support is available on the +terminal.
  • +
  • always: Always display colors.
  • +
  • never: Never display colors.
  • +
+

May also be specified with the term.color +config value.

+ + +
+ +### Manifest Options + +
+
--manifest-path path
+
Path to the Cargo.toml file. By default, Cargo searches for the +Cargo.toml file in the current directory or any parent directory.
+ + +
+ +### Common Options + +
+ +
+toolchain
+
If Cargo has been installed with rustup, and the first argument to cargo +begins with +, it will be interpreted as a rustup toolchain name (such +as +stable or +nightly). +See the rustup documentation +for more information about how toolchain overrides work.
+ + +
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ + +
-h
+
--help
+
Prints help information.
+ + +
-Z flag
+
Unstable (nightly-only) flags to Cargo. Run cargo -Z help for details.
+ + +
+ + +## ENVIRONMENT + +See [the reference](../reference/environment-variables.html) for +details on environment variables that Cargo reads. + + +## EXIT STATUS + +* `0`: Cargo succeeded. +* `101`: Cargo failed to complete. + + +## EXAMPLES + +1. Add `regex` as a dependency + + cargo add regex + +2. Add `trybuild` as a dev-dependency + + cargo add --dev trybuild + +3. Add an older version of `nom` as a dependency + + cargo add nom@5 + +4. Add support for serializing data structures to json with `derive`s + + cargo add serde serde_json -F serde/derive + +## SEE ALSO +[cargo(1)](cargo.html) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-bench.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-bench.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-bench.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-bench.md 2022-10-20 06:00:42.000000000 +0000 @@ -2,6 +2,7 @@ + ## NAME cargo-bench - Execute benchmarks of a package @@ -28,10 +29,11 @@ cargo bench -- foo --exact -Benchmarks are built with the `--test` option to `rustc` which creates an -executable with a `main` function that automatically runs all functions -annotated with the `#[bench]` attribute. Cargo passes the `--bench` flag to -the test harness to tell it to run only benchmarks. +Benchmarks are built with the `--test` option to `rustc` which creates a +special executable by linking your code with libtest. The executable +automatically runs all functions annotated with the `#[bench]` attribute. +Cargo passes the `--bench` flag to the test harness to tell it to run +only benchmarks. The libtest harness may be disabled by setting `harness = false` in the target manifest settings, in which case your code will need to provide its own `main` @@ -138,6 +140,16 @@ target by name ignore the `bench` flag and will always benchmark the given target. +Binary targets are automatically built if there is an integration test or +benchmark being selected to benchmark. This allows an integration +test to execute the binary to exercise and test its behavior. +The `CARGO_BIN_EXE_` +[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) +is set when the integration test is built so that it can use the +[`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the +executable. + + Passing target selection flags will benchmark only the specified targets. @@ -219,6 +231,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -243,7 +256,7 @@
--target triple
Benchmark for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -271,7 +284,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -351,7 +364,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -408,6 +421,12 @@ for more information about how toolchain overrides work.
+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
@@ -431,7 +450,9 @@
--jobs N
Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
+the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-build.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-build.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-build.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-build.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-build(1) + ## NAME cargo-build - Compile the current package @@ -66,6 +67,16 @@ binary and library targets of the selected packages. Binaries are skipped if they have `required-features` that are missing. +Binary targets are automatically built if there is an integration test or +benchmark being selected to build. This allows an integration +test to execute the binary to exercise and test its behavior. +The `CARGO_BIN_EXE_` +[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) +is set when the integration test is built so that it can use the +[`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the +executable. + + Passing target selection flags will build only the specified targets. @@ -147,6 +158,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -171,7 +183,7 @@
--target triple
Build for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -206,7 +218,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -288,7 +300,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -353,6 +365,12 @@ for more information about how toolchain overrides work.
+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
@@ -372,7 +390,9 @@
--jobs N
Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
+the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-check.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-check.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-check.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-check.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-check(1) + ## NAME cargo-check - Check the current package @@ -152,6 +153,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -176,7 +178,7 @@
--target triple
Check for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -215,7 +217,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -288,7 +290,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -344,6 +346,12 @@ for more information about how toolchain overrides work.
+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
@@ -363,7 +371,9 @@
--jobs N
Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
+the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-clean.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-clean.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-clean.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-clean.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-clean(1) + ## NAME cargo-clean - Remove generated artifacts @@ -59,7 +60,7 @@
--target triple
Clean for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -149,6 +150,12 @@ for more information about how toolchain overrides work.

+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-doc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-doc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-doc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-doc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-doc(1) + ## NAME cargo-doc - Build a package's documentation @@ -130,6 +131,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -154,7 +156,7 @@
--target triple
Document for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -189,7 +191,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -262,7 +264,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -318,6 +320,12 @@ for more information about how toolchain overrides work.
+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
@@ -337,7 +345,9 @@
--jobs N
Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
+the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-fetch.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-fetch.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-fetch.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-fetch.md 2022-10-20 06:00:42.000000000 +0000 @@ -2,6 +2,7 @@ + ## NAME cargo-fetch - Fetch dependencies of a package from the network @@ -34,7 +35,7 @@
--target triple
Fetch for the given architecture. The default is all architectures. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -123,6 +124,12 @@ for more information about how toolchain overrides work.

+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-fix.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-fix.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-fix.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-fix.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-fix(1) + ## NAME cargo-fix - Automatically fix lint warnings reported by rustc @@ -232,6 +233,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -256,7 +258,7 @@
--target triple
Fix for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -295,7 +297,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -368,7 +370,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -424,6 +426,12 @@ for more information about how toolchain overrides work.
+
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
@@ -443,7 +451,9 @@
--jobs N
Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
+the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-generate-lockfile.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-generate-lockfile.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-generate-lockfile.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-generate-lockfile.md 2022-10-20 06:00:42.000000000 +0000 @@ -98,6 +98,12 @@ for more information about how toolchain overrides work. +
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-init.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-init.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-init.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-init.md 2022-10-20 06:00:42.000000000 +0000 @@ -111,6 +111,12 @@ for more information about how toolchain overrides work. +
--config KEY=VALUE or PATH
+
Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
+ +
-h
--help
Prints help information.
diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-install.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-install.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-install.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-install.md 2022-10-20 06:00:42.000000000 +0000 @@ -8,7 +8,7 @@ ## SYNOPSIS -`cargo install` [_options_] _crate_...\ +`cargo install` [_options_] _crate_[@_version_]...\ `cargo install` [_options_] `--path` _path_\ `cargo install` [_options_] `--git` _url_ [_crate_...]\ `cargo install` [_options_] `--list` @@ -179,6 +179,7 @@
+
-F features
--features features
Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -242,7 +243,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

    -
  • html: Write a human-readable file cargo-timing.html to the +
  • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -292,7 +293,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
--keep-going
@@ -350,7 +353,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -372,6 +375,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-locate-project.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-locate-project.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-locate-project.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-locate-project.md 2022-10-20 06:00:42.000000000 +0000 @@ -87,6 +87,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-login.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-login.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-login.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-login.md 2022-10-20 06:00:42.000000000 +0000 @@ -79,6 +79,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo.md 2022-10-20 06:00:42.000000000 +0000 @@ -221,6 +221,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-metadata.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-metadata.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-metadata.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-metadata.md 2022-10-20 06:00:42.000000000 +0000 @@ -330,6 +330,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -426,6 +427,12 @@ for more information about how toolchain overrides work.
    +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-new.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-new.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-new.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-new.md 2022-10-20 06:00:42.000000000 +0000 @@ -106,6 +106,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-owner.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-owner.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-owner.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-owner.md 2022-10-20 06:00:42.000000000 +0000 @@ -117,6 +117,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-package.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-package.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-package.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-package.md 2022-10-20 06:00:42.000000000 +0000 @@ -2,6 +2,7 @@ + ## NAME cargo-package - Assemble the local package into a distributable tarball @@ -133,7 +134,7 @@
    --target triple
    Package for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

    +list of supported targets. This flag may be specified multiple times.

    This may also be specified with the build.target config value.

    Note that specifying this flag makes Cargo run in a different mode where the @@ -163,6 +164,7 @@

    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -224,7 +226,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    @@ -279,6 +283,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-pkgid.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-pkgid.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-pkgid.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-pkgid.md 2022-10-20 06:00:42.000000000 +0000 @@ -27,11 +27,11 @@ SPEC Structure | Example SPEC ---------------------------|-------------- _name_ | `bitflags` -_name_`:`_version_ | `bitflags:1.0.4` +_name_`@`_version_ | `bitflags@1.0.4` _url_ | `https://github.com/rust-lang/cargo` _url_`#`_version_ | `https://github.com/rust-lang/cargo#0.33.0` _url_`#`_name_ | `https://github.com/rust-lang/crates.io-index#bitflags` -_url_`#`_name_`:`_version_ | `https://github.com/rust-lang/cargo#crates-io:0.21.0` +_url_`#`_name_`:`_version_ | `https://github.com/rust-lang/cargo#crates-io@0.21.0` ## OPTIONS @@ -127,6 +127,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -159,7 +165,7 @@ 2. Retrieve package specification for version 1.0.0 of `foo`: - cargo pkgid foo:1.0.0 + cargo pkgid foo@1.0.0 3. Retrieve package specification for `foo` from crates.io: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-publish.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-publish.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-publish.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-publish.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-publish(1) + ## NAME cargo-publish - Upload a package to the registry @@ -99,7 +100,7 @@
    --target triple
    Publish for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

    +list of supported targets. This flag may be specified multiple times.

    This may also be specified with the build.target config value.

    Note that specifying this flag makes Cargo run in a different mode where the @@ -129,6 +130,7 @@

    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -190,7 +192,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    @@ -245,6 +249,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-run.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-run.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-run.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-run.md 2022-10-20 06:00:42.000000000 +0000 @@ -65,6 +65,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -124,7 +125,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

      -
    • html: Write a human-readable file cargo-timing.html to the +
    • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -198,7 +199,7 @@
    • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
    • -
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
    • @@ -257,6 +258,12 @@ for more information about how toolchain overrides work.
    +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -276,7 +283,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-rustc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-rustc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-rustc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-rustc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-rustc(1) + ## NAME cargo-rustc - Compile the current package, and pass extra options to the compiler @@ -53,6 +54,16 @@ When no target selection options are given, `cargo rustc` will build all binary and library targets of the selected package. +Binary targets are automatically built if there is an integration test or +benchmark being selected to build. This allows an integration +test to execute the binary to exercise and test its behavior. +The `CARGO_BIN_EXE_` +[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) +is set when the integration test is built so that it can use the +[`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the +executable. + + Passing target selection flags will build only the specified targets. @@ -134,6 +145,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -158,7 +170,7 @@
    --target triple
    Build for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

    +list of supported targets. This flag may be specified multiple times.

    This may also be specified with the build.target config value.

    Note that specifying this flag makes Cargo run in a different mode where the @@ -203,7 +215,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

      -
    • html: Write a human-readable file cargo-timing.html to the +
    • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -215,6 +227,17 @@ +
      --crate-type crate-type
      +
      Build for the given crate type. This flag accepts a comma-separated list of +1 or more crate types, of which the allowed values are the same as crate-type +field in the manifest for configurating a Cargo target. See +crate-type field +for possible values.

      +

      If the manifest contains a list, and --crate-type is provided, +the command-line argument value will override what is in the manifest.

      +

      This flag only works when building a lib or example library target.

      + +
    ### Output Options @@ -277,7 +300,7 @@
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • -
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
  • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
  • @@ -336,6 +359,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -355,7 +384,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    @@ -395,5 +426,9 @@ cargo rustc --lib -- -Z print-type-sizes +3. Override `crate-type` field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + ## SEE ALSO [cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html), [rustc(1)](https://doc.rust-lang.org/rustc/index.html) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-rustdoc.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-rustdoc.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-rustdoc.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-rustdoc.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,6 +1,7 @@ # cargo-rustdoc(1) + ## NAME cargo-rustdoc - Build a package's documentation, using specified custom flags @@ -149,6 +150,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -173,7 +175,7 @@
    --target triple
    Document for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

    +list of supported targets. This flag may be specified multiple times.

    This may also be specified with the build.target config value.

    Note that specifying this flag makes Cargo run in a different mode where the @@ -208,7 +210,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

      -
    • html: Write a human-readable file cargo-timing.html to the +
    • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -281,7 +283,7 @@
    • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
    • -
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
    • @@ -337,6 +339,12 @@ for more information about how toolchain overrides work.
    +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -356,7 +364,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-search.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-search.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-search.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-search.md 2022-10-20 06:00:42.000000000 +0000 @@ -83,6 +83,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-test.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-test.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-test.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-test.md 2022-10-20 06:00:42.000000000 +0000 @@ -2,6 +2,7 @@ + ## NAME cargo-test - Execute unit and integration tests of a package @@ -12,7 +13,7 @@ ## DESCRIPTION -Compile and execute unit and integration tests. +Compile and execute unit, integration, and documentation tests. 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 @@ -27,20 +28,34 @@ cargo test foo -- --test-threads 3 -Tests are built with the `--test` option to `rustc` which creates an -executable with a `main` function that automatically runs all functions -annotated with the `#[test]` attribute in multiple threads. `#[bench]` -annotated functions will also be run with one iteration to verify that they -are functional. +Tests are built with the `--test` option to `rustc` which creates a special +executable by linking your code with libtest. The executable automatically +runs all functions annotated with the `#[test]` attribute in multiple threads. +`#[bench]` annotated functions will also be run with one iteration to verify +that they are functional. + +If the package contains multiple test targets, each target compiles to a +special executable as aforementioned, and then is run serially. The libtest harness may be disabled by setting `harness = false` in the target manifest settings, in which case your code will need to provide its own `main` function to handle running tests. +### Documentation tests + Documentation tests are also run by default, which is handled by `rustdoc`. It -extracts code samples from documentation comments and executes them. See the -[rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information on -writing doc tests. +extracts code samples from documentation comments of the library target, and +then executes them. + +Different from normal test targets, each code block compiles to a doctest +executable on the fly with `rustc`. These executables run in parallel in +separate processes. The compilation of a code block is in fact a part of test +function controlled by libtest, so some options such as `--jobs` might not +take effect. Note that this execution model of doctests is not guaranteed +and may change in the future; beware of depending on it. + +See the [rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information +on writing doc tests. ## OPTIONS @@ -131,13 +146,15 @@ library in the manifest. Binary targets are automatically built if there is an integration test or -benchmark. This allows an integration test to execute the binary to exercise -and test its behavior. The `CARGO_BIN_EXE_` +benchmark being selected to test. This allows an integration +test to execute the binary to exercise and test its behavior. +The `CARGO_BIN_EXE_` [environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates) is set when the integration test is built so that it can use the [`env` macro](https://doc.rust-lang.org/std/macro.env.html) to locate the executable. + Passing target selection flags will test only the specified targets. @@ -228,6 +245,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -252,7 +270,7 @@
    --target triple
    Test for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

    +list of supported targets. This flag may be specified multiple times.

    This may also be specified with the build.target config value.

    Note that specifying this flag makes Cargo run in a different mode where the @@ -287,7 +305,7 @@ Specifying an output format (rather than the default) is unstable and requires -Zunstable-options. Valid output formats:

      -
    • html: Write a human-readable file cargo-timing.html to the +
    • html (unstable, requires -Zunstable-options): Write a human-readable file cargo-timing.html to the target/cargo-timings directory with a report of the compilation. Also write a report to the same directory with a timestamp in the filename if you want to look at older runs. HTML output is suitable for human consumption only, @@ -367,7 +385,7 @@
    • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
    • -
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in +
    • json-render-diagnostics: Instruct Cargo to not include rustc diagnostics in JSON messages printed, but instead Cargo itself should render the JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others coming from rustc are still emitted. Cannot be used with human or short.
    • @@ -426,6 +444,12 @@ for more information about how toolchain overrides work.
    +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -452,7 +476,9 @@
    --jobs N
    Number of parallel jobs to run. May also be specified with the build.jobs config value. Defaults to -the number of CPUs.
    +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. +Should not be 0.
    --keep-going
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-tree.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-tree.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-tree.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-tree.md 2022-10-20 06:00:42.000000000 +0000 @@ -249,6 +249,7 @@
    +
    -F features
    --features features
    Space or comma separated list of features to activate. Features of workspace members may be enabled with package-name/feature-name syntax. This flag may @@ -312,6 +313,12 @@ for more information about how toolchain overrides work.
    +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-uninstall.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-uninstall.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-uninstall.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-uninstall.md 2022-10-20 06:00:42.000000000 +0000 @@ -93,6 +93,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-update.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-update.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-update.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-update.md 2022-10-20 06:00:42.000000000 +0000 @@ -138,6 +138,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-vendor.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-vendor.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-vendor.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-vendor.md 2022-10-20 06:00:42.000000000 +0000 @@ -134,6 +134,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-verify-project.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-verify-project.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-verify-project.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-verify-project.md 2022-10-20 06:00:42.000000000 +0000 @@ -104,6 +104,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-yank.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-yank.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/cargo-yank.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/cargo-yank.md 2022-10-20 06:00:42.000000000 +0000 @@ -6,7 +6,8 @@ ## SYNOPSIS -`cargo yank` [_options_] `--vers` _version_ [_crate_] +`cargo yank` [_options_] _crate_@_version_\ +`cargo yank` [_options_] `--version` _version_ [_crate_] ## DESCRIPTION @@ -31,6 +32,7 @@
    --vers version
    +
    --version version
    The version to yank or un-yank.
    @@ -111,6 +113,12 @@ for more information about how toolchain overrides work. +
    --config KEY=VALUE or PATH
    +
    Overrides a Cargo configuration value. The argument should be in TOML syntax of KEY=VALUE, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the command-line overrides section for more information.
    + +
    -h
    --help
    Prints help information.
    @@ -139,7 +147,7 @@ 1. Yank a crate from the index: - cargo yank --vers 1.0.7 foo + cargo yank foo@1.0.7 ## SEE ALSO [cargo(1)](cargo.html), [cargo-login(1)](cargo-login.html), [cargo-publish(1)](cargo-publish.html) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/manifest-commands.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/manifest-commands.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/commands/manifest-commands.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/commands/manifest-commands.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,4 +1,5 @@ # Manifest Commands +* [cargo add](cargo-add.md) * [cargo generate-lockfile](cargo-generate-lockfile.md) * [cargo locate-project](cargo-locate-project.md) * [cargo metadata](cargo-metadata.md) diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/faq.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/faq.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/faq.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/faq.md 2022-10-20 06:00:42.000000000 +0000 @@ -3,7 +3,7 @@ ### Is the plan to use GitHub as a package repository? No. The plan for Cargo is to use [crates.io], like npm or Rubygems do with -npmjs.org and rubygems.org. +[npmjs.com][1] and [rubygems.org][3]. We plan to support git repositories as a source of packages forever, because they can be used for early development and temporary patches, @@ -23,8 +23,9 @@ are downloaded through the registry in those ecosystems, with an important minority of packages making use of git-based packages. -[1]: https://www.npmjs.org +[1]: https://www.npmjs.com [2]: https://bundler.io +[3]: https://rubygems.org Some of the advantages that make a central registry popular in other languages include: @@ -135,9 +136,9 @@ with wildcard dependency constraints.** While libraries _can_, strictly speaking, they should not. A version requirement -of `*` says “This will work with every version ever,” which is never going +of `*` says “This will work with every version ever”, which is never going to be true. Libraries should always specify the range that they do work with, -even if it’s something as general as “every 1.x.y version.” +even if it’s something as general as “every 1.x.y version”. ### Why `Cargo.toml`? diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/cargo-toml-vs-cargo-lock.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/cargo-toml-vs-cargo-lock.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/cargo-toml-vs-cargo-lock.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/cargo-toml-vs-cargo-lock.md 2022-10-20 06:00:42.000000000 +0000 @@ -43,7 +43,8 @@ build would include new commits while yours would not. Therefore, we would get different builds. This would be bad because we want reproducible builds. -We could fix this problem by putting a `rev` line in our `Cargo.toml`: +We could fix this problem by defining a specific `rev` value in our `Cargo.toml`, +so Cargo could know exactly which revision to use when building the package: ```toml [dependencies] diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/continuous-integration.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/continuous-integration.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/continuous-integration.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/continuous-integration.md 2022-10-20 06:00:42.000000000 +0000 @@ -46,7 +46,7 @@ - beta - nightly steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }} - run: cargo build --verbose - run: cargo test --verbose diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/tests.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/tests.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/guide/tests.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/guide/tests.md 2022-10-20 06:00:42.000000000 +0000 @@ -2,9 +2,9 @@ Cargo can run your tests with the `cargo test` command. Cargo looks for tests to run in two places: in each of your `src` files and any tests in `tests/`. -Tests in your `src` files should be unit tests, and tests in `tests/` should be -integration-style tests. As such, you’ll need to import your crates into -the files in `tests`. +Tests in your `src` files should be unit tests and [documentation tests]. +Tests in `tests/` should be integration-style tests. As such, you’ll need to +import your crates into the files in `tests`. Here's an example of running `cargo test` in our [package][def-package], which currently has no tests: @@ -31,10 +31,14 @@ This will run any test with `foo` in its name. -`cargo test` runs additional checks as well. It will compile any -examples you’ve included and will also test the examples in your -documentation. Please see the [testing guide][testing] in the Rust -documentation for more details. +`cargo test` runs additional checks as well. It will compile any examples +you’ve included to ensure they are still compiles. It also run documentation +tests to ensure your code samples from documentation comments compiles. +Please see the [testing guide][testing] in the Rust documentation for a general +view of writing and organizing tests. See [Cargo Targets: Tests] to learn more +about different styles of tests in Cargo. +[documentation tests]: ../../rustdoc/write-documentation/documentation-tests.html [def-package]: ../appendix/glossary.md#package '"package" (glossary entry)' [testing]: ../../book/ch11-00-testing.html +[Cargo Targets: Tests]: ../reference/cargo-targets.html#tests diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/build-scripts.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/build-scripts.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/build-scripts.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/build-scripts.md 2022-10-20 06:00:42.000000000 +0000 @@ -77,6 +77,15 @@ interpret each line that starts with `cargo:` as an instruction that will influence compilation of the package. All other lines are ignored. +> Note: The order of `cargo:` instructions printed by the build script *may* +> affect the order of arguments that `cargo` passes to `rustc`. In turn, the +> order of arguments passed to `rustc` may affect the order of arguments passed +> to the linker. Therefore, you will want to pay attention to the order of the +> build script's instructions. For example, if object `foo` needs to link against +> library `bar`, you may want to make sure that library `bar`'s +> [`cargo:rustc-link-lib`](#rustc-link-lib) instruction appears *after* +> instructions to link object `foo`. + The output of the script is hidden from the terminal during normal compilation. If you would like to see the output directly in your terminal, invoke Cargo as "very verbose" with the `-vv` flag. This only happens when the @@ -106,7 +115,7 @@ flags to a linker for examples. * [`cargo:rustc-link-arg-benches=FLAG`](#rustc-link-arg-benches) – Passes custom flags to a linker for benchmarks. -* [`cargo:rustc-link-lib=[KIND=]NAME`](#rustc-link-lib) — Adds a library to +* [`cargo:rustc-link-lib=LIB`](#rustc-link-lib) — Adds a library to link. * [`cargo:rustc-link-search=[KIND=]PATH`](#rustc-link-search) — Adds to the library search path. @@ -153,12 +162,16 @@ -#### `cargo:rustc-link-lib=[KIND=]NAME` +#### `cargo:rustc-link-lib=LIB` The `rustc-link-lib` instruction tells Cargo to link the given library using the compiler's [`-l` flag][option-link]. This is typically used to link a native library using [FFI]. +The `LIB` string is passed directly to rustc, so it supports any syntax that +`-l` does. \ +Currently the full supported syntax for `LIB` is `[KIND[:MODIFIERS]=]NAME[:RENAME]`. + The `-l` flag is only passed to the library target of the package, unless there is no library target, in which case it is passed to all targets. This is done because all other targets have an implicit dependency on the library @@ -315,7 +328,9 @@ cases, this is not a good choice, so it is recommended that every build script emit at least one of the `rerun-if` instructions (described below). If these are emitted, then Cargo will only re-run the script if the given value has -changed. +changed. If Cargo is re-running the build scripts of your own crate or a +dependency and you don't know why, see ["Why is Cargo rebuilding my code?" in the +FAQ](../faq.md#why-is-cargo-rebuilding-my-code). [`exclude` and `include` fields]: manifest.md#the-exclude-and-include-fields diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/cargo-targets.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/cargo-targets.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/cargo-targets.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/cargo-targets.md 2022-10-20 06:00:42.000000000 +0000 @@ -100,7 +100,13 @@ field](#the-harness-field) if you want to use a different harness or test strategy. +> **Note**: There is another special style of test in Cargo: +> [documentation tests][documentation examples]. +> They are handled by `rustdoc` and have a slightly different execution model. +> For more information, please see [`cargo test`][cargo-test-documentation-tests]. + [libtest harness]: ../../rustc/tests/index.html +[cargo-test-documentation-tests]: ../commands/cargo-test.md#documentation-tests #### Integration tests diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/config.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/config.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/config.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/config.md 2022-10-20 06:00:42.000000000 +0000 @@ -59,6 +59,7 @@ t = "test" r = "run" rr = "run --release" +recursive_example = "rr --example recursions" space_example = ["run", "--release", "--", "\"command list\""] [build] @@ -195,15 +196,70 @@ In addition to the system above, Cargo recognizes a few other specific [environment variables][env]. +### Command-line overrides + +Cargo also accepts arbitrary configuration overrides through the +`--config` command-line option. The argument should be in TOML syntax of +`KEY=VALUE`: + +```console +cargo --config net.git-fetch-with-cli=true fetch +``` + +The `--config` option may be specified multiple times, in which case the +values are merged in left-to-right order, using the same merging logic +that is used when multiple configuration files apply. Configuration +values specified this way take precedence over environment variables, +which take precedence over configuration files. + +Some examples of what it looks like using Bourne shell syntax: + +```console +# Most shells will require escaping. +cargo --config http.proxy=\"http://example.com\" … + +# Spaces may be used. +cargo --config "net.git-fetch-with-cli = true" … + +# TOML array example. Single quotes make it easier to read and write. +cargo --config 'build.rustdocflags = ["--html-in-header", "header.html"]' … + +# Example of a complex TOML key. +cargo --config "target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))'.runner = 'my-runner'" … + +# Example of overriding a profile setting. +cargo --config profile.dev.package.image.opt-level=3 … +``` + +The `--config` option can also be used to pass paths to extra +configuration files that Cargo should use for a specific invocation. +Options from configuration files loaded this way follow the same +precedence rules as other options specified directly with `--config`. + ### Config-relative paths -Paths in config files may be absolute, relative, or a bare name without any -path separators. Paths for executables without a path separator will use the -`PATH` environment variable to search for the executable. Paths for -non-executables will be relative to where the config value is defined. For -config files, that is relative to the parent directory of the `.cargo` -directory where the value was defined. For environment variables it is -relative to the current working directory. +Paths in config files may be absolute, relative, or a bare name without any path separators. +Paths for executables without a path separator will use the `PATH` environment variable to search for the executable. +Paths for non-executables will be relative to where the config value is defined. + +In particular, rules are: + +* For environment variables, paths are relative to the current working directory. +* For config values loaded directly from the [`--config KEY=VALUE`](#command-line-overrides) option, + paths are relative to the current working directory. +* For config files, paths are relative to the parent directory of the directory where the config files were defined, + no matter those files are from either the [hierarchical probing](#hierarchical-structure) + or the [`--config `](#command-line-overrides) option. + +> **Note:** To maintain consistency with existing `.cargo/config.toml` probing behavior, +> it is by design that a path in a config file passed via `--config ` +> is also relative to two levels up from the config file itself. +> +> To avoid unexpected results, the rule of thumb is putting your extra config files +> at the same level of discovered `.cargo/config.toml` in your porject. +> For instance, given a project `/my/project`, +> it is recommended to put config files under `/my/project/.cargo` +> or a new directory at the same level, such as `/my/project/.config`. ```toml # Relative path examples. @@ -295,6 +351,14 @@ Aliases are not allowed to redefine existing built-in commands. +Aliases are recursive: + +```toml +[alias] +rr = "run --release" +recursive_example = "rr --example recursions" +``` + #### `[build]` The `[build]` table controls build-time operations and compiler settings. @@ -304,7 +368,9 @@ * Default: number of logical CPUs * Environment: `CARGO_BUILD_JOBS` -Sets the maximum number of compiler processes to run in parallel. +Sets the maximum number of compiler processes to run in parallel. If negative, +it sets the maximum number of compiler processes to the number of logical CPUs +plus provided value. Should not be 0. Can be overridden with the `--jobs` CLI option. @@ -321,7 +387,8 @@ * Environment: `CARGO_BUILD_RUSTC_WRAPPER` or `RUSTC_WRAPPER` Sets a wrapper to execute instead of `rustc`. The first argument passed to the -wrapper is the path to the actual `rustc`. +wrapper is the path to the actual executable to use +(i.e., `build.rustc`, if that is set, or `"rustc"` otherwise). ##### `build.rustc-workspace-wrapper` * Type: string (program path) @@ -329,7 +396,8 @@ * Environment: `CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER` or `RUSTC_WORKSPACE_WRAPPER` Sets a wrapper to execute instead of `rustc`, for workspace members only. -The first argument passed to the wrapper is the path to the actual `rustc`. +The first argument passed to the wrapper is the path to the actual +executable to use (i.e., `build.rustc`, if that is set, or `"rustc"` otherwise). It affects the filename hash so that artifacts produced by the wrapper are cached separately. ##### `build.rustdoc` @@ -340,16 +408,25 @@ Sets the executable to use for `rustdoc`. ##### `build.target` -* Type: string +* Type: string or array of strings * Default: host platform * Environment: `CARGO_BUILD_TARGET` -The default target platform triple to compile to. +The default target platform triples to compile to. -This may also be a relative path to a `.json` target spec file. +This allows passing either a string or an array of strings. Each string value +is a target platform triple. The selected build targets will be built for each +of the selected architectures. + +The string value may also be a relative path to a `.json` target spec file. Can be overridden with the `--target` CLI option. +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"] +``` + ##### `build.target-dir` * Type: string (path) * Default: "target" @@ -363,18 +440,19 @@ ##### `build.rustflags` * Type: string or array of strings * Default: none -* Environment: `CARGO_BUILD_RUSTFLAGS` or `RUSTFLAGS` +* Environment: `CARGO_BUILD_RUSTFLAGS` or `CARGO_ENCODED_RUSTFLAGS` or `RUSTFLAGS` -Extra command-line flags to pass to `rustc`. The value may be a array of +Extra command-line flags to pass to `rustc`. The value may be an array of strings or a space-separated string. -There are three mutually exclusive sources of extra flags. They are checked in +There are four mutually exclusive sources of extra flags. They are checked in order, with the first one being used: -1. `RUSTFLAGS` environment variable. -2. All matching `target..rustflags` and `target..rustflags` +1. `CARGO_ENCODED_RUSTFLAGS` environment variable. +2. `RUSTFLAGS` environment variable. +3. All matching `target..rustflags` and `target..rustflags` config entries joined together. -3. `build.rustflags` config value. +4. `build.rustflags` config value. Additional flags may also be passed with the [`cargo rustc`] command. @@ -399,16 +477,17 @@ ##### `build.rustdocflags` * Type: string or array of strings * Default: none -* Environment: `CARGO_BUILD_RUSTDOCFLAGS` or `RUSTDOCFLAGS` +* Environment: `CARGO_BUILD_RUSTDOCFLAGS` or `CARGO_ENCODED_RUSTDOCFLAGS` or `RUSTDOCFLAGS` -Extra command-line flags to pass to `rustdoc`. The value may be a array of +Extra command-line flags to pass to `rustdoc`. The value may be an array of strings or a space-separated string. -There are two mutually exclusive sources of extra flags. They are checked in +There are three mutually exclusive sources of extra flags. They are checked in order, with the first one being used: -1. `RUSTDOCFLAGS` environment variable. -2. `build.rustdocflags` config value. +1. `CARGO_ENCODED_RUSTDOCFLAGS` environment variable. +2. `RUSTDOCFLAGS` environment variable. +3. `build.rustdocflags` config value. Additional flags may also be passed with the [`cargo rustdoc`] command. @@ -972,7 +1051,7 @@ * Environment: `CARGO_TARGET__RUSTFLAGS` Passes a set of custom flags to the compiler for this ``. The value -may be a array of strings or a space-separated string. +may be an array of strings or a space-separated string. See [`build.rustflags`](#buildrustflags) for more details on the different ways to specific extra flags. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/environment-variables.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/environment-variables.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/environment-variables.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/environment-variables.md 2022-10-20 06:00:42.000000000 +0000 @@ -9,6 +9,11 @@ You can override these environment variables to change Cargo's behavior on your system: +* `CARGO_LOG` - Cargo uses the [`env_logger`] crate to display debug log messages. + The `CARGO_LOG` environment variable can be set to enable debug logging, + with a value such as `trace`, `debug`, or `warn`. + Usually it is only used during debugging. For more details refer to the + [Debug logging]. * `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` (`%USERPROFILE%\.cargo` on Windows), but this variable overrides the @@ -21,15 +26,18 @@ * `RUSTC` — Instead of running `rustc`, Cargo will execute this specified compiler instead. See [`build.rustc`] to set via config. * `RUSTC_WRAPPER` — Instead of simply running `rustc`, Cargo will execute this - specified wrapper instead, passing as its command-line arguments the rustc - invocation, with the first argument being `rustc`. Useful to set up a build - cache tool such as `sccache`. See [`build.rustc-wrapper`] to set via config. -* `RUSTC_WORKSPACE_WRAPPER` — Instead of simply running `rustc`, Cargo will - execute this specified wrapper instead for workspace members only, passing + specified wrapper, passing as its command-line arguments the rustc + invocation, with the first argument being the path to the actual rustc. + Useful to set up a build cache tool such as `sccache`. See + [`build.rustc-wrapper`] to set via config. Setting this to the empty string + overwrites the config and resets cargo to not use a wrapper. +* `RUSTC_WORKSPACE_WRAPPER` — Instead of simply running `rustc`, for workspace + members Cargo will execute this specified wrapper, passing as its command-line arguments the rustc invocation, with the first argument - being `rustc`. It affects the filename hash so that artifacts produced by - the wrapper are cached separately. See [`build.rustc-workspace-wrapper`] - to set via config. + being the path to the actual rustc. It affects the filename hash + so that artifacts produced by the wrapper are cached separately. + See [`build.rustc-workspace-wrapper`] to set via config. Setting this to the empty string + overwrites the config and resets cargo to not use a wrapper for workspace members. * `RUSTDOC` — Instead of running `rustdoc`, Cargo will execute this specified `rustdoc` instance instead. See [`build.rustdoc`] to set via config. * `RUSTDOCFLAGS` — A space-separated list of custom flags to pass to all `rustdoc` @@ -37,15 +45,17 @@ useful for passing a flag to *all* `rustdoc` instances. See [`build.rustdocflags`] for some more ways to set flags. This string is split by whitespace; for a more robust encoding of multiple arguments, - set `CARGO_ENCODED_RUSTDOCFLAGS` instead with arguments separated by - `0x1f` (ASCII Unit Separator). + see `CARGO_ENCODED_RUSTDOCFLAGS`. +* `CARGO_ENCODED_RUSTDOCFLAGS` - A list of custom flags separated by `0x1f` + (ASCII Unit Separator) to pass to all `rustdoc` invocations that Cargo performs. * `RUSTFLAGS` — A space-separated list of custom flags to pass to all compiler invocations that Cargo performs. In contrast with [`cargo rustc`], this is useful for passing a flag to *all* compiler instances. See [`build.rustflags`] for some more ways to set flags. This string is split by whitespace; for a more robust encoding of multiple arguments, - set `CARGO_ENCODED_RUSTFLAGS` instead with arguments separated by - `0x1f` (ASCII Unit Separator). + see `CARGO_ENCODED_RUSTFLAGS`. +* `CARGO_ENCODED_RUSTFLAGS` - A list of custom flags separated by `0x1f` + (ASCII Unit Separator) to pass to all compiler invocations that Cargo performs. * `CARGO_INCREMENTAL` — If this is set to 1 then Cargo will force [incremental compilation] to be enabled for the current compilation, and when set to 0 it will force disabling it. If this env var isn't present then cargo's defaults @@ -82,7 +92,7 @@ * `CARGO_BUILD_INCREMENTAL` — Incremental compilation, see [`build.incremental`]. * `CARGO_BUILD_DEP_INFO_BASEDIR` — Dep-info relative directory, see [`build.dep-info-basedir`]. * `CARGO_CARGO_NEW_VCS` — The default source control system with [`cargo new`], see [`cargo-new.vcs`]. -* `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY` - How often we should generate a future incompat report notifcation, see [`future-incompat-report.frequency`]. +* `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY` - How often we should generate a future incompat report notification, see [`future-incompat-report.frequency`]. * `CARGO_HTTP_DEBUG` — Enables HTTP debugging, see [`http.debug`]. * `CARGO_HTTP_PROXY` — Enables HTTP proxy, see [`http.proxy`]. * `CARGO_HTTP_TIMEOUT` — The HTTP timeout, see [`http.timeout`]. @@ -212,6 +222,9 @@ * `CARGO_PKG_REPOSITORY` — The repository from the manifest of your package. * `CARGO_PKG_LICENSE` — The license from the manifest of your package. * `CARGO_PKG_LICENSE_FILE` — The license file from the manifest of your package. +* `CARGO_PKG_RUST_VERSION` — The Rust version from the manifest of your package. + Note that this is the minimum Rust version supported by the package, not the + current Rust version. * `CARGO_CRATE_NAME` — The name of the crate that is currently being compiled. * `CARGO_BIN_NAME` — The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as `.exe`. * `OUT_DIR` — If the package has a build script, this is set to the folder where the build @@ -361,6 +374,8 @@ the environment; scripts should use `CARGO_ENCODED_RUSTFLAGS` instead. * `CARGO_PKG_` - The package information variables, with the same names and values as are [provided during crate building][variables set for crates]. +[`env_logger`]: https://docs.rs/env_logger +[debug logging]: https://doc.crates.io/contrib/architecture/console.html#debug-logging [unix-like platforms]: ../../reference/conditional-compilation.html#unix-and-windows [windows-like platforms]: ../../reference/conditional-compilation.html#unix-and-windows [target family]: ../../reference/conditional-compilation.html#target_family diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/features.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/features.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/features.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/features.md 2022-10-20 06:00:42.000000000 +0000 @@ -513,3 +513,9 @@ [`cargo vendor`]: ../commands/cargo-vendor.md [cargo-clone-crate]: https://crates.io/crates/cargo-clone-crate + +### Feature combinations + +Because features are a form of conditional compilation, they require an exponential number of configurations and test cases to be 100% covered. By default, tests, docs, and other tooling such as [Clippy](https://github.com/rust-lang/rust-clippy) will only run with the default set of features. + +We encourage you to consider your strategy and tooling in regards to different feature combinations - Every project will have different requirements in conjunction with time, resources, and the cost-benefit of covering specific scenarios. Common configurations may be with / without default features, specific combinations of features, or all combinations of features. diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/future-incompat-report.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/future-incompat-report.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/future-incompat-report.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/future-incompat-report.md 2022-10-20 06:00:42.000000000 +0000 @@ -1,24 +1,37 @@ ### Future incompat report -Cargo checks for future-incompatible warnings in all dependencies. These are warnings for +Cargo checks for future-incompatible warnings in all dependencies. These are warnings for changes that may become hard errors in the future, causing the dependency to stop building in a future version of rustc. If any warnings are found, a small notice is displayed indicating that the warnings were found, and provides instructions on how to display a full report. +For example, you may see something like this at the end of a build: + +```text +warning: the following packages contain code that will be rejected by a future + version of Rust: rental v0.5.5 +note: to see what the problems were, use the option `--future-incompat-report`, + or run `cargo report future-incompatibilities --id 1` +``` + A full report can be displayed with the `cargo report future-incompatibilities --id ID` command, or by running the build again with the `--future-incompat-report` flag. The developer should then update their dependencies to a version where the issue is fixed, or work with the developers of the dependencies to help resolve the issue. -This feature can be configured through a `[future-incompat-report]` -section in `.cargo/config`. Currently, the supported options are: +## Configuration -``` +This feature can be configured through a [`[future-incompat-report]`][config] +section in `.cargo/config.toml`. Currently, the supported options are: + +```toml [future-incompat-report] -frequency = FREQUENCY +frequency = "always" ``` -The supported values for `FREQUENCY` are `always` and `never`, which control +The supported values for the frequency are `"always"` and `"never"`, which control whether or not a message is printed out at the end of `cargo build` / `cargo check`. + +[config]: config.md#future-incompat-report diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/manifest.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/manifest.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/manifest.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/manifest.md 2022-10-20 06:00:42.000000000 +0000 @@ -74,11 +74,15 @@ inferred lib and bin targets. The name must use only [alphanumeric] characters or `-` or `_`, and cannot be empty. + Note that [`cargo new`] and [`cargo init`] impose some additional restrictions on the package name, such as enforcing that it is a valid Rust identifier and not -a keyword. [crates.io] imposes even more restrictions, such as -enforcing only ASCII characters, not a reserved name, not a special Windows -name such as "nul", is not too long, etc. +a keyword. [crates.io] imposes even more restrictions, such as: + +- Only ASCII characters are allowed. +- Do not use reserved names. +- Do not use special Windows name such as "nul". +- Use a maximum of 64 characters of length. [alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric @@ -361,10 +365,13 @@ [links]: build-scripts.md#the-links-manifest-key +For example, a crate that links a native library called "git2" (e.g. `libgit2.a` +on Linux) may specify: + ```toml [package] # ... -links = "foo" +links = "git2" ``` diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/overriding-dependencies.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/overriding-dependencies.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/overriding-dependencies.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/overriding-dependencies.md 2022-10-20 06:00:42.000000000 +0000 @@ -266,6 +266,12 @@ baz = { git = 'https://github.com/example/patched-baz', branch = 'my-branch' } ``` +> **Note**: The `[patch]` table can also be specified as a [configuration +> option](config.md), such as in a `.cargo/config.toml` file or a CLI option +> like `--config 'patch.crates-io.rand.path="rand"'`. This can be useful for +> local-only changes that you don't want to commit, or temporarily testing a +> patch. + The `[patch]` table is made of dependency-like sub-tables. Each key after `[patch]` is a URL of the source that is being patched, or the name of a registry. The name `crates-io` may be used to override the default registry diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/pkgid-spec.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/pkgid-spec.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/pkgid-spec.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/pkgid-spec.md 2022-10-20 06:00:42.000000000 +0000 @@ -9,12 +9,12 @@ packages. The specification may be fully qualified, such as -`https://github.com/rust-lang/crates.io-index#regex:1.4.3` or it may be +`https://github.com/rust-lang/crates.io-index#regex@1.4.3` or it may be abbreviated, such as `regex`. The abbreviated form may be used as long as it uniquely identifies a single package in the dependency graph. If there is ambiguity, additional qualifiers can be added to make it unique. For example, if there are two versions of the `regex` package in the graph, then it can be -qualified with a version to make it unique, such as `regex:1.4.3`. +qualified with a version to make it unique, such as `regex@1.4.3`. #### Specification grammar @@ -23,7 +23,7 @@ ```notrust spec := pkgname | proto "://" hostname-and-path [ "#" ( pkgname | semver ) ] -pkgname := name [ ":" semver ] +pkgname := name [ ("@" | ":" ) semver ] proto := "http" | "git" | ... ``` @@ -40,17 +40,17 @@ | Spec | Name | Version | |:------------------------------------------------------------|:-------:|:-------:| | `regex` | `regex` | `*` | -| `regex:1.4.3` | `regex` | `1.4.3` | +| `regex@1.4.3` | `regex` | `1.4.3` | | `https://github.com/rust-lang/crates.io-index#regex` | `regex` | `*` | -| `https://github.com/rust-lang/crates.io-index#regex:1.4.3` | `regex` | `1.4.3` | +| `https://github.com/rust-lang/crates.io-index#regex@1.4.3` | `regex` | `1.4.3` | The following are some examples of specs for several different git dependencies: | Spec | Name | Version | |:----------------------------------------------------------|:----------------:|:--------:| | `https://github.com/rust-lang/cargo#0.52.0` | `cargo` | `0.52.0` | -| `https://github.com/rust-lang/cargo#cargo-platform:0.1.2` | `cargo-platform` | `0.1.2` | -| `ssh://git@github.com/rust-lang/regex.git#regex:1.4.3` | `regex` | `1.4.3` | +| `https://github.com/rust-lang/cargo#cargo-platform@0.1.2` | `cargo-platform` | `0.1.2` | +| `ssh://git@github.com/rust-lang/regex.git#regex@1.4.3` | `regex` | `1.4.3` | Local packages on the filesystem can use `file://` URLs to reference them: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/profiles.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/profiles.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/profiles.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/profiles.md 2022-10-20 06:00:42.000000000 +0000 @@ -246,7 +246,7 @@ #### dev The `dev` profile is used for normal development and debugging. It is the -default for build commands like [`cargo build`]. +default for build commands like [`cargo build`], and is used for `cargo install --debug`. The default settings for the `dev` profile are: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/publishing.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/publishing.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/publishing.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/publishing.md 2022-10-20 06:00:42.000000000 +0000 @@ -142,8 +142,8 @@ crate. ```console -$ cargo yank --vers 1.0.1 -$ cargo yank --vers 1.0.1 --undo +$ cargo yank --version 1.0.1 +$ cargo yank --version 1.0.1 --undo ``` A yank **does not** delete any code. This feature is not intended for deleting diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/registries.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/registries.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/registries.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/registries.md 2022-10-20 06:00:42.000000000 +0000 @@ -320,9 +320,10 @@ using the [`cargo login`] command, or by passing the token on the command-line. -Responses use a 200 response code for both success and errors. Cargo looks at -the JSON response to determine if there was success or failure. Failure -responses have a JSON object with the following structure: +Responses use the 200 response code for success. +Errors should use an appropriate response code, such as 404. +Failure +responses should have a JSON object with the following structure: ```javascript { @@ -336,10 +337,10 @@ } ``` -Servers may also respond with a 404 response code to indicate the requested -resource is not found (for example, an unknown crate name). However, using a -200 response with an `errors` object allows a registry to provide a more -detailed error message if desired. +If the response has this structure Cargo will display the detailed message to the user, even if the response code is 200. +If the response code indicates an error and the content does not have this structure, Cargo will display to the user a + message intended to help debugging the server error. A server returning an `errors` object allows a registry to provide a more +detailed or user-centric error message. For backwards compatibility, servers should ignore any unexpected query parameters or JSON fields. If a JSON field is missing, it should be assumed to diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/resolver.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/resolver.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/resolver.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/resolver.md 2022-10-20 06:00:42.000000000 +0000 @@ -37,7 +37,8 @@ `0.1.0` and `0.2.0` are not. Similarly, `0.0.1` and `0.0.2` are not compatible. -As a quick refresher, the *version requirement* syntax Cargo uses for +As a quick refresher, the +[*version requirement* syntax][Specifying Dependencies] Cargo uses for dependencies is: Requirement | Example | Equivalence | Description diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/semver.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/semver.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/semver.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/semver.md 2022-10-20 06:00:42.000000000 +0000 @@ -955,7 +955,7 @@ ### Minor: generalizing a function to use generics (supporting original type) -The type of an parameter to a function, or its return value, can be +The type of a parameter to a function, or its return value, can be *generalized* to use generics, including by introducing a new type parameter, as long as it can be instantiated to the original type. For example, the following changes are allowed: diff -Nru cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/specifying-dependencies.md cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/specifying-dependencies.md --- cargo-0.62.0ubuntu0libgit2/src/doc/src/reference/specifying-dependencies.md 2022-04-29 22:38:54.000000000 +0000 +++ cargo-0.66.0+ds0ubuntu0.libgit2/src/doc/src/reference/specifying-dependencies.md 2022-10-20 06:00:42.000000000 +0000 @@ -454,8 +454,44 @@ log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error! ``` +### Inheriting a dependency from a workspace + +Dependencies can be inherited from a workspace by specifying the +dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table. +After that, add it to the `[dependencies]` table with `workspace = true`. + +Along with the `workspace` key, dependencies can also include these keys: +- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`. +- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]` + +Other than `optional` and `features`, inherited dependencies cannot use any other +dependency key (such as `version` or `default-features`). + +Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and +`[target."...".dependencies]` sections support the ability to reference the +`[workspace.dependencies]` definition of dependencies. + +```toml +[project] +name = "bar" +version = "0.2.0" + +[dependencies] +regex = { workspace = true, features = ["unicode"] } + +[build-dependencies] +cc.workspace = true + +[dev-dependencies] +rand = { workspace = true, optional = true } +``` + + [crates.io]: https://crates.io/ [dev-dependencies]: #development-dependencies +[workspace.dependencies]: workspaces.md#the-workspacedependencies-table +[optional]: features.md#optional-dependencies +[features]: features.md