@@ -123,16 +123,38 @@ pub fn get_closest_merge_commit(
123
123
config : & GitConfig < ' _ > ,
124
124
target_paths : & [ PathBuf ] ,
125
125
) -> 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
+ } ;
127
139
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
+ }
131
153
132
- let channel = include_str ! ( "../../ci/channel" ) ;
154
+ let channel = include_str ! ( "../../ci/channel" ) ;
133
155
134
- let merge_base = {
135
- if CiEnv :: is_ci ( ) &&
156
+ let merge_base = {
157
+ if CiEnv :: is_ci ( ) &&
136
158
// FIXME: When running on rust-lang managed CI and it's not a nightly build,
137
159
// `git_upstream_merge_base` fails with an error message similar to this:
138
160
// ```
@@ -141,28 +163,29 @@ pub fn get_closest_merge_commit(
141
163
// ```
142
164
// Investigate and resolve this issue instead of skipping it like this.
143
165
( 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" ) ;
150
179
}
151
- } ;
152
180
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) ;
160
182
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
+ }
164
186
165
- Ok ( output_result ( & mut git) ?. trim ( ) . to_owned ( ) )
187
+ Ok ( output_result ( & mut git) ?. trim ( ) . to_owned ( ) )
188
+ }
166
189
}
167
190
168
191
/// Returns the files that have been modified in the current branch compared to the master branch.
0 commit comments