summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/common/src/git.rs39
-rw-r--r--server/common/src/tests.rs10
-rw-r--r--server/src/git_root.rs2
3 files changed, 41 insertions, 10 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;
diff --git a/server/common/src/tests.rs b/server/common/src/tests.rs
index 34cc315..c8553f7 100644
--- a/server/common/src/tests.rs
+++ b/server/common/src/tests.rs
@@ -272,15 +272,15 @@ async fn git_fetch(bare: bool) -> git::Repository {
repo.fetch("branch"),
repo.fetch("other"),
);
- main.unwrap();
- branch.unwrap();
- other.unwrap();
+ assert_eq!(main.unwrap(), "d7c502b9c6b833060576a0c4da0287933d603011");
+ assert_eq!(branch.unwrap(), "2d05d489d42d4f36dd0ebf52502f243991e010eb");
+ assert_eq!(other.unwrap(), "2cecdec660a30bf3964cee645d9cee03640ef8dc");
} else {
// Not bare repo will complain when you try to fetch into the currently checked
// out branch. So just try fetching other branches.
let (branch, other) = tokio::join!(repo.fetch("branch"), repo.fetch("other"));
- branch.unwrap();
- other.unwrap();
+ assert_eq!(branch.unwrap(), "2d05d489d42d4f36dd0ebf52502f243991e010eb");
+ assert_eq!(other.unwrap(), "2cecdec660a30bf3964cee645d9cee03640ef8dc");
}
repo
}
diff --git a/server/src/git_root.rs b/server/src/git_root.rs
index 01cc2b5..71ad96f 100644
--- a/server/src/git_root.rs
+++ b/server/src/git_root.rs
@@ -535,7 +535,7 @@ async fn setup_project_root(
let bg_project_id = project_id.clone();
tokio::spawn(async move {
match bg_repo.fetch(&main_branch).await {
- Ok(()) => {}
+ Ok(_) => {}
Err(e) => {
error!("{bg_project_id}: fetch {main_branch} returned {e:?}");
}