History

FAIL: try to auto-udpate crates index with lifetime crazyness (#234)

Even though it could work, it's too complicated.

Sebastian Thiel committed 5 years ago

Commit 82075e81 parent a4a53767 files · +172 −71Browse files

Unified · Split

7 files
  1. cargo-smart-release/src/changelog/init.rs +7 −7
  2. cargo-smart-release/src/command/changelog.rs +8 −5
  3. cargo-smart-release/src/command/release/mod.rs +38 −20
  4. cargo-smart-release/src/git/history.rs +5 −4
  5. cargo-smart-release/src/git/mod.rs +38 −2
  6. cargo-smart-release/src/traverse.rs +51 −29
  7. cargo-smart-release/src/version.rs +25 −4
cargo-smart-release/src/changelog/init.rs+7−7
@@ -37,10 +37,10 @@ pub struct Outcome { · 36 unmodified lines
3737 }
3838
3939 impl ChangeLog {
40− pub fn for_package_with_write_lock<'a>(
41− package: &'a Package,
40+ pub fn for_package_with_write_lock<'meta>(
41+ package: &'meta Package,
4242 history: &commit::History,
43− ctx: &'a crate::Context,
43+ ctx: &crate::git::ContextRef<'meta, '_>,
4444 selection: segment::Selection,
4545 ) -> anyhow::Result<Outcome> {
4646 let mut generated = ChangeLog::from_history_segments(
@@ -85,12 +85,12 @@ impl ChangeLog { · 38 unmodified lines
8585 })
8686 }
8787
88− pub fn for_crate_by_name_with_write_lock<'a>(
89− package: &'a Package,
88+ pub fn for_crate_by_name_with_write_lock<'meta>(
89+ package: &'meta Package,
9090 history: &commit::History,
91− ctx: &'a crate::Context,
91+ ctx: &crate::git::ContextRef<'meta, '_>,
9292 selection: segment::Selection,
93− ) -> anyhow::Result<(Outcome, &'a Package)> {
93+ ) -> anyhow::Result<(Outcome, &'meta Package)> {
9494 let out = Self::for_package_with_write_lock(package, history, ctx, selection)?;
9595 Ok((out, package))
9696 }
cargo-smart-release/src/command/changelog.rs+8−5
@@ -25,14 +25,17 @@ pub fn changelog(opts: Options, crates: Vec<String>) -> anyhow::Result<()> { · 24 unmodified lines
2525 let ctx = crate::Context::new(crates.clone(), force_history_segmentation, bump_spec, bump_spec)?;
2626 let crates: Vec<_> = {
2727 let add_production_crates = true;
28− let bump_only_when_needed = true;
28+ let bump_when_needed = true;
2929 let isolate_dependencies_from_breaking_changes = true;
3030 crate::traverse::dependencies(
3131 &ctx,
32− add_production_crates,
33− bump_only_when_needed,
34− isolate_dependencies_from_breaking_changes,
35− dependencies,
32+ &ctx.meta,
33+ crate::traverse::Options {
34+ add_production_crates,
35+ bump_when_needed,
36+ isolate_dependencies_from_breaking_changes,
37+ traverse_graph: dependencies,
38+ },
3639 )?
3740 .into_iter()
3841 .filter_map(|d| match d.mode {
cargo-smart-release/src/command/release/mod.rs+38−20
@@ -1,7 +1,9 @@
11 use std::collections::BTreeMap;
22
33 use anyhow::bail;
4+use cargo_metadata::Metadata;
45
6+use crate::traverse::Dependency;
57 use crate::{
68 changelog,
79 changelog::{write::Linkables, Section},
@@ -83,33 +85,49 @@ pub fn release(opts: Options, crates: Vec<String>, bump: BumpSpec, bump_dependen · 75 unmodified lines
8385 Ok(())
8486 }
8587
86−fn release_depth_first(ctx: Context, options: Options) -> anyhow::Result<()> {
87− let Options {
88− bump_when_needed,
89− dry_run,
90− allow_auto_publish_of_stable_crates,
91− dependencies: traverse_dependencies,
92− verbose,
93− isolate_dependencies_from_breaking_changes,
94− ..
95− } = options;
88+impl From<Options> for crate::traverse::Options {
89+ fn from(opts: Options) -> Self {
90+ Self {
91+ add_production_crates: opts.allow_auto_publish_of_stable_crates,
92+ bump_when_needed: opts.bump_when_needed,
93+ isolate_dependencies_from_breaking_changes: opts.isolate_dependencies_from_breaking_changes,
94+ traverse_graph: opts.dependencies,
95+ }
96+ }
97+}
98+
99+fn release_depth_first(mut ctx: Context, opts: Options) -> anyhow::Result<()> {
100+ let Options { verbose, dry_run, .. } = opts;
96101 let crates = {
97− crate::traverse::dependencies(
98− &ctx.base,
99− allow_auto_publish_of_stable_crates,
100− bump_when_needed,
101− isolate_dependencies_from_breaking_changes,
102− traverse_dependencies,
103− )
104− .and_then(|deps| present_and_validate_dependencies(&deps, &ctx, verbose, dry_run).map(|_| deps))?
102+ crate::traverse::dependencies((&ctx.base).into(), opts.into())
103+ .and_then(|crates| assure_crates_index_is_uptodate(crates, &mut ctx.base, opts.into()))
104+ .and_then(|crates| present_and_validate_dependencies(&crates, &ctx, verbose, dry_run).map(|_| crates))?
105105 };
106106
107− assure_working_tree_is_unchanged(options)?;
108− perform_release(&ctx, options, &crates)?;
107+ assure_working_tree_is_unchanged(opts)?;
108+ perform_release(&ctx, opts, &crates)?;
109109
110110 Ok(())
111111 }
112112
113+fn assure_crates_index_is_uptodate<'meta>(
114+ crates: Vec<Dependency<'meta>>,
115+ ctx: &mut crate::Context,
116+ opts: crate::traverse::Options,
117+) -> anyhow::Result<Vec<Dependency<'meta>>> {
118+ if let Some(dep) = crates
119+ .iter()
120+ .filter_map(|d| d.mode.version_adjustment_bump().map(|b| (d, b)))
121+ .find_map(|(d, b)| (b.next_release <= d.package.version).then(|| d))
122+ {
123+ log::warn!("Crate '{}' computed version not greater than the current package version. Updating crates index to assure correct results", dep.package.name);
124+ ctx.crates_index.update()?;
125+ crate::traverse::dependencies((&ctx.base).into(), opts)
126+ } else {
127+ Ok(crates)
128+ }
129+}
130+
113131 fn present_and_validate_dependencies(
114132 crates: &[traverse::Dependency<'_>],
115133 ctx: &Context,
cargo-smart-release/src/git/history.rs+5−4
@@ -6,7 +6,8 @@ use std::{ · 5 unmodified lines
66 };
77
88 use anyhow::bail;
9−use cargo_metadata::Package;
9+use cargo_metadata::camino::Utf8Path;
10+use cargo_metadata::{Metadata, Package};
1011 use git_repository as git;
1112 use git_repository::{
1213 bstr::ByteSlice,
@@ -14,12 +15,12 @@ use git_repository::{ · 1 unmodified line
1415 prelude::{CacheAccessExt, ObjectAccessExt, ObjectIdExt, ReferenceAccessExt, ReferenceExt},
1516 };
1617
18+use crate::git::ContextRef;
1719 use crate::{
1820 commit,
1921 commit::history::{Item, Segment},
2022 git::strip_tag_path,
2123 utils::{component_to_bytes, is_tag_name, is_tag_version, tag_prefix},
22− Context,
2324 };
2425
2526 pub enum SegmentScope {
@@ -99,7 +100,7 @@ pub fn collect(repo: &git::Easy) -> anyhow::Result<Option<commit::History>> { · 73 unmodified lines
99100 /// Return the head reference followed by all tags affecting `crate_name` as per our tag name rules, ordered by ancestry.
100101 pub fn crate_ref_segments<'h>(
101102 package: &Package,
102− ctx: &crate::Context,
103+ ctx: &ContextRef<'_, '_>,
103104 history: &'h commit::History,
104105 scope: SegmentScope,
105106 ) -> anyhow::Result<Vec<commit::history::Segment<'h>>> {
@@ -206,7 +207,7 @@ enum Filter<'a> { · 100 unmodified lines
206207 }
207208
208209 fn add_item_if_package_changed<'a>(
209− ctx: &Context,
210+ ctx: &ContextRef<'_, '_>,
210211 segment: &mut Segment<'a>,
211212 filter: &Filter<'_>,
212213 item: &'a Item,
cargo-smart-release/src/git/mod.rs+38−2
@@ -1,7 +1,7 @@
11 use std::{convert::TryInto, process::Command};
22
33 use anyhow::{anyhow, bail};
4−use cargo_metadata::{camino::Utf8Path, Package};
4+use cargo_metadata::{camino::Utf8Path, Metadata, Package};
55 use git_repository as git;
66 use git_repository::{
77 bstr::{BStr, ByteSlice},
@@ -14,13 +14,49 @@ use crate::utils::{component_to_bytes, tag_name}; · 6 unmodified lines
1414
1515 pub mod history;
1616
17+pub struct ContextRef<'meta, 'a> {
18+ pub meta: &'meta Metadata,
19+ pub repo: &'a git::Easy,
20+ pub root: &'a Utf8Path,
21+}
22+
23+impl<'meta, 'a> From<&crate::Context> for ContextRef<'meta, 'a> {
24+ fn from(v: &crate::Context) -> Self {
25+ Self {
26+ meta: &v.meta,
27+ repo: &v.repo,
28+ root: &v.root,
29+ }
30+ }
31+}
32+
33+impl<'meta, 'a> ContextRef<'meta, 'a> {
34+ pub(crate) fn repo_relative_path<'b>(&self, p: &'b Package) -> Option<&'b Utf8Path> {
35+ let dir = p
36+ .manifest_path
37+ .parent()
38+ .expect("parent of a file is always present")
39+ .strip_prefix(&self.root)
40+ .expect("workspace members are releative to the root directory");
41+
42+ if dir.as_os_str().is_empty() {
43+ None
44+ } else {
45+ dir.into()
46+ }
47+ }
48+}
49+
1750 #[derive(Clone, Debug)]
1851 pub enum PackageChangeKind {
1952 Untagged { wanted_tag_name: String },
2053 ChangedOrNew,
2154 }
2255
23−pub fn change_since_last_release(package: &Package, ctx: &crate::Context) -> anyhow::Result<Option<PackageChangeKind>> {
56+pub fn change_since_last_release(
57+ package: &Package,
58+ ctx: &ContextRef<'_, '_>,
59+) -> anyhow::Result<Option<PackageChangeKind>> {
2460 let version_tag_name = tag_name(package, &package.version, &ctx.repo);
2561 let mut tag_ref = match ctx.repo.try_find_reference(&version_tag_name)? {
2662 None => {
cargo-smart-release/src/traverse.rs+51−29
@@ -1,6 +1,6 @@
11 use std::collections::BTreeSet;
22
3−use cargo_metadata::{DependencyKind, Package, PackageId};
3+use cargo_metadata::{DependencyKind, Metadata, Package, PackageId};
44
55 use crate::{
66 git,
@@ -127,6 +127,31 @@ pub mod dependency { · 120 unmodified lines
127127 }
128128 }
129129
130+pub struct Options {
131+ pub add_production_crates: bool,
132+ pub bump_when_needed: bool,
133+ pub isolate_dependencies_from_breaking_changes: bool,
134+ pub traverse_graph: bool,
135+}
136+
137+pub struct ContextRef<'meta, 'a> {
138+ meta: &'meta Metadata,
139+ crate_names: &'a [String],
140+ git: crate::git::ContextRef<'meta, 'a>,
141+ version: crate::version::ContextRef<'a>,
142+}
143+
144+impl<'meta, 'a> From<&crate::Context> for ContextRef<'meta, 'a> {
145+ fn from(v: &Context) -> Self {
146+ Self {
147+ meta: &v.meta,
148+ crate_names: &v.crate_names,
149+ git: v.into(),
150+ version: v.into(),
151+ }
152+ }
153+}
154+
130155 #[derive(Clone, Debug)]
131156 pub struct Dependency<'meta> {
132157 pub package: &'meta Package,
@@ -134,13 +159,15 @@ pub struct Dependency<'meta> { · 1 unmodified line
134159 pub mode: dependency::Mode,
135160 }
136161
137−pub fn dependencies(
138− ctx: &crate::Context,
139− allow_auto_publish_of_stable_crates: bool,
140− bump_when_needed: bool,
141− isolate_dependencies_from_breaking_changes: bool,
142− traverse_graph: bool,
143−) -> anyhow::Result<Vec<Dependency<'_>>> {
162+pub fn dependencies<'meta>(
163+ ctx: &ContextRef<'meta, '_>,
164+ Options {
165+ add_production_crates,
166+ bump_when_needed,
167+ isolate_dependencies_from_breaking_changes,
168+ traverse_graph,
169+ }: Options,
170+) -> anyhow::Result<Vec<Dependency<'meta>>> {
144171 let mut seen = BTreeSet::new();
145172 let mut crates = Vec::new();
146173 for crate_name in &ctx.crate_names {
@@ -155,12 +182,12 @@ pub fn dependencies( · 8 unmodified lines
155182 &mut seen,
156183 &mut crates_this_round,
157184 package,
158− allow_auto_publish_of_stable_crates,
185+ add_production_crates,
159186 bump_when_needed,
160187 )?;
161188 }
162189
163− match git::change_since_last_release(package, ctx)? {
190+ match git::change_since_last_release(package, &ctx.git)? {
164191 Some(user_package_change) => {
165192 crates_this_round.push(Dependency {
166193 package,
@@ -169,7 +196,7 @@ pub fn dependencies( · 2 unmodified lines
169196 dependency::Mode::ToBePublished {
170197 adjustment: VersionAdjustment::Changed {
171198 change: user_package_change,
172− bump: version::bump_package(package, ctx, bump_when_needed)?,
199+ bump: version::bump_package(package, &ctx.version, bump_when_needed)?,
173200 },
174201 }
175202 } else {
@@ -196,17 +223,12 @@ pub fn dependencies( · 20 unmodified lines
196223 }
197224
198225 if isolate_dependencies_from_breaking_changes {
199− forward_propagate_breaking_changes_for_publishing(
200− ctx,
201− &mut crates,
202− bump_when_needed,
203− allow_auto_publish_of_stable_crates,
204− )?;
226+ forward_propagate_breaking_changes_for_publishing(ctx, &mut crates, bump_when_needed, add_production_crates)?;
205227 forward_propagate_breaking_changes_for_manifest_updates(
206228 ctx,
207229 &mut crates,
208230 bump_when_needed,
209− allow_auto_publish_of_stable_crates,
231+ add_production_crates,
210232 )?;
211233 }
212234 crates.extend(find_workspace_crates_depending_on_adjusted_crates(ctx, &crates));
@@ -226,7 +248,7 @@ fn merge_crates<'meta>(dest: &mut Vec<Dependency<'meta>>, src: Vec<Dependency<'m · 13 unmodified lines
226248 }
227249
228250 fn forward_propagate_breaking_changes_for_manifest_updates<'meta>(
229− ctx: &'meta Context,
251+ ctx: &ContextRef<'meta, '_>,
230252 crates: &mut Vec<Dependency<'meta>>,
231253 bump_when_needed: bool,
232254 allow_auto_publish_of_stable_crates: bool,
@@ -323,9 +345,9 @@ fn package_may_be_published(p: &Package) -> bool { · 90 unmodified lines
323345 p.publish.is_none()
324346 }
325347
326−fn forward_propagate_breaking_changes_for_publishing(
327− ctx: &Context,
328− mut crates: &mut Vec<Dependency<'_>>,
348+fn forward_propagate_breaking_changes_for_publishing<'meta>(
349+ ctx: &ContextRef<'meta, '_>,
350+ mut crates: &mut Vec<Dependency<'meta>>,
329351 bump_when_needed: bool,
330352 allow_auto_publish_of_stable_crates: bool,
331353 ) -> anyhow::Result<()> {
@@ -378,7 +400,7 @@ impl EditForPublish { · 46 unmodified lines
378400 fn apply(
379401 self,
380402 crates: &mut [Dependency<'_>],
381− ctx: &Context,
403+ ctx: &ContextRef<'_, '_>,
382404 bump_when_needed: bool,
383405 allow_auto_publish_of_stable_crates: bool,
384406 ) -> anyhow::Result<()> {
@@ -425,11 +447,11 @@ impl EditForPublish { · 40 unmodified lines
425447 }
426448 }
427449
428−fn breaking_version_bump(ctx: &Context, package: &Package, bump_when_needed: bool) -> anyhow::Result<Bump> {
450+fn breaking_version_bump(ctx: &ContextRef<'_, '_>, package: &Package, bump_when_needed: bool) -> anyhow::Result<Bump> {
429451 let breaking_spec = is_pre_release_version(&package.version)
430452 .then(|| BumpSpec::Minor)
431453 .unwrap_or(BumpSpec::Major);
432− version::bump_package_with_spec(package, breaking_spec, ctx, bump_when_needed)
454+ version::bump_package_with_spec(package, breaking_spec, &ctx.version, bump_when_needed)
433455 }
434456
435457 fn make_breaking(adjustment: &mut VersionAdjustment, breaking_bump: version::Bump, breaking_crate_names: Vec<String>) {
@@ -493,7 +515,7 @@ fn find_safety_bump_edits_backwards_from_crates_for_publish( · 57 unmodified lines
493515 }
494516
495517 fn depth_first_traversal<'meta>(
496− ctx: &'meta crate::Context,
518+ ctx: &ContextRef<'_, 'meta>,
497519 seen: &mut BTreeSet<&'meta PackageId>,
498520 crates: &mut Vec<Dependency<'meta>>,
499521 root: &Package,
@@ -519,7 +541,7 @@ fn depth_first_traversal<'meta>( · 19 unmodified lines
519541 bump_when_needed,
520542 )?;
521543
522− crates.push(match git::change_since_last_release(workspace_dependency, ctx)? {
544+ crates.push(match git::change_since_last_release(workspace_dependency, &ctx.git)? {
523545 Some(change) => {
524546 if is_pre_release_version(&workspace_dependency.version) || allow_auto_publish_of_stable_crates {
525547 Dependency {
@@ -528,7 +550,7 @@ fn depth_first_traversal<'meta>( · 2 unmodified lines
528550 mode: dependency::Mode::ToBePublished {
529551 adjustment: VersionAdjustment::Changed {
530552 change,
531− bump: version::bump_package(workspace_dependency, ctx, bump_when_needed)?,
553+ bump: version::bump_package(workspace_dependency, &ctx.version, bump_when_needed)?,
532554 },
533555 },
534556 }
@@ -557,7 +579,7 @@ fn depth_first_traversal<'meta>( · 22 unmodified lines
557579 }
558580
559581 fn find_workspace_crates_depending_on_adjusted_crates<'meta>(
560− ctx: &'meta Context,
582+ ctx: &ContextRef<'meta, '_>,
561583 crates: &[Dependency<'_>],
562584 ) -> Vec<Dependency<'meta>> {
563585 ctx.meta
cargo-smart-release/src/version.rs+25−4
@@ -1,7 +1,28 @@
1+use cargo_metadata::camino::Utf8Path;
12 use cargo_metadata::Package;
23 use semver::{Prerelease, Version};
34
4−use crate::Context;
5+pub struct ContextRef<'a> {
6+ pub crate_names: &'a [String],
7+ pub root: &'a Utf8Path,
8+ pub crates_index: &'a crates_index::Index,
9+ pub history: Option<&'a crate::commit::History>,
10+ pub bump: BumpSpec,
11+ pub bump_dependencies: BumpSpec,
12+}
13+
14+impl<'a> From<&crate::Context> for ContextRef<'a> {
15+ fn from(v: &crate::Context) -> Self {
16+ Self {
17+ crate_names: &v.crate_names,
18+ root: &v.root,
19+ crates_index: &v.crates_index,
20+ history: v.history.as_ref(),
21+ bump: v.bump,
22+ bump_dependencies: v.bump_dependencies,
23+ }
24+ }
25+}
526
627 #[derive(Copy, Clone)]
728 pub enum BumpSpec {
@@ -25,7 +46,7 @@ impl std::fmt::Display for BumpSpec { · 17 unmodified lines
2546 }
2647
2748 #[allow(clippy::ptr_arg)]
28−pub(crate) fn select_publishee_bump_spec(name: &String, ctx: &Context) -> BumpSpec {
49+pub(crate) fn select_publishee_bump_spec(name: &String, ctx: &ContextRef<'_>) -> BumpSpec {
2950 if ctx.crate_names.contains(name) {
3051 ctx.bump
3152 } else {
@@ -79,7 +100,7 @@ impl Bump { · 47 unmodified lines
79100 pub(crate) fn bump_package_with_spec(
80101 package: &Package,
81102 bump_spec: BumpSpec,
82− ctx: &Context,
103+ ctx: &ContextRef<'_>,
83104 bump_when_needed: bool,
84105 ) -> anyhow::Result<Bump> {
85106 let mut v = package.version.clone();
@@ -168,7 +189,7 @@ pub(crate) fn bump_package_with_spec( · 82 unmodified lines
168189 })
169190 }
170191
171−pub(crate) fn bump_package(package: &Package, ctx: &Context, bump_when_needed: bool) -> anyhow::Result<Bump> {
192+pub(crate) fn bump_package(package: &Package, ctx: &ContextRef<'_>, bump_when_needed: bool) -> anyhow::Result<Bump> {
172193 let bump_spec = select_publishee_bump_spec(&package.name, ctx);
173194 bump_package_with_spec(package, bump_spec, ctx, bump_when_needed)
174195 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t