From 27107637f2ef28e93b8e703d7d49cdd5c95cd077 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Sun, 7 Nov 2021 15:18:24 -0800 Subject: [PATCH] git: fix regression in pruning of remote refs A while ago, I replaced a call to git2-rs's `Remote::fetch()` by calls to `Remote::download()` and `Remote::update_tips()`. The function is documented to be a convenience for those function, but it turns out that the pruning of deleted remote refs is a separate call (`Remote::prune()`), so we need to call that too. --- lib/src/git.rs | 4 ++-- lib/tests/test_git.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/src/git.rs b/lib/src/git.rs index 038e97920..5124fb2ad 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -14,7 +14,7 @@ use std::collections::{BTreeMap, HashSet}; -use git2::{FetchPrune, RemoteCallbacks}; +use git2::RemoteCallbacks; use itertools::Itertools; use thiserror::Error; @@ -143,10 +143,10 @@ pub fn fetch( fetch_options.proxy_options(proxy_options); let callbacks = create_remote_callbacks(); fetch_options.remote_callbacks(callbacks); - fetch_options.prune(FetchPrune::On); let refspec: &[&str] = &[]; remote.download(refspec, Some(&mut fetch_options))?; remote.update_tips(None, false, git2::AutotagOption::Unspecified, None)?; + remote.prune(None)?; // TODO: We could make it optional to get the default branch since we only care // about it on clone. let mut default_branch = None; diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index 704eb918f..2c78155da 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -327,6 +327,37 @@ fn test_fetch_success() { ); } +#[test] +fn test_fetch_prune_deleted_ref() { + let settings = testutils::user_settings(); + let temp_dir = tempfile::tempdir().unwrap(); + let source_repo_dir = temp_dir.path().join("source"); + let clone_repo_dir = temp_dir.path().join("clone"); + let jj_repo_dir = temp_dir.path().join("jj"); + let source_git_repo = git2::Repository::init_bare(&source_repo_dir).unwrap(); + empty_git_commit(&source_git_repo, "refs/heads/main", &[]); + let clone_git_repo = + git2::Repository::clone(source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); + std::fs::create_dir(&jj_repo_dir).unwrap(); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir).unwrap(); + + let mut tx = jj_repo.start_transaction("test"); + git::fetch(tx.mut_repo(), &clone_git_repo, "origin").unwrap(); + // Test the setup + assert!(tx.mut_repo().get_branch("main").is_some()); + + // After re-fetching, the branch should be deleted + source_git_repo + .find_reference("refs/heads/main") + .unwrap() + .delete() + .unwrap(); + git::fetch(tx.mut_repo(), &clone_git_repo, "origin").unwrap(); + assert!(tx.mut_repo().get_branch("main").is_none()); + + tx.discard(); +} + #[test] fn test_fetch_no_default_branch() { let settings = testutils::user_settings();