@@ -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}
0 commit comments