Skip to content

Commit dc9c5f2

Browse files
committed
implement build_helper::git::get_closest_merge_commit
Compare to `get_git_merge_base`, this doesn't require configuring the upstream remote. Signed-off-by: onur-ozkan <work@onurozkan.dev>
1 parent 05043a3 commit dc9c5f2

File tree

1 file changed

+34
-6
lines changed
  • src/tools/build_helper/src

1 file changed

+34
-6
lines changed

src/tools/build_helper/src/git.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::path::Path;
1+
use std::path::{Path, PathBuf};
22
use std::process::{Command, Stdio};
33

44
pub struct GitConfig<'a> {
@@ -96,10 +96,7 @@ pub fn updated_master_branch(
9696
Err("Cannot find any suitable upstream master branch".to_owned())
9797
}
9898

99-
pub fn get_git_merge_base(
100-
config: &GitConfig<'_>,
101-
git_dir: Option<&Path>,
102-
) -> Result<String, String> {
99+
fn get_git_merge_base(config: &GitConfig<'_>, git_dir: Option<&Path>) -> Result<String, String> {
103100
let updated_master = updated_master_branch(config, git_dir)?;
104101
let mut git = Command::new("git");
105102
if let Some(git_dir) = git_dir {
@@ -108,6 +105,37 @@ pub fn get_git_merge_base(
108105
Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
109106
}
110107

108+
/// Resolves the closest merge commit by the given `author` and `target_paths`.
109+
///
110+
/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD.
111+
pub fn get_closest_merge_commit(
112+
git_dir: Option<&Path>,
113+
config: &GitConfig<'_>,
114+
target_paths: &[PathBuf],
115+
) -> Result<String, String> {
116+
let mut git = Command::new("git");
117+
118+
if let Some(git_dir) = git_dir {
119+
git.current_dir(git_dir);
120+
}
121+
122+
let merge_base = get_git_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into());
123+
124+
git.args([
125+
"rev-list",
126+
&format!("--author={}", config.git_merge_commit_email),
127+
"-n1",
128+
"--first-parent",
129+
&merge_base,
130+
]);
131+
132+
if !target_paths.is_empty() {
133+
git.arg("--").args(target_paths);
134+
}
135+
136+
Ok(output_result(&mut git)?.trim().to_owned())
137+
}
138+
111139
/// Returns the files that have been modified in the current branch compared to the master branch.
112140
/// The `extensions` parameter can be used to filter the files by their extension.
113141
/// Does not include removed files.
@@ -117,7 +145,7 @@ pub fn get_git_modified_files(
117145
git_dir: Option<&Path>,
118146
extensions: &[&str],
119147
) -> Result<Option<Vec<String>>, String> {
120-
let merge_base = get_git_merge_base(config, git_dir)?;
148+
let merge_base = get_closest_merge_commit(git_dir, config, &[])?;
121149

122150
let mut git = Command::new("git");
123151
if let Some(git_dir) = git_dir {

0 commit comments

Comments
 (0)