Skip to content

Commit

Permalink
Implement --package and --exclude
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Nov 1, 2019
1 parent 75bff8d commit 694b7bb
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 74 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ A tool to work around some limitations on cargo.
anyhow = "1.0.18"
termcolor = "1.0.5"
toml_edit = "0.1.5"
indexmap = "1.3.0"

[dev-dependencies]
easy-ext = "0.1.6"
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,6 @@ To install the current cargo-hack requires Rust 1.36 or later.

Unlike `cargo` ([rust-lang/cargo#3620], [rust-lang/cargo#4106], [rust-lang/cargo#4463], [rust-lang/cargo#4753], [rust-lang/cargo#5015], [rust-lang/cargo#5364], [rust-lang/cargo#6195]), it can also be applied to sub-crate.

* **`-p`**, **`--package`**

*Currently this flag is ignored.*

* **`--exclude`**

*Currently this flag is ignored.*

[rust-lang/cargo#3620]: https://github.com/rust-lang/cargo/issues/3620
[rust-lang/cargo#4106]: https://github.com/rust-lang/cargo/issues/4106
[rust-lang/cargo#4463]: https://github.com/rust-lang/cargo/issues/4463
Expand Down
5 changes: 4 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Some common cargo commands are (see all commands with --list):
)
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub(crate) struct Options {
pub(crate) first: Vec<String>,
pub(crate) second: Vec<String>,
Expand Down Expand Up @@ -310,6 +310,9 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Options> {
"'--ignore-non-exist-features' flag is deprecated, use '--ignore-unknown-features' flag instead"
);
}
if !exclude.is_empty() && workspace.is_none() {
bail!("--exclude can only be used together with --workspace")
}

res.map(|()| Options {
first,
Expand Down
74 changes: 38 additions & 36 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ mod term;
mod cli;
mod manifest;
mod process;
mod workspace;

use std::{env, ffi::OsString, fs, path::Path};

use anyhow::{bail, Context, Result};

use crate::{
cli::{Coloring, Options},
manifest::Manifest,
manifest::{find_root_manifest_for_wd, Manifest},
process::ProcessBuilder,
workspace::Workspace,
};

fn main() {
Expand Down Expand Up @@ -64,50 +66,50 @@ For more information try --help
if let Some(flag) = &args.workspace {
warn!(args.color, "`{}` flag for `cargo hack` is experimental", flag)
}
if !args.package.is_empty() {
warn!(args.color, "`--package` flag for `cargo hack` is currently ignored")
}
if !args.exclude.is_empty() {
warn!(args.color, "`--exclude` flag for `cargo hack` is currently ignored")
}

let current_dir = &env::current_dir()?;

let root_manifest = match &args.manifest_path {
let current_manifest = match &args.manifest_path {
Some(path) => Manifest::with_manifest_path(path)?,
None => Manifest::new(&manifest::find_root_manifest_for_wd(&current_dir)?)?,
None => Manifest::new(&find_root_manifest_for_wd(&current_dir)?)?,
};
let workspace = Workspace::new(&current_manifest)?;

exec_on_workspace(&args, &root_manifest)
exec_on_workspace(&args, &workspace)
}

fn exec_on_workspace(args: &Options, root_manifest: &Manifest) -> Result<()> {
let root_dir = root_manifest.dir();

if args.workspace.is_some() || root_manifest.is_virtual() {
root_manifest
.members()
.into_iter()
.flat_map(|v| v.iter().filter_map(|v| v.as_str()))
.map(Path::new)
.try_for_each(|mut dir| {
if let Ok(new) = dir.strip_prefix(".") {
dir = new;
}

let path = manifest::find_project_manifest_exact(&root_dir.join(dir))?;
let manifest = crate::Manifest::new(&path)?;

if root_manifest.path == manifest.path {
return Ok(());
}

exec_on_package(&manifest, args)
})?;
}
fn exec_on_workspace(args: &Options, workspace: &Workspace<'_>) -> Result<()> {
if args.workspace.is_some() {
for spec in &args.exclude {
if !workspace.members.contains_key(spec) {
warn!(
args.color,
"excluded package(s) {} not found in workspace `{}`",
spec,
workspace.current_manifest.dir().display()
);
}
}

if !root_manifest.is_virtual() {
exec_on_package(root_manifest, args)?;
for (_, manifest) in
workspace.members.iter().filter(|(spec, _)| !args.exclude.contains(spec))
{
exec_on_package(manifest, args)?;
}
} else if !args.package.is_empty() {
for spec in &args.package {
if let Some(manifest) = workspace.members.get(spec) {
exec_on_package(manifest, args)?;
} else {
bail!("package ID specification `{}` matched no packages", spec);
}
}
} else if workspace.current_manifest.is_virtual() {
for (_, manifest) in workspace.members.iter() {
exec_on_package(manifest, args)?;
}
} else if !workspace.current_manifest.is_virtual() {
exec_on_package(workspace.current_manifest, args)?;
}

Ok(())
Expand Down
15 changes: 6 additions & 9 deletions src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ use toml_edit::{Array, Document, Item as Value, Table};

use crate::Options;

const MANIFEST_FILE: &str = "Cargo.toml";

#[derive(Debug)]
#[derive(Clone, Debug)]
pub(crate) struct Manifest {
pub(crate) path: PathBuf,
pub(crate) raw: String,
Expand Down Expand Up @@ -48,7 +46,7 @@ impl Manifest {
}

pub(crate) fn with_manifest_path(path: &str) -> Result<Self> {
if !path.ends_with(MANIFEST_FILE) {
if !path.ends_with("Cargo.toml") {
bail!("the manifest-path must be a path to a Cargo.toml file");
}

Expand Down Expand Up @@ -116,7 +114,7 @@ pub(crate) fn remove_key_and_target_key(table: &mut Table, key: &str) {
/// Finds the root `Cargo.toml`.
pub(crate) fn find_root_manifest_for_wd(cwd: &Path) -> Result<PathBuf> {
for current in cwd.ancestors() {
let manifest = current.join(MANIFEST_FILE);
let manifest = current.join("Cargo.toml");
if manifest.exists() {
return Ok(manifest);
}
Expand All @@ -125,13 +123,12 @@ pub(crate) fn find_root_manifest_for_wd(cwd: &Path) -> Result<PathBuf> {
bail!("could not find `Cargo.toml` in `{}` or any parent directory", cwd.display())
}

/// Returns the path to the `MANIFEST_FILE` in `pwd`, if it exists.
/// Returns the path to the `Cargo.toml` in `pwd`, if it exists.
pub(crate) fn find_project_manifest_exact(pwd: &Path) -> Result<PathBuf> {
let manifest = pwd.join(MANIFEST_FILE);

let manifest = pwd.join("Cargo.toml");
if manifest.exists() {
Ok(manifest)
} else {
bail!("Could not find `{}` in `{}`", MANIFEST_FILE, pwd.display())
bail!("Could not find `Cargo.toml` in `{}`", pwd.display())
}
}
56 changes: 56 additions & 0 deletions src/workspace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::path::Path;

use anyhow::Result;
use indexmap::IndexMap;
use toml_edit::Item as Value;

use crate::manifest::{find_project_manifest_exact, Manifest};

pub(crate) struct Workspace<'a> {
/// This manifest is a manifest to where the current cargo subcommand was
/// invoked from.
pub(crate) current_manifest: &'a Manifest,

// Map of members in this workspace. Keys are their package names and values
// are their manifests.
pub(crate) members: IndexMap<String, Manifest>,
}

impl<'a> Workspace<'a> {
pub(crate) fn new(current_manifest: &'a Manifest) -> Result<Self> {
let mut members = IndexMap::new();
// TODO: The current cargo-hack doesn't try to find the root manifest
// after finding the current package's manifest.
// https://github.com/taiki-e/cargo-hack/issues/11
let root_dir = current_manifest.dir();
let mut inserted = false;

if let Some(workspace) = current_manifest.workspace() {
for mut dir in workspace
.get("members")
.and_then(Value::as_array)
.into_iter()
.flat_map(|v| v.iter().filter_map(|v| v.as_str()))
.map(Path::new)
{
if let Ok(new) = dir.strip_prefix(".") {
dir = new;
}

let path = find_project_manifest_exact(&root_dir.join(dir))?;
let manifest = Manifest::new(&path)?;

if current_manifest.path == manifest.path {
inserted = true;
}
members.insert(manifest.package_name().to_string(), manifest);
}
}

if !current_manifest.is_virtual() && !inserted {
members.insert(current_manifest.package_name().to_string(), current_manifest.clone());
}

Ok(Self { current_manifest, members })
}
}
Loading

0 comments on commit 694b7bb

Please sign in to comment.