diff options
| author | Joel Klinghed <the_jk@spawned.biz> | 2025-06-09 23:03:30 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@spawned.biz> | 2025-06-12 09:12:27 +0200 |
| commit | baa7c85ff3db2366d67ac875fca48ad6dcabf212 (patch) | |
| tree | 490b357aa08394a1ee7fb92dd52e72af6ca335ba /server/common/src/git.rs | |
| parent | 7311e02c89b66849f5e660b690ca69b5e8fd1383 (diff) | |
git: Make fetch return the new head for the fetched branch
Diffstat (limited to 'server/common/src/git.rs')
| -rw-r--r-- | server/common/src/git.rs | 39 |
1 files changed, 35 insertions, 4 deletions
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<TreeEntry> { ret } +fn branch_eq(a: impl AsRef<str>, b: impl AsRef<str>) -> 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<String, Error> { if repo.remote.is_none() { return Err(Error::new("No remote set")); } @@ -149,9 +165,24 @@ impl RepoData { // <+ force update><remote branch>:<local branch> cmd.arg(format!("+{branch}:{branch}")); - self.output(&mut cmd).await?; + let output = self.output(&mut cmd).await?; - Ok(()) + // git fetch porcelain format: + // <flag> <old-object-id> <new-object-id> <local-reference> + 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::<Vec<&str>>().join(" "); + if branch_eq(local_reference, &branch) { + return Ok(new_object_id.to_string()); + } + } + } + + 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<String>) -> Result<(), Error> { + pub async fn fetch(&self, branch: impl Into<String>) -> Result<String, Error> { let branch = branch.into(); let data = self.lock.read().await; |
