From baa7c85ff3db2366d67ac875fca48ad6dcabf212 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Mon, 9 Jun 2025 23:03:30 +0200 Subject: git: Make fetch return the new head for the fetched branch --- server/common/src/git.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'server/common/src/git.rs') diff --git a/server/common/src/git.rs b/server/common/src/git.rs index 053ff3f..8fe7863 100644 --- a/server/common/src/git.rs +++ b/server/common/src/git.rs @@ -122,6 +122,22 @@ fn parse_tree_entries(output: String) -> Vec { ret } +fn branch_eq(a: impl AsRef, b: impl AsRef) -> bool { + let a = a.as_ref(); + let b = b.as_ref(); + if a.starts_with("refs/heads/") { + if b.starts_with("refs/heads/") { + return a[11..] == b[11..]; + } + return a == format!("refs/heads/{b}"); + } else { + if b.starts_with("refs/heads/") { + return format!("refs/heads/{a}") == b; + } + return a == b; + } +} + impl RepoData { fn new() -> Self { Self { @@ -130,7 +146,7 @@ impl RepoData { } } - async fn fetch(&self, repo: &Repository, branch: String) -> Result<(), Error> { + async fn fetch(&self, repo: &Repository, branch: String) -> Result { if repo.remote.is_none() { return Err(Error::new("No remote set")); } @@ -149,9 +165,24 @@ impl RepoData { // <+ force update>: cmd.arg(format!("+{branch}:{branch}")); - self.output(&mut cmd).await?; + let output = self.output(&mut cmd).await?; + + // git fetch porcelain format: + // + for line in output.lines() { + let mut parts = line.split(' '); + parts.next(); // flag + parts.next(); // old-object-id + if let Some(new_object_id) = parts.next() { + let local_reference = parts.collect::>().join(" "); + if branch_eq(local_reference, &branch) { + return Ok(new_object_id.to_string()); + } + } + } - Ok(()) + assert!(false); + Err(Error::new("Fetch succeeded but branch not found")) } async fn init(&mut self, repo: &Repository) -> Result<(), Error> { @@ -590,7 +621,7 @@ impl Repository { Ok(()) } - pub async fn fetch(&self, branch: impl Into) -> Result<(), Error> { + pub async fn fetch(&self, branch: impl Into) -> Result { let branch = branch.into(); let data = self.lock.read().await; -- cgit v1.2.3-70-g09d2