diff --git a/Cargo.toml b/Cargo.toml index 08b5a5de27f..78cc401ecb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ path = "src/cargo/lib.rs" [dependencies] atty = "0.2" bytesize = "1.0" -cargo-platform = { path = "crates/cargo-platform", version = "0.1.1" } +cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } cargo-util = { path = "crates/cargo-util", version = "0.1.1" } crates-io = { path = "crates/crates-io", version = "0.33.0" } crossbeam-utils = "0.8" @@ -40,7 +40,7 @@ home = "0.5" humantime = "2.0.0" ignore = "0.4.7" lazy_static = "1.2.0" -jobserver = "0.1.21" +jobserver = "0.1.23" lazycell = "1.2.0" libc = "0.2" log = "0.4.6" diff --git a/crates/cargo-platform/Cargo.toml b/crates/cargo-platform/Cargo.toml index 0a9a8197876..2b5e86e9921 100644 --- a/crates/cargo-platform/Cargo.toml +++ b/crates/cargo-platform/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-platform" -version = "0.1.1" +version = "0.1.2" authors = ["The Cargo Project Developers"] edition = "2018" license = "MIT OR Apache-2.0" diff --git a/crates/cargo-test-support/src/lib.rs b/crates/cargo-test-support/src/lib.rs index 17e01d14de1..36fa9d2dabc 100644 --- a/crates/cargo-test-support/src/lib.rs +++ b/crates/cargo-test-support/src/lib.rs @@ -70,20 +70,36 @@ pub mod tools; struct FileBuilder { path: PathBuf, body: String, + executable: bool, } impl FileBuilder { - pub fn new(path: PathBuf, body: &str) -> FileBuilder { + pub fn new(path: PathBuf, body: &str, executable: bool) -> FileBuilder { FileBuilder { path, body: body.to_string(), + executable: executable, } } - fn mk(&self) { + fn mk(&mut self) { + if self.executable { + self.path.set_extension(env::consts::EXE_EXTENSION); + } + self.dirname().mkdir_p(); fs::write(&self.path, &self.body) .unwrap_or_else(|e| panic!("could not create file {}: {}", self.path.display(), e)); + + #[cfg(unix)] + if self.executable { + use std::os::unix::fs::PermissionsExt; + + let mut perms = fs::metadata(&self.path).unwrap().permissions(); + let mode = perms.mode(); + perms.set_mode(mode | 0o111); + fs::set_permissions(&self.path, perms).unwrap(); + } } fn dirname(&self) -> &Path { @@ -122,11 +138,16 @@ impl SymlinkBuilder { } #[cfg(windows)] - fn mk(&self) { + fn mk(&mut self) { self.dirname().mkdir_p(); if self.src_is_dir { t!(os::windows::fs::symlink_dir(&self.dst, &self.src)); } else { + if let Some(ext) = self.dst.extension() { + if ext == env::consts::EXE_EXTENSION { + self.src.set_extension(ext); + } + } t!(os::windows::fs::symlink_file(&self.dst, &self.src)); } } @@ -177,13 +198,22 @@ impl ProjectBuilder { /// Adds a file to the project. pub fn file>(mut self, path: B, body: &str) -> Self { - self._file(path.as_ref(), body); + self._file(path.as_ref(), body, false); self } - fn _file(&mut self, path: &Path, body: &str) { - self.files - .push(FileBuilder::new(self.root.root().join(path), body)); + /// Adds an executable file to the project. + pub fn executable>(mut self, path: B, body: &str) -> Self { + self._file(path.as_ref(), body, true); + self + } + + fn _file(&mut self, path: &Path, body: &str, executable: bool) { + self.files.push(FileBuilder::new( + self.root.root().join(path), + body, + executable, + )); } /// Adds a symlink to a file to the project. @@ -219,13 +249,17 @@ impl ProjectBuilder { let manifest_path = self.root.root().join("Cargo.toml"); if !self.no_manifest && self.files.iter().all(|fb| fb.path != manifest_path) { - self._file(Path::new("Cargo.toml"), &basic_manifest("foo", "0.0.1")) + self._file( + Path::new("Cargo.toml"), + &basic_manifest("foo", "0.0.1"), + false, + ) } let past = time::SystemTime::now() - Duration::new(1, 0); let ftime = filetime::FileTime::from_system_time(past); - for file in self.files.iter() { + for file in self.files.iter_mut() { file.mk(); if is_coarse_mtime() { // Place the entire project 1 second in the past to ensure @@ -237,7 +271,7 @@ impl ProjectBuilder { } } - for symlink in self.symlinks.iter() { + for symlink in self.symlinks.iter_mut() { symlink.mk(); } @@ -316,7 +350,7 @@ impl Project { /// Changes the contents of an existing file. pub fn change_file(&self, path: &str, body: &str) { - FileBuilder::new(self.root().join(path), body).mk() + FileBuilder::new(self.root().join(path), body, false).mk() } /// Creates a `ProcessBuilder` to run a program in the project diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 2fefa8a2d02..12346170111 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -98,20 +98,23 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'", if args.is_present("list") { drop_println!(config, "Installed Commands:"); - for command in list_commands(config) { + for (name, command) in list_commands(config) { match command { - CommandInfo::BuiltIn { name, about } => { + CommandInfo::BuiltIn { about } => { let summary = about.unwrap_or_default(); let summary = summary.lines().next().unwrap_or(&summary); // display only the first line drop_println!(config, " {:<20} {}", name, summary); } - CommandInfo::External { name, path } => { + CommandInfo::External { path } => { if is_verbose { drop_println!(config, " {:<20} {}", name, path.display()); } else { drop_println!(config, " {}", name); } } + CommandInfo::Alias { target } => { + drop_println!(config, " {:<20} {}", name, target.iter().join(" ")); + } } } return Ok(()); diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 6f9134b8c54..58056aa8375 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -4,10 +4,11 @@ #![warn(clippy::redundant_clone)] 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}; use cargo_util::{ProcessBuilder, ProcessError}; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::env; use std::fs; use std::path::{Path, PathBuf}; @@ -83,10 +84,10 @@ fn aliased_command(config: &Config, command: &str) -> CargoResult BTreeSet { +fn list_commands(config: &Config) -> BTreeMap { let prefix = "cargo-"; let suffix = env::consts::EXE_SUFFIX; - let mut commands = BTreeSet::new(); + let mut commands = BTreeMap::new(); for dir in search_directories(config) { let entries = match fs::read_dir(dir) { Ok(entries) => entries, @@ -103,39 +104,47 @@ fn list_commands(config: &Config) -> BTreeSet { } if is_executable(entry.path()) { let end = filename.len() - suffix.len(); - commands.insert(CommandInfo::External { - name: filename[prefix.len()..end].to_string(), - path: path.clone(), - }); + commands.insert( + filename[prefix.len()..end].to_string(), + CommandInfo::External { path: path.clone() }, + ); } } } for cmd in commands::builtin() { - commands.insert(CommandInfo::BuiltIn { - name: cmd.get_name().to_string(), - about: cmd.p.meta.about.map(|s| s.to_string()), - }); + commands.insert( + cmd.get_name().to_string(), + CommandInfo::BuiltIn { + about: cmd.p.meta.about.map(|s| s.to_string()), + }, + ); } // Add the builtin_aliases and them descriptions to the - // `commands` `BTreeSet`. + // `commands` `BTreeMap`. for command in &BUILTIN_ALIASES { - commands.insert(CommandInfo::BuiltIn { - name: command.0.to_string(), - about: Some(command.2.to_string()), - }); + commands.insert( + command.0.to_string(), + CommandInfo::BuiltIn { + about: Some(command.2.to_string()), + }, + ); } - commands -} - -/// List all runnable aliases -fn list_aliases(config: &Config) -> Vec { - match config.get::>("alias") { - Ok(aliases) => aliases.keys().map(|a| a.to_string()).collect(), - Err(_) => Vec::new(), + // Add the user-defined aliases + if let Ok(aliases) = config.get::>("alias") { + for (name, target) in aliases.iter() { + commands.insert( + name.to_string(), + CommandInfo::Alias { + target: target.clone(), + }, + ); + } } + + commands } fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult { @@ -147,13 +156,8 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli let command = match path { Some(command) => command, None => { - let commands: Vec = list_commands(config) - .iter() - .map(|c| c.name().to_string()) - .collect(); - let aliases = list_aliases(config); - let suggestions = commands.iter().chain(aliases.iter()); - let did_you_mean = closest_msg(cmd, suggestions, |c| c); + 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); return Err(CliError::new(err, 101)); } diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 72d4371b889..3d8967ee9ed 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -195,12 +195,12 @@ impl<'a, 'cfg> Context<'a, 'cfg> { self.compilation .binaries .push(self.unit_output(unit, bindst)); - } else if unit.target.is_cdylib() { - if !self.compilation.cdylibs.iter().any(|uo| uo.unit == *unit) { - self.compilation - .cdylibs - .push(self.unit_output(unit, bindst)); - } + } else if unit.target.is_cdylib() + && !self.compilation.cdylibs.iter().any(|uo| uo.unit == *unit) + { + self.compilation + .cdylibs + .push(self.unit_output(unit, bindst)); } } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 1687a5d2ace..7007d0dd8c2 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -796,6 +796,7 @@ fn build_base_args( let bcx = cx.bcx; let Profile { ref opt_level, + codegen_backend, codegen_units, debuginfo, debug_assertions, @@ -860,6 +861,10 @@ fn build_base_args( } } + if let Some(backend) = codegen_backend { + cmd.arg("-Z").arg(&format!("codegen-backend={}", backend)); + } + if let Some(n) = codegen_units { cmd.arg("-C").arg(&format!("codegen-units={}", n)); } diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index 01136017dec..66596bb1880 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -84,7 +84,7 @@ fn add_deps_for_unit( // The paths we have saved from the unit are of arbitrary relativeness and may be // relative to the crate root of the dependency. let path = unit.pkg.root().join(path); - deps.insert(path.into()); + deps.insert(path); } } } diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index e338a66acea..31fe062ca0d 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -402,6 +402,9 @@ features! { // Allow to specify per-package targets (compile kinds) (unstable, per_package_target, "", "reference/unstable.html#per-package-target"), + + // Allow to specify which codegen backend should be used. + (unstable, codegen_backend, "", "reference/unstable.html#codegen-backend"), } pub struct Feature { diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 04ec2e6f9e1..ac167f17363 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -565,6 +565,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) { Some(StringOrBool::String(ref n)) => profile.lto = Lto::Named(InternedString::new(n)), None => {} } + if toml.codegen_backend.is_some() { + profile.codegen_backend = toml.codegen_backend; + } if toml.codegen_units.is_some() { profile.codegen_units = toml.codegen_units; } @@ -626,6 +629,8 @@ pub struct Profile { pub root: ProfileRoot, pub lto: Lto, // `None` means use rustc default. + pub codegen_backend: Option, + // `None` means use rustc default. pub codegen_units: Option, pub debuginfo: Option, pub split_debuginfo: Option, @@ -644,6 +649,7 @@ impl Default for Profile { opt_level: InternedString::new("0"), root: ProfileRoot::Debug, lto: Lto::Bool(false), + codegen_backend: None, codegen_units: None, debuginfo: None, debug_assertions: false, @@ -670,6 +676,7 @@ compact_debug! { opt_level lto root + codegen_backend codegen_units debuginfo split_debuginfo @@ -757,6 +764,7 @@ impl Profile { ( self.opt_level, self.lto, + self.codegen_backend, self.codegen_units, self.debuginfo, self.split_debuginfo, diff --git a/src/cargo/ops/cargo_config.rs b/src/cargo/ops/cargo_config.rs index ea63024d7fd..e84e84edf0d 100644 --- a/src/cargo/ops/cargo_config.rs +++ b/src/cargo/ops/cargo_config.rs @@ -51,13 +51,11 @@ pub struct GetOptions<'a> { } pub fn get(config: &Config, opts: &GetOptions<'_>) -> CargoResult<()> { - if opts.show_origin { - if !matches!(opts.format, ConfigFormat::Toml) { - bail!( - "the `{}` format does not support --show-origin, try the `toml` format instead", - opts.format - ); - } + if opts.show_origin && !matches!(opts.format, ConfigFormat::Toml) { + bail!( + "the `{}` format does not support --show-origin, try the `toml` format instead", + opts.format + ); } let key = match opts.key { Some(key) => ConfigKey::from_str(key), diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index 8965b89480b..e612fc4b9ec 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -211,20 +211,18 @@ fn install_one( specify an alternate source", src.path().display() ); + } else if src.path().join("cargo.toml").exists() { + bail!( + "`{}` does not contain a Cargo.toml file, but found cargo.toml please try to rename it to Cargo.toml. \ + --path must point to a directory containing a Cargo.toml file.", + src.path().display() + ) } else { - if src.path().join("cargo.toml").exists() { - bail!( - "`{}` does not contain a Cargo.toml file, but found cargo.toml please try to rename it to Cargo.toml. \ - --path must point to a directory containing a Cargo.toml file.", - src.path().display() - ) - } else { - bail!( - "`{}` does not contain a Cargo.toml file. \ - --path must point to a directory containing a Cargo.toml file.", - src.path().display() - ) - } + bail!( + "`{}` does not contain a Cargo.toml file. \ + --path must point to a directory containing a Cargo.toml file.", + src.path().display() + ) } } select_pkg( diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index fbf56eae7a5..9e6cebc9f11 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -602,15 +602,13 @@ impl Summaries { // present and considered fresh this is where the debug assertions // actually happens to verify that our cache is indeed fresh and // computes exactly the same value as before. - if cfg!(debug_assertions) && cache_contents.is_some() { - if cache_bytes != cache_contents { - panic!( - "original cache contents:\n{:?}\n\ - does not equal new cache contents:\n{:?}\n", - cache_contents.as_ref().map(|s| String::from_utf8_lossy(s)), - cache_bytes.as_ref().map(|s| String::from_utf8_lossy(s)), - ); - } + if cfg!(debug_assertions) && cache_contents.is_some() && cache_bytes != cache_contents { + panic!( + "original cache contents:\n{:?}\n\ + does not equal new cache contents:\n{:?}\n", + cache_contents.as_ref().map(|s| String::from_utf8_lossy(s)), + cache_bytes.as_ref().map(|s| String::from_utf8_lossy(s)), + ); } // Once we have our `cache_bytes` which represents the `Summaries` we're diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index 61f73ffae1c..9e893928850 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -6,11 +6,12 @@ use crate::sources::CRATES_IO_REGISTRY; use crate::util::important_paths::find_root_manifest_for_wd; use crate::util::interning::InternedString; use crate::util::restricted_names::is_glob_pattern; +use crate::util::toml::{StringOrVec, TomlProfile}; +use crate::util::validate_package_name; use crate::util::{ print_available_benches, print_available_binaries, print_available_examples, print_available_packages, print_available_tests, }; -use crate::util::{toml::TomlProfile, validate_package_name}; use crate::CargoResult; use anyhow::bail; use cargo_util::paths; @@ -715,17 +716,9 @@ pub fn values_os(args: &ArgMatches<'_>, name: &str) -> Vec { args._values_of_os(name) } -#[derive(PartialEq, PartialOrd, Eq, Ord)] +#[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum CommandInfo { - BuiltIn { name: String, about: Option }, - External { name: String, path: PathBuf }, -} - -impl CommandInfo { - pub fn name(&self) -> &str { - match self { - CommandInfo::BuiltIn { name, .. } => name, - CommandInfo::External { name, .. } => name, - } - } + BuiltIn { about: Option }, + External { path: PathBuf }, + Alias { target: StringOrVec }, } diff --git a/src/cargo/util/config/target.rs b/src/cargo/util/config/target.rs index a55ad84c25d..d259b970633 100644 --- a/src/cargo/util/config/target.rs +++ b/src/cargo/util/config/target.rs @@ -72,14 +72,12 @@ pub(super) fn get_target_applies_to_host(config: &Config) -> CargoResult { } else { Ok(!config.cli_unstable().host_config) } + } else if config.cli_unstable().host_config { + anyhow::bail!( + "the -Zhost-config flag requires the -Ztarget-applies-to-host flag to be set" + ); } else { - if config.cli_unstable().host_config { - anyhow::bail!( - "the -Zhost-config flag requires the -Ztarget-applies-to-host flag to be set" - ); - } else { - Ok(true) - } + Ok(true) } } diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index e32160ea2b3..6b4f5eac154 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -433,6 +433,7 @@ pub enum U32OrBool { pub struct TomlProfile { pub opt_level: Option, pub lto: Option, + pub codegen_backend: Option, pub codegen_units: Option, pub debug: Option, pub split_debuginfo: Option, @@ -491,12 +492,12 @@ impl TomlProfile { ) -> CargoResult<()> { if let Some(ref profile) = self.build_override { features.require(Feature::profile_overrides())?; - profile.validate_override("build-override")?; + profile.validate_override("build-override", features)?; } if let Some(ref packages) = self.package { features.require(Feature::profile_overrides())?; for profile in packages.values() { - profile.validate_override("package")?; + profile.validate_override("package", features)?; } } @@ -562,6 +563,18 @@ impl TomlProfile { if self.strip.is_some() { features.require(Feature::strip())?; } + + if let Some(codegen_backend) = &self.codegen_backend { + features.require(Feature::codegen_backend())?; + if codegen_backend.contains(|c: char| !c.is_ascii_alphanumeric() && c != '_') { + bail!( + "`profile.{}.codegen-backend` setting of `{}` is not a valid backend name.", + name, + codegen_backend, + ); + } + } + Ok(()) } @@ -642,7 +655,7 @@ impl TomlProfile { Ok(()) } - fn validate_override(&self, which: &str) -> CargoResult<()> { + fn validate_override(&self, which: &str, features: &Features) -> CargoResult<()> { if self.package.is_some() { bail!("package-specific profiles cannot be nested"); } @@ -658,6 +671,9 @@ impl TomlProfile { if self.rpath.is_some() { bail!("`rpath` may not be specified in a `{}` profile", which) } + if self.codegen_backend.is_some() { + features.require(Feature::codegen_backend())?; + } Ok(()) } @@ -671,6 +687,10 @@ impl TomlProfile { self.lto = Some(v.clone()); } + if let Some(v) = profile.codegen_backend { + self.codegen_backend = Some(v); + } + if let Some(v) = profile.codegen_units { self.codegen_units = Some(v); } @@ -740,7 +760,9 @@ impl TomlProfile { } } -#[derive(Clone, Debug, Serialize, Eq, PartialEq)] +/// A StringOrVec can be parsed from either a TOML string or array, +/// but is always stored as a vector. +#[derive(Clone, Debug, Serialize, Eq, PartialEq, PartialOrd, Ord)] pub struct StringOrVec(Vec); impl<'de> de::Deserialize<'de> for StringOrVec { @@ -777,6 +799,12 @@ impl<'de> de::Deserialize<'de> for StringOrVec { } } +impl StringOrVec { + pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, String> { + self.0.iter() + } +} + #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] #[serde(untagged, expecting = "expected a boolean or a string")] pub enum StringOrBool { diff --git a/src/doc/src/reference/pkgid-spec.md b/src/doc/src/reference/pkgid-spec.md index c2d613ab37c..7ac32bf0e4b 100644 --- a/src/doc/src/reference/pkgid-spec.md +++ b/src/doc/src/reference/pkgid-spec.md @@ -49,7 +49,7 @@ 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.1` | `cargo-platform` | `0.1.1` | +| `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 --git a/src/doc/src/reference/semver.md b/src/doc/src/reference/semver.md index 2659012608c..0404efdcfb2 100644 --- a/src/doc/src/reference/semver.md +++ b/src/doc/src/reference/semver.md @@ -943,7 +943,7 @@ pub fn foo() {} use updated_crate::foo; fn main() { - foo::(); // Error: this function takes 2 type arguments but only 1 type argument was supplied + foo::(); // Error: this function takes 2 generic arguments but 1 generic argument was supplied } ``` diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 0eafbd0e5fe..6bdc2ac582e 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1406,3 +1406,21 @@ environment variables. The `rust-version` field in `Cargo.toml` has been stabilized in the 1.56 release. See the [rust-version field](manifest.html#the-rust-version-field) for more information on using the `rust-version` field and the `--ignore-rust-version` option. + +### codegen-backend + +The `codegen-backend` feature makes it possible to select the codegen backend used by rustc using a +profile. + +Example: + +```toml +[package] +name = "foo" + +[dependencies] +serde = "1.0.117" + +[profile.dev.package.foo] +codegen-backend = "cranelift" +``` diff --git a/tests/testsuite/cargo_command.rs b/tests/testsuite/cargo_command.rs index 492f4c0aae9..574a6c94e78 100644 --- a/tests/testsuite/cargo_command.rs +++ b/tests/testsuite/cargo_command.rs @@ -1,63 +1,16 @@ //! Tests for custom cargo commands and other global command features. use std::env; -use std::fs::{self, File}; +use std::fs; use std::io::Read; use std::path::{Path, PathBuf}; use std::process::Stdio; use std::str; use cargo_test_support::cargo_process; -use cargo_test_support::paths::{self, CargoPathExt}; +use cargo_test_support::paths; use cargo_test_support::registry::Package; -use cargo_test_support::{basic_bin_manifest, basic_manifest, cargo_exe, project, Project}; - -#[cfg_attr(windows, allow(dead_code))] -enum FakeKind<'a> { - Executable, - Symlink { target: &'a Path }, -} - -/// Adds an empty file with executable flags (and platform-dependent suffix). -// -// TODO: move this to `Project` if other cases using this emerge. -fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind<'_>) -> Project { - let path = proj - .root() - .join(dir) - .join(&format!("{}{}", name, env::consts::EXE_SUFFIX)); - path.parent().unwrap().mkdir_p(); - match *kind { - FakeKind::Executable => { - File::create(&path).unwrap(); - make_executable(&path); - } - FakeKind::Symlink { target } => { - make_symlink(&path, target); - } - } - return proj; - - #[cfg(unix)] - fn make_executable(p: &Path) { - use std::os::unix::prelude::*; - - let mut perms = fs::metadata(p).unwrap().permissions(); - let mode = perms.mode(); - perms.set_mode(mode | 0o111); - fs::set_permissions(p, perms).unwrap(); - } - #[cfg(windows)] - fn make_executable(_: &Path) {} - #[cfg(unix)] - fn make_symlink(p: &Path, t: &Path) { - ::std::os::unix::fs::symlink(t, p).expect("Failed to create symlink"); - } - #[cfg(windows)] - fn make_symlink(_: &Path, _: &Path) { - panic!("Not supported") - } -} +use cargo_test_support::{basic_bin_manifest, basic_manifest, cargo_exe, project, project_in_home}; fn path() -> Vec { env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect() @@ -79,7 +32,7 @@ fn list_commands_with_descriptions() { } #[cargo_test] -fn list_aliases_with_descriptions() { +fn list_builtin_aliases_with_descriptions() { let p = project().build(); p.cargo("--list") .with_stdout_contains(" b alias: build") @@ -89,15 +42,48 @@ fn list_aliases_with_descriptions() { .run(); } +#[cargo_test] +fn list_custom_aliases_with_descriptions() { + let p = project_in_home("proj") + .file( + &paths::home().join(".cargo").join("config"), + r#" + [alias] + myaliasstr = "foo --bar" + myaliasvec = ["foo", "--bar"] + "#, + ) + .build(); + + p.cargo("--list") + .with_stdout_contains(" myaliasstr foo --bar") + .with_stdout_contains(" myaliasvec foo --bar") + .run(); +} + +#[cargo_test] +fn list_dedupe() { + let p = project() + .executable(Path::new("path-test-1").join("cargo-dupe"), "") + .executable(Path::new("path-test-2").join("cargo-dupe"), "") + .build(); + + let mut path = path(); + path.push(p.root().join("path-test-1")); + path.push(p.root().join("path-test-2")); + let path = env::join_paths(path.iter()).unwrap(); + + p.cargo("--list") + .env("PATH", &path) + .with_stdout_contains_n(" dupe", 1) + .run(); +} + #[cargo_test] fn list_command_looks_at_path() { - let proj = project().build(); - let proj = fake_file( - proj, - Path::new("path-test"), - "cargo-1", - &FakeKind::Executable, - ); + let proj = project() + .executable(Path::new("path-test").join("cargo-1"), "") + .build(); let mut path = path(); path.push(proj.root().join("path-test")); @@ -114,19 +100,11 @@ fn list_command_looks_at_path() { ); } -// Windows and symlinks don't currently mix well. -#[cfg(unix)] #[cargo_test] fn list_command_resolves_symlinks() { - let proj = project().build(); - let proj = fake_file( - proj, - Path::new("path-test"), - "cargo-2", - &FakeKind::Symlink { - target: &cargo_exe(), - }, - ); + let proj = project() + .symlink(cargo_exe(), Path::new("path-test").join("cargo-2")) + .build(); let mut path = path(); path.push(proj.root().join("path-test")); diff --git a/tests/testsuite/unit_graph.rs b/tests/testsuite/unit_graph.rs index 977d04915c5..b61cb453f14 100644 --- a/tests/testsuite/unit_graph.rs +++ b/tests/testsuite/unit_graph.rs @@ -49,177 +49,183 @@ fn simple() { .masquerade_as_nightly_cargo() .with_json( r#"{ - "version": 1, + "roots": [ + 3 + ], "units": [ { + "dependencies": [ + { + "extern_crate_name": "b", + "index": 1, + "noprelude": false, + "public": false + } + ], + "features": [ + "feata" + ], + "mode": "build", "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" + }, "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "a", "src_path": "[..]/a-1.0.0/src/lib.rs", - "edition": "2015", - "doc": true, - "doctest": true, "test": true - }, + } + }, + { + "dependencies": [ + { + "extern_crate_name": "c", + "index": 2, + "noprelude": false, + "public": false + } + ], + "features": [ + "featb" + ], + "mode": "build", + "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "feata" - ], - "dependencies": [ - { - "index": 1, - "extern_crate_name": "b", - "public": false, - "noprelude": false - } - ] - }, - { - "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "b", "src_path": "[..]/b-1.0.0/src/lib.rs", - "edition": "2015", - "doc": true, - "doctest": true, "test": true - }, + } + }, + { + "dependencies": [], + "features": [ + "featc" + ], + "mode": "build", + "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "featb" - ], - "dependencies": [ - { - "index": 2, - "extern_crate_name": "c", - "public": false, - "noprelude": false - } - ] - }, - { - "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "c", "src_path": "[..]/c-1.0.0/src/lib.rs", - "edition": "2015", - "test": true, - "doc": true, - "doctest": true - }, + "test": true + } + }, + { + "dependencies": [ + { + "extern_crate_name": "a", + "index": 0, + "noprelude": false, + "public": false + } + ], + "features": [], + "mode": "build", + "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "featc" - ], - "dependencies": [] - }, - { - "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "foo", "src_path": "[..]/foo/src/lib.rs", - "edition": "2015", - "test": true, - "doc": true, - "doctest": true - }, - "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", - "codegen_units": null, - "debuginfo": 2, - "debug_assertions": true, - "overflow_checks": true, - "rpath": false, - "incremental": false, - "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" - }, - "platform": null, - "mode": "build", - "features": [], - "dependencies": [ - { - "index": 0, - "extern_crate_name": "a", - "public": false, - "noprelude": false - } - ] + "test": true + } } ], - "roots": [3] + "version": 1 } "#, )