Skip to content

Commit

Permalink
fully data-driven presentation of dependency tracking results… (#222)
Browse files Browse the repository at this point in the history
…which opens up much improved version handling and reporting, one line
per crate and not multiple.
  • Loading branch information
Byron committed Oct 17, 2021
1 parent 51a5d36 commit fd53e22
Show file tree
Hide file tree
Showing 18 changed files with 109 additions and 98 deletions.
2 changes: 1 addition & 1 deletion cargo-smart-release/src/command/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn changelog(opts: Options, crates: Vec<String>) -> anyhow::Result<()> {
let add_production_crates = true;
crate::traverse::dependencies(&ctx, add_production_crates)?
.into_iter()
.filter_map(|d| matches!(d.kind, dependency::Outcome::ToBePublished { .. }).then(|| d.package))
.filter_map(|d| matches!(d.mode, dependency::Mode::ToBePublished { .. }).then(|| d.package))
.collect()
} else {
ctx.crate_names
Expand Down
63 changes: 34 additions & 29 deletions cargo-smart-release/src/command/release/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ fn release_depth_first(ctx: Context, options: Options) -> anyhow::Result<()> {
.collect::<Result<Vec<_>, _>>()?
} else {
let dependencies = crate::traverse::dependencies(&ctx.base, options.allow_auto_publish_of_stable_crates)?;
present_dependencies(&dependencies, &ctx.base.crate_names, options.verbose);
present_dependencies(&dependencies, options.verbose);
dependencies
.into_iter()
.filter_map(|d| matches!(d.kind, dependency::Outcome::ToBePublished { .. }).then(|| d.package))
.filter_map(|d| matches!(d.mode, dependency::Mode::ToBePublished { .. }).then(|| d.package))
.collect()
};

Expand Down Expand Up @@ -158,47 +158,51 @@ fn release_depth_first(ctx: Context, options: Options) -> anyhow::Result<()> {
Ok(())
}

fn present_dependencies(deps: &[traverse::Dependency<'_>], provided_crate_names: &[String], verbose: bool) {
use dependency::{PublishReason, SkippedReason};
fn present_dependencies(deps: &[traverse::Dependency<'_>], verbose: bool) {
use dependency::{Kind, SkippedReason};
if verbose {
for dep in deps {
match &dep.kind {
dependency::Outcome::ToBePublished {
reason: PublishReason::UnpublishedDependencyOfUserSelection { wanted_tag_name },
match &dep.mode {
dependency::Mode::ToBePublished {
kind,
change_kind: crate::git::PackageChangeKind::Untagged { wanted_tag_name },
} => {
log::info!(
"Package '{}' wasn't tagged with {} yet and thus needs a release",
"{} '{}' wasn't tagged with {} yet and thus needs a release",
match kind {
Kind::UserSelection => "Provided package",
Kind::DependencyOfUserSelection => "Dependent package",
},
dep.package.name,
wanted_tag_name
);
}
dependency::Outcome::ToBePublished {
reason: PublishReason::ChangedDependencyOfUserSelection,
dependency::Mode::ToBePublished {
kind: Kind::DependencyOfUserSelection,
change_kind: crate::git::PackageChangeKind::ChangedOrNew,
} => {
log::info!(
"Adding '{}' v{} to set of published crates as it changed since last release",
"Dependent package '{}' v{} will be published as it changed since last release",
dep.package.name,
dep.package.version
);
}
dependency::Outcome::Skipped {
dependency::Mode::Skipped {
kind,
reason: SkippedReason::Unchanged,
} => {
if provided_crate_names.contains(&dep.package.name) {
log::info!(
"Skipping provided {} v{} hasn't changed since last released",
dep.package.name,
dep.package.version
);
} else {
log::info!(
"'{}' v{} - skipped release as it didn't change",
dep.package.name,
dep.package.version
);
}
log::info!(
"Skipped {} '{}' v{} as it didn't change since last release",
match kind {
Kind::UserSelection => "provided package",
Kind::DependencyOfUserSelection => "dependent package",
},
dep.package.name,
dep.package.version
);
}
dependency::Outcome::Skipped {
dependency::Mode::Skipped {
kind: _,
reason: SkippedReason::DeniedAutopublishOfProductionCrate,
} => {
log::warn!(
Expand All @@ -207,15 +211,16 @@ fn present_dependencies(deps: &[traverse::Dependency<'_>], provided_crate_names:
dep.package.version
);
}
dependency::Outcome::ToBePublished {
reason: PublishReason::UserSelected,
dependency::Mode::ToBePublished {
kind: Kind::UserSelection,
change_kind: _,
} => {}
}
}
} else {
let num_skipped = deps
.iter()
.filter(|dep| matches!(&dep.kind, dependency::Outcome::Skipped { .. }))
.filter(|dep| matches!(&dep.mode, dependency::Mode::Skipped { .. }))
.count();
if num_skipped != 0 {
log::info!(
Expand Down
2 changes: 1 addition & 1 deletion cargo-smart-release/src/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::utils::{component_to_bytes, tag_name};

pub mod history;

#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum PackageChangeKind {
Untagged { wanted_tag_name: String },
ChangedOrNew,
Expand Down
88 changes: 49 additions & 39 deletions cargo-smart-release/src/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,36 @@ use crate::{
};

pub mod dependency {
#[derive(Clone, Debug)]
pub enum PublishReason {
UserSelected,
ChangedDependencyOfUserSelection,
UnpublishedDependencyOfUserSelection { wanted_tag_name: String },
}

/// Skipped crates are always dependent ones
#[derive(Copy, Clone, Debug)]
pub enum SkippedReason {
Unchanged,
DeniedAutopublishOfProductionCrate,
}

#[derive(Clone, Debug)]
pub enum Outcome {
ToBePublished { reason: PublishReason },
Skipped { reason: SkippedReason },
pub enum Kind {
UserSelection,
DependencyOfUserSelection,
}

#[derive(Clone, Debug)]
pub enum Mode {
ToBePublished {
kind: Kind,
change_kind: crate::git::PackageChangeKind,
},
Skipped {
kind: Kind,
reason: SkippedReason,
},
}
}

#[derive(Debug)]
pub struct Dependency<'meta> {
pub package: &'meta Package,
pub kind: dependency::Outcome,
pub mode: dependency::Mode,
}

pub fn dependencies(ctx: &crate::Context, add_production_crates: bool) -> anyhow::Result<Vec<Dependency<'_>>> {
Expand All @@ -50,24 +56,32 @@ pub fn dependencies(ctx: &crate::Context, add_production_crates: bool) -> anyhow
let num_crates_for_publishing_without_dependencies = crates.len();
let current_skipped = depth_first_traversal(ctx, add_production_crates, &mut seen, &mut crates, package)?;
crates.extend(current_skipped);
if num_crates_for_publishing_without_dependencies == crates.len()
&& git::change_since_last_release(package, ctx)?.is_none()
{
crates.push(Dependency {
package,
kind: dependency::Outcome::Skipped {
reason: dependency::SkippedReason::Unchanged,
},
});
continue;

match git::change_since_last_release(package, ctx)? {
Some(user_package_change) => {
crates.push(Dependency {
package,
mode: dependency::Mode::ToBePublished {
kind: dependency::Kind::UserSelection,
change_kind: user_package_change,
},
});
seen.insert(&package.id);
}
None => {
let found_no_dependencies = num_crates_for_publishing_without_dependencies == crates.len();
if found_no_dependencies {
crates.push(Dependency {
package,
mode: dependency::Mode::Skipped {
kind: dependency::Kind::UserSelection,
reason: dependency::SkippedReason::Unchanged,
},
});
continue;
}
}
}
crates.push(Dependency {
package,
kind: dependency::Outcome::ToBePublished {
reason: dependency::PublishReason::UserSelected,
},
});
seen.insert(&package.id);
}
Ok(crates)
}
Expand Down Expand Up @@ -100,29 +114,25 @@ fn depth_first_traversal<'meta>(
if is_pre_release_version(&workspace_dependency.version) || add_production_crates {
crates.push(Dependency {
package: workspace_dependency,
kind: dependency::Outcome::ToBePublished {
reason: match change {
git::PackageChangeKind::ChangedOrNew => {
dependency::PublishReason::ChangedDependencyOfUserSelection
}
git::PackageChangeKind::Untagged { wanted_tag_name } => {
dependency::PublishReason::UnpublishedDependencyOfUserSelection { wanted_tag_name }
}
},
mode: dependency::Mode::ToBePublished {
kind: dependency::Kind::DependencyOfUserSelection,
change_kind: change,
},
});
} else {
crates.push(Dependency {
package: workspace_dependency,
kind: dependency::Outcome::Skipped {
mode: dependency::Mode::Skipped {
kind: dependency::Kind::DependencyOfUserSelection,
reason: dependency::SkippedReason::DeniedAutopublishOfProductionCrate,
},
});
}
} else {
skipped.push(Dependency {
package: workspace_dependency,
kind: dependency::Outcome::Skipped {
mode: dependency::Mode::Skipped {
kind: dependency::Kind::DependencyOfUserSelection,
reason: dependency::SkippedReason::Unchanged,
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Adding 'a' v0.8.0 to set of published crates as it changed since last release
[INFO ] Dependent package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[WARN ] The working tree has changes which will prevent a release with --execute unless --allow-dirty is also specified. The latter isn't recommended.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] Congratulations for the new release of 'b' 🎉
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Adding 'a' v0.8.0 to set of published crates as it changed since last release
[INFO ] Dependent package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[WARN ] The working tree has changes which will prevent a release with --execute unless --allow-dirty is also specified. The latter isn't recommended.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] WOULD modify existing changelog for 'a'.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[WARN ] The working tree has changes which will prevent a release with --execute unless --allow-dirty is also specified. The latter isn't recommended.
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.9.0.
[INFO ] Congratulations for the new release of 'a' 🎉
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.9.0.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] WOULD modify existing changelog for 'a'.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' minor version to 0.9.0 from 0.8.0 to signal breaking changes.
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.9.0.
[INFO ] Congratulations for the new release of 'a' 🎉
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Adding 'a' v0.8.0 to set of published crates as it changed since last release
[INFO ] Package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[INFO ] Adding 'b' v0.8.0 to set of published crates as it changed since last release
[INFO ] Dependent package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Dependent package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'c' wasn't tagged with c-v8.0.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' minor version to 0.9.0 from 0.8.0 to signal breaking changes.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] Auto-bumped 'b' patch version to 0.8.1 from 0.8.0.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' minor version to 0.9.0 from 0.8.0 to signal breaking changes.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] WOULD modify existing changelog for 'a'.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' patch version to 0.8.1 from 0.8.0 to signal new features due to 'feat:' in commit message.
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.8.1.
[INFO ] Congratulations for the new release of 'a' 🎉
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' patch version to 0.8.1 from 0.8.0.
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.8.1.
[INFO ] Congratulations for the new release of 'a' 🎉
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[WARN ] The working tree has changes which will prevent a release with --execute unless --allow-dirty is also specified. The latter isn't recommended.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] WOULD modify existing changelog for 'a'.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[WARN ] The working tree has changes which will prevent a release with --execute unless --allow-dirty is also specified. The latter isn't recommended.
[INFO ] Congratulations for the new release of 'a' 🎉
[INFO ] WOULD modify existing changelog for 'a'.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
[WARN ] Consider running with --update-crates-index to assure bumping on demand uses the latest information
[WARN ] Crates.io index doesn't exist. Consider using --update-crates-index to help determining if release versions are published already
[INFO ] Package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Adding 'a' v0.8.0 to set of published crates as it changed since last release
[INFO ] Package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[INFO ] Adding 'b' v0.8.0 to set of published crates as it changed since last release
[INFO ] Dependent package 'a' wasn't tagged with a-v0.8.0 yet and thus needs a release
[INFO ] Dependent package 'b' wasn't tagged with b-v0.8.0 yet and thus needs a release
[INFO ] Provided package 'c' wasn't tagged with c-v8.0.0 yet and thus needs a release
[INFO ] Auto-bumped 'a' patch version to 0.8.1 from 0.8.0.
[INFO ] Using current version 0.8.0 of crate a instead of bumped one 0.8.1.
[INFO ] Congratulations for the new release of 'a' 🎉
Expand Down
Loading

0 comments on commit fd53e22

Please sign in to comment.