@@ -123,16 +123,38 @@ pub fn get_closest_merge_commit(
123123 config : & GitConfig < ' _ > ,
124124 target_paths : & [ PathBuf ] ,
125125) -> Result < String , String > {
126- let mut git = Command :: new ( "git" ) ;
126+ // The need of `--first-parent` is inconsistent. It's sometimes required, sometimes not.
127+ // See https://github.com/rust-lang/rust/issues/101907#issuecomment-2677860377 for more
128+ // context.
129+ //
130+ // FIXME: This is so hacky, is there a more sane way to fix this problem?
131+ let result = match get_closest_merge_commit_impl ( git_dir, config, target_paths, true ) {
132+ // If the commit is empty, it's most likely because the first parent isn't from rust-lang/rust.
133+ // Fall back to the regular traversal.
134+ Ok ( commit) if commit. is_empty ( ) => {
135+ get_closest_merge_commit_impl ( git_dir, config, target_paths, false )
136+ }
137+ result => result,
138+ } ;
127139
128- if let Some ( git_dir) = git_dir {
129- git. current_dir ( git_dir) ;
130- }
140+ return result;
141+
142+ fn get_closest_merge_commit_impl (
143+ git_dir : Option < & Path > ,
144+ config : & GitConfig < ' _ > ,
145+ target_paths : & [ PathBuf ] ,
146+ follow_first_parent_only : bool ,
147+ ) -> Result < String , String > {
148+ let mut git = Command :: new ( "git" ) ;
149+
150+ if let Some ( git_dir) = git_dir {
151+ git. current_dir ( git_dir) ;
152+ }
131153
132- let channel = include_str ! ( "../../ci/channel" ) ;
154+ let channel = include_str ! ( "../../ci/channel" ) ;
133155
134- let merge_base = {
135- if CiEnv :: is_ci ( ) &&
156+ let merge_base = {
157+ if CiEnv :: is_ci ( ) &&
136158 // FIXME: When running on rust-lang managed CI and it's not a nightly build,
137159 // `git_upstream_merge_base` fails with an error message similar to this:
138160 // ```
@@ -141,28 +163,29 @@ pub fn get_closest_merge_commit(
141163 // ```
142164 // Investigate and resolve this issue instead of skipping it like this.
143165 ( channel == "nightly" || !CiEnv :: is_rust_lang_managed_ci_job ( ) )
144- {
145- git_upstream_merge_base ( config, git_dir) . unwrap ( )
146- } else {
147- // For non-CI environments, ignore rust-lang/rust upstream as it usually gets
148- // outdated very quickly.
149- "HEAD" . to_string ( )
166+ {
167+ git_upstream_merge_base ( config, git_dir) . unwrap ( )
168+ } else {
169+ // For non-CI environments, ignore rust-lang/rust upstream as it usually gets
170+ // outdated very quickly.
171+ "HEAD" . to_string ( )
172+ }
173+ } ;
174+
175+ git. args ( [ "rev-list" , & format ! ( "--author={}" , config. git_merge_commit_email) , "-n1" ] ) ;
176+
177+ if follow_first_parent_only {
178+ git. arg ( "--first-parent" ) ;
150179 }
151- } ;
152180
153- git. args ( [
154- "rev-list" ,
155- & format ! ( "--author={}" , config. git_merge_commit_email) ,
156- "-n1" ,
157- "--first-parent" ,
158- & merge_base,
159- ] ) ;
181+ git. arg ( merge_base) ;
160182
161- if !target_paths. is_empty ( ) {
162- git. arg ( "--" ) . args ( target_paths) ;
163- }
183+ if !target_paths. is_empty ( ) {
184+ git. arg ( "--" ) . args ( target_paths) ;
185+ }
164186
165- Ok ( output_result ( & mut git) ?. trim ( ) . to_owned ( ) )
187+ Ok ( output_result ( & mut git) ?. trim ( ) . to_owned ( ) )
188+ }
166189}
167190
168191/// Returns the files that have been modified in the current branch compared to the master branch.
0 commit comments