Skip to content

Commit b977b5a

Browse files
CopilotByron
andcommitted
Move git index check to commit_changes and remove CommitLocksOutcome struct
Co-authored-by: Byron <[email protected]>
1 parent 94762a4 commit b977b5a

File tree

2 files changed

+46
-83
lines changed

2 files changed

+46
-83
lines changed

src/command/release/git.rs

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,44 @@ pub(in crate::command::release_impl) fn commit_changes<'a>(
1212
dry_run: bool,
1313
empty_commit_possible: bool,
1414
signoff: bool,
15-
new_changelogs: &[impl AsRef<Path>],
15+
changelog_paths: &[impl AsRef<Path>],
1616
ctx: &'a crate::Context,
1717
) -> anyhow::Result<Option<Id<'a>>> {
1818
// TODO: replace with gitoxide one day
19-
// Add new changelog files to git before committing, as `git commit -a` only stages tracked files
20-
if !new_changelogs.is_empty() {
21-
let mut add_cmd = Command::new("git");
22-
add_cmd.arg("add").arg("--");
23-
for path in new_changelogs {
24-
add_cmd.arg(path.as_ref());
25-
}
26-
log::trace!("{} run {:?}", will(dry_run), add_cmd);
27-
if !dry_run && !add_cmd.status()?.success() {
28-
let paths: Vec<_> = new_changelogs.iter().map(|p| p.as_ref().display().to_string()).collect();
29-
bail!("Failed to add new changelog files to git: {}", paths.join(", "));
19+
// Add changelog files that are not yet tracked in git index.
20+
// `git commit -am` only stages tracked files, so we need to explicitly add new ones.
21+
if !changelog_paths.is_empty() {
22+
let index = ctx.repo.open_index()?;
23+
let worktree = ctx.repo.workdir().expect("this is a worktree repository");
24+
25+
let untracked_paths: Vec<_> = changelog_paths
26+
.iter()
27+
.filter(|path| {
28+
// Convert absolute path to worktree-relative path with forward slashes
29+
path.as_ref()
30+
.strip_prefix(worktree)
31+
.ok()
32+
.map(|relative_path| {
33+
let relative_path_unix =
34+
gix::path::to_unix_separators(gix::path::into_bstr(relative_path));
35+
// Check if the path is NOT tracked in the git index
36+
index.entry_by_path(relative_path_unix.as_bstr()).is_none()
37+
})
38+
.unwrap_or(false)
39+
})
40+
.collect();
41+
42+
if !untracked_paths.is_empty() {
43+
let mut add_cmd = Command::new("git");
44+
add_cmd.arg("add").arg("--");
45+
for path in &untracked_paths {
46+
add_cmd.arg(path.as_ref());
47+
}
48+
log::trace!("{} run {:?}", will(dry_run), add_cmd);
49+
if !dry_run && !add_cmd.status()?.success() {
50+
let paths: Vec<_> = untracked_paths.iter().map(|p| p.as_ref().display().to_string()).collect();
51+
bail!("Failed to add new changelog files to git: {}", paths.join(", "));
52+
}
3053
}
3154
}
3255

@@ -190,33 +213,4 @@ mod tests {
190213
assert_eq!(captured_logs[0].level, Level::Trace);
191214
});
192215
}
193-
194-
#[test]
195-
#[ignore = "TBD: isolate properly, worked in PR, but stopped working in CI"]
196-
fn test_commit_changes_with_new_changelog() {
197-
let ctx = crate::Context::new(
198-
vec![],
199-
false,
200-
crate::version::BumpSpec::Auto,
201-
crate::version::BumpSpec::Auto,
202-
)
203-
.unwrap();
204-
let message = "commit message";
205-
let new_changelogs: &[&std::path::Path] = &[std::path::Path::new("/some/path/CHANGELOG.md")];
206-
testing_logger::setup();
207-
let _ = commit_changes(message, true, false, false, new_changelogs, &ctx).unwrap();
208-
testing_logger::validate(|captured_logs| {
209-
assert_eq!(captured_logs.len(), 2);
210-
assert_eq!(
211-
captured_logs[0].body,
212-
"WOULD run \"git\" \"add\" \"--\" \"/some/path/CHANGELOG.md\""
213-
);
214-
assert_eq!(captured_logs[0].level, Level::Trace);
215-
assert_eq!(
216-
captured_logs[1].body,
217-
"WOULD run \"git\" \"commit\" \"-am\" \"commit message\""
218-
);
219-
assert_eq!(captured_logs[1].level, Level::Trace);
220-
});
221-
}
222216
}

src/command/release/manifest.rs

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77

88
use anyhow::{bail, Context as ContextTrait};
99
use cargo_metadata::{camino::Utf8PathBuf, Package};
10-
use gix::{bstr::ByteSlice, lock::File, Id};
10+
use gix::{lock::File, Id};
1111
use semver::{Version, VersionReq};
1212

1313
use super::{cargo, git, Context, Options};
@@ -94,10 +94,13 @@ pub(in crate::command::release_impl) fn edit_version_and_fixup_dependent_crates_
9494

9595
preview_changelogs(ctx, &pending_changelogs, opts.clone())?;
9696

97-
let CommitLocksOutcome {
98-
bail_message,
99-
new_changelog_paths,
100-
} = commit_locks_and_generate_bail_message(
97+
// Collect all changelog paths before they are consumed by commit_locks_and_generate_bail_message
98+
let changelog_paths: Vec<std::path::PathBuf> = pending_changelogs
99+
.iter()
100+
.map(|(_, _, lock)| lock.resource_path().to_owned())
101+
.collect();
102+
103+
let bail_message = commit_locks_and_generate_bail_message(
101104
ctx,
102105
pending_changelogs,
103106
locks_by_manifest_path,
@@ -111,7 +114,7 @@ pub(in crate::command::release_impl) fn edit_version_and_fixup_dependent_crates_
111114
dry_run,
112115
!made_change,
113116
opts.signoff,
114-
&new_changelog_paths,
117+
&changelog_paths,
115118
&ctx.base,
116119
)?;
117120
if let Some(bail_message) = bail_message {
@@ -124,12 +127,6 @@ pub(in crate::command::release_impl) fn edit_version_and_fixup_dependent_crates_
124127
}
125128
}
126129

127-
struct CommitLocksOutcome {
128-
bail_message: Option<String>,
129-
/// Paths to changelog files that were newly created (not tracked by git)
130-
new_changelog_paths: Vec<std::path::PathBuf>,
131-
}
132-
133130
fn commit_locks_and_generate_bail_message(
134131
ctx: &Context,
135132
pending_changelogs: Vec<(&Package, bool, File)>,
@@ -143,32 +140,7 @@ fn commit_locks_and_generate_bail_message(
143140
allow_empty_release_message,
144141
..
145142
}: Options,
146-
) -> anyhow::Result<CommitLocksOutcome> {
147-
// Collect paths to changelog files not in the git index.
148-
// These need to be explicitly added to git since `git commit -am` only stages tracked files.
149-
let index = ctx.base.repo.open_index()?;
150-
let worktree = ctx
151-
.base
152-
.repo
153-
.workdir()
154-
.expect("this is a worktree repository");
155-
let new_changelog_paths: Vec<std::path::PathBuf> = pending_changelogs
156-
.iter()
157-
.filter_map(|(_, _, lock)| {
158-
let path = lock.resource_path();
159-
// Convert absolute path to worktree-relative path with forward slashes
160-
let relative_path = path.strip_prefix(worktree).ok()?;
161-
let relative_path_unix =
162-
gix::path::to_unix_separators(gix::path::into_bstr(relative_path));
163-
// Check if the path is tracked in the git index
164-
if index.entry_by_path(relative_path_unix.as_bstr()).is_none() {
165-
Some(path.to_owned())
166-
} else {
167-
None
168-
}
169-
})
170-
.collect();
171-
143+
) -> anyhow::Result<Option<String>> {
172144
let bail_message = if !dry_run {
173145
let mut packages_whose_changelogs_need_edits = None;
174146
let mut packages_which_might_be_fully_generated = None;
@@ -294,10 +266,7 @@ fn commit_locks_and_generate_bail_message(
294266
}
295267
None
296268
};
297-
Ok(CommitLocksOutcome {
298-
bail_message,
299-
new_changelog_paths,
300-
})
269+
Ok(bail_message)
301270
}
302271

303272
fn preview_changelogs(

0 commit comments

Comments
 (0)