Skip to content

Commit

Permalink
Merge pull request #21 from sgasse/sgasse/feature/exclude
Browse files Browse the repository at this point in the history
Add flag to exclude specified workspace members
  • Loading branch information
hdoordt authored Nov 1, 2024
2 parents b598b71 + 3589f38 commit 1aa5a8a
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 9 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ anyhow = "1.0.80"
clap = { version = "4", features = ["derive"] }
guppy = "0.17.5"
fs-err = "2.11.0"
cargo-manifest = "0.14.0"
cargo-manifest = "0.16.0"
toml = "0.8.10"
semver = "1.0.22"
toml_edit = "0.22.6"
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ It collects all the dependencies in your workspace, determines which ones can be
the `[workspace.dependencies]` section of the root `Cargo.toml`. It also takes care of updating the members'
`Cargo.toml` files, setting the correct `features` field for each package.

To exclude workspace members from the autoinherit process, you can either pass their packgage names as an
option like so:

```bash
cargo autoinherit -e cargo-inherit-test-web
```

or you can define the exclusion in the workspace metadata:

```toml
# Cargo.toml
[workspace]
members = [
"cli",
"config",
"db",
"web",
"macros"
]

[workspace.metadata.cargo-autoinherit]
# Skip cargo-autoinherit for these packages
exclude-members = [
"cargo-autoinherit-test-web" # <= This member will be excluded
]
```

## Installation

You can find prebuilt binaries on the [Releases page](https://github.com/mainmatter/cargo-autoinherit/releases).
Expand Down
66 changes: 61 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::dedup::MinimalVersionSet;
use anyhow::Context;
use cargo_manifest::{Dependency, DependencyDetail, DepsSet, Manifest};
use anyhow::{anyhow, Context};
use cargo_manifest::{Dependency, DependencyDetail, DepsSet, Manifest, Workspace};
use guppy::VersionReq;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Formatter;
use toml_edit::{Array, Key};

Expand All @@ -15,6 +15,46 @@ pub struct AutoInheritConf {
help = "Represents inherited dependencies as `package.workspace = true` if possible."
)]
pub prefer_simple_dotted: bool,
/// Package name(s) of workspace member(s) to exclude.
#[arg(short, long)]
exclude_members: Vec<String>,
}

#[derive(Debug, Default)]
struct AutoInheritMetadata {
exclude_members: Vec<String>,
}

impl AutoInheritMetadata {
fn from_workspace(workspace: &Workspace<toml::Table>) -> Result<Self, anyhow::Error> {
fn error() -> anyhow::Error {
anyhow!("Excpected value of `exclude` in `workspace.metadata.cargo-autoinherit` to be an array of strings")
}

let Some(exclude) = workspace
.metadata
.as_ref()
.and_then(|m| m.get("cargo-autoinherit"))
.and_then(|v| v.as_table())
.and_then(|t| t.get("exclude-members").or(t.get("exclude_members")))
else {
return Ok(Self::default());
};

let exclude: Vec<String> = match exclude {
toml::Value::Array(excluded) => excluded
.iter()
.map(|v| v.as_str().ok_or_else(error).map(|s| s.to_string()))
.try_fold(Vec::with_capacity(excluded.len()), |mut res, item| {
res.push(item?);
Ok::<_, anyhow::Error>(res)
})?,
_ => return Err(error()),
};
Ok(Self {
exclude_members: exclude,
})
}
}

/// Rewrites a `path` dependency as being absolute, based on a given path
Expand Down Expand Up @@ -76,15 +116,15 @@ macro_rules! get_either_table_mut {
};
}

pub fn auto_inherit(conf: &AutoInheritConf) -> Result<(), anyhow::Error> {
pub fn auto_inherit(conf: AutoInheritConf) -> Result<(), anyhow::Error> {
let metadata = guppy::MetadataCommand::new().exec().context(
"Failed to execute `cargo metadata`. Was the command invoked inside a Rust project?",
)?;
let graph = metadata
.build_graph()
.context("Failed to build package graph")?;
let workspace_root = graph.workspace().root();
let mut root_manifest: Manifest = {
let mut root_manifest: Manifest<toml::Value, toml::Table> = {
let contents = fs_err::read_to_string(workspace_root.join("Cargo.toml").as_std_path())
.context("Failed to read root manifest")?;
toml::from_str(&contents).context("Failed to parse root manifest")?
Expand All @@ -97,6 +137,13 @@ pub fn auto_inherit(conf: &AutoInheritConf) -> Result<(), anyhow::Error> {
)
};

let autoinherit_metadata = AutoInheritMetadata::from_workspace(workspace)?;
let excluded_members = BTreeSet::from_iter(
conf.exclude_members
.into_iter()
.chain(autoinherit_metadata.exclude_members),
);

let mut package_name2specs: BTreeMap<String, Action> = BTreeMap::new();
if let Some(deps) = &mut workspace.dependencies {
rewrite_dep_paths_as_absolute(deps.values_mut(), workspace_root);
Expand All @@ -106,7 +153,12 @@ pub fn auto_inherit(conf: &AutoInheritConf) -> Result<(), anyhow::Error> {
for member_id in graph.workspace().member_ids() {
let package = graph.metadata(member_id)?;
assert!(package.in_workspace());

let mut manifest: Manifest = {
if excluded_members.contains(package.name()) {
println!("Excluded workspace member `{}`", package.name());
continue;
}
let contents = fs_err::read_to_string(package.manifest_path().as_std_path())
.context("Failed to read root manifest")?;
toml::from_str(&contents).context("Failed to parse root manifest")?
Expand Down Expand Up @@ -193,6 +245,10 @@ pub fn auto_inherit(conf: &AutoInheritConf) -> Result<(), anyhow::Error> {
// Inherit new "shared" dependencies in each member's manifest
for member_id in graph.workspace().member_ids() {
let package = graph.metadata(member_id)?;
if excluded_members.contains(package.name()) {
continue;
}

let manifest_contents = fs_err::read_to_string(package.manifest_path().as_std_path())
.context("Failed to read root manifest")?;
let manifest: Manifest =
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ pub enum CargoInvocation {
fn main() -> Result<(), anyhow::Error> {
let cli = CliWrapper::parse();
let CargoInvocation::AutoInherit(conf) = cli.command;
auto_inherit(&conf)
auto_inherit(conf)
}

0 comments on commit 1aa5a8a

Please sign in to comment.