#![warn(rust_2018_idioms)]
use cargo_metadata::MetadataCommand;
use difference::assert_diff;
use duct::cmd;
use std::{
env, fs, io,
path::Path,
str::{self, Utf8Error},
};
use tempdir::TempDir;
use termcolor::NoColor;
#[test]
fn normal() -> anyhow::Result<()> {
let tempdir = TempDir::new("cargo-member-test-include-normal")?;
fs::write(tempdir.path().join("Cargo.toml"), ORIGINAL)?;
cargo_new(&tempdir.path().join("a"))?;
cargo_new(&tempdir.path().join("b"))?;
let mut stderr = vec![];
cargo_member::Include::new(tempdir.path(), &[tempdir.path().join("b")])
.force(false)
.dry_run(false)
.stderr(NoColor::new(&mut stderr))
.exec()?;
assert_manifest(&tempdir.path().join("Cargo.toml"), EXPECTED_MANIFEST)?;
assert_stderr(
&stderr,
&EXPECTED_STDERR.replace("{}", &tempdir.path().join("Cargo.lock").to_string_lossy()),
)?;
cargo_metadata(&tempdir.path().join("Cargo.toml"), &["--locked"])?;
return Ok(());
static ORIGINAL: &str = r#"[workspace]
members = ["a"]
exclude = ["b"]
"#;
static EXPECTED_MANIFEST: &str = r#"[workspace]
members = ["a", "b"]
exclude = []
"#;
static EXPECTED_STDERR: &str = r#" Adding "b" to `workspace.members`
Removing "b" from `workspace.exclude`
Updating {}
"#;
}
#[test]
fn force_nonexisting() -> anyhow::Result<()> {
let tempdir = TempDir::new("cargo-member-test-include-force-nonexisting")?;
fs::write(tempdir.path().join("Cargo.toml"), ORIGINAL)?;
let mut stderr = vec![];
cargo_member::Include::new(tempdir.path(), &[tempdir.path().join("nonexisting")])
.force(true)
.dry_run(false)
.stderr(NoColor::new(&mut stderr))
.exec()?;
assert_manifest(&tempdir.path().join("Cargo.toml"), EXPECTED_MANIFEST)?;
assert_stderr(&stderr, EXPECTED_STDERR)?;
cargo_metadata(&tempdir.path().join("Cargo.toml"), &[]).unwrap_err();
return Ok(());
static ORIGINAL: &str = r#"[workspace]
members = []
exclude = []
"#;
static EXPECTED_MANIFEST: &str = r#"[workspace]
members = ["nonexisting"]
exclude = []
"#;
static EXPECTED_STDERR: &str = r#" Adding "nonexisting" to `workspace.members`
"#;
}
#[test]
fn dry_run() -> anyhow::Result<()> {
let tempdir = TempDir::new("cargo-member-test-include-dry-run")?;
fs::write(tempdir.path().join("Cargo.toml"), MANIFEST)?;
cargo_new(&tempdir.path().join("a"))?;
cargo_new(&tempdir.path().join("b"))?;
cargo_metadata(&tempdir.path().join("Cargo.toml"), &[])?;
let mut stderr = vec![];
cargo_member::Include::new(tempdir.path(), &[tempdir.path().join("b")])
.force(false)
.dry_run(true)
.stderr(NoColor::new(&mut stderr))
.exec()?;
assert_manifest(&tempdir.path().join("Cargo.toml"), MANIFEST)?;
assert_stderr(&stderr, EXPECTED_STDERR)?;
cargo_metadata(&tempdir.path().join("Cargo.toml"), &["--locked"])?;
return Ok(());
static MANIFEST: &str = r#"[workspace]
members = ["a"]
exclude = ["b"]
"#;
static EXPECTED_STDERR: &str = r#" Adding "b" to `workspace.members`
Removing "b" from `workspace.exclude`
warning: `workspace` unchanged
warning: not modifying the manifest due to dry run
"#;
}
fn cargo_new(path: &Path) -> io::Result<()> {
let cargo_exe = env::var("CARGO").unwrap();
cmd!(cargo_exe, "new", "-q", "--vcs", "none", path).run()?;
Ok(())
}
fn assert_manifest(manifest_path: &Path, expected: &str) -> io::Result<()> {
let modified = fs::read_to_string(manifest_path)?;
assert_diff!(expected, &modified, "\n", 0);
Ok(())
}
fn assert_stderr(stderr: &[u8], expected: &str) -> std::result::Result<(), Utf8Error> {
assert_diff!(expected, str::from_utf8(stderr)?, "\n", 0);
Ok(())
}
fn cargo_metadata(manifest_path: &Path, opts: &[&str]) -> cargo_metadata::Result<()> {
let opts = opts
.iter()
.copied()
.map(ToOwned::to_owned)
.collect::<Vec<_>>();
MetadataCommand::new()
.manifest_path(manifest_path)
.other_options(opts.iter().map(ToOwned::to_owned).collect::<Vec<_>>())
.exec()
.map(drop)
}