git: take a MutableRepo instead of a Transaction

This commit is contained in:
Martin von Zweigbergk 2021-03-16 16:08:40 -07:00
parent 769f88bbae
commit 5ed14185a0
4 changed files with 26 additions and 44 deletions

View File

@ -15,8 +15,8 @@
use thiserror::Error;
use crate::commit::Commit;
use crate::repo::MutableRepo;
use crate::store::CommitId;
use crate::transaction::Transaction;
#[derive(Error, Debug, PartialEq)]
pub enum GitImportError {
@ -26,16 +26,16 @@ pub enum GitImportError {
// Reflect changes made in the underlying Git repo in the Jujube repo.
pub fn import_refs(
tx: &mut Transaction,
mut_repo: &mut MutableRepo,
git_repo: &git2::Repository,
) -> Result<(), GitImportError> {
let store = tx.store().clone();
let store = mut_repo.store().clone();
let git_refs = git_repo.references()?;
let existing_git_refs: Vec<_> = tx.view().git_refs().keys().cloned().collect();
let existing_git_refs: Vec<_> = mut_repo.view().git_refs().keys().cloned().collect();
// TODO: Store the id of the previous import and read it back here, so we can
// merge the views instead of overwriting.
for existing_git_ref in existing_git_refs {
tx.remove_git_ref(&existing_git_ref);
mut_repo.remove_git_ref(&existing_git_ref);
// TODO: We should probably also remove heads pointing to the same
// commits and commits no longer reachable from other refs.
// If the underlying git repo has a branch that gets rewritten, we
@ -59,12 +59,12 @@ pub fn import_refs(
};
let id = CommitId(git_commit.id().as_bytes().to_vec());
let commit = store.get_commit(&id).unwrap();
tx.add_head(&commit);
tx.insert_git_ref(git_ref.name().unwrap().to_string(), id);
mut_repo.add_head(&commit);
mut_repo.insert_git_ref(git_ref.name().unwrap().to_string(), id);
// For now, we consider all remotes "publishing".
// TODO: Make it configurable which remotes are publishing.
if git_ref.is_remote() {
tx.add_public_head(&commit);
mut_repo.add_public_head(&commit);
}
}
Ok(())
@ -80,7 +80,7 @@ pub enum GitFetchError {
}
pub fn fetch(
tx: &mut Transaction,
mut_repo: &mut MutableRepo,
git_repo: &git2::Repository,
remote_name: &str,
) -> Result<(), GitFetchError> {
@ -104,7 +104,7 @@ pub fn fetch(
fetch_options.remote_callbacks(callbacks);
let refspec: &[&str] = &[];
remote.fetch(refspec, Some(&mut fetch_options), None)?;
import_refs(tx, git_repo).map_err(|err| match err {
import_refs(mut_repo, git_repo).map_err(|err| match err {
GitImportError::InternalGitError(source) => GitFetchError::InternalGitError(source),
})?;
Ok(())

View File

@ -103,26 +103,6 @@ impl<'r> Transaction<'r> {
mut_repo.remove_head(head)
}
pub fn add_public_head(&mut self, head: &Commit) {
let mut_repo = Arc::get_mut(self.repo.as_mut().unwrap()).unwrap();
mut_repo.add_public_head(head)
}
pub fn remove_public_head(&mut self, head: &Commit) {
let mut_repo = Arc::get_mut(self.repo.as_mut().unwrap()).unwrap();
mut_repo.remove_public_head(head);
}
pub fn insert_git_ref(&mut self, name: String, commit_id: CommitId) {
let mut_repo = Arc::get_mut(self.repo.as_mut().unwrap()).unwrap();
mut_repo.insert_git_ref(name, commit_id);
}
pub fn remove_git_ref(&mut self, name: &str) {
let mut_repo = Arc::get_mut(self.repo.as_mut().unwrap()).unwrap();
mut_repo.remove_git_ref(name);
}
pub fn set_view(&mut self, data: op_store::View) {
let mut_repo = Arc::get_mut(self.repo.as_mut().unwrap()).unwrap();
mut_repo.set_view(data);

View File

@ -68,7 +68,7 @@ fn test_import_refs() {
let git_repo = repo.store().git_repo().unwrap();
let mut tx = repo.start_transaction("test");
let heads_before: HashSet<_> = repo.view().heads().clone();
jujube_lib::git::import_refs(&mut tx, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default();
let view = tx.view();
let expected_heads: HashSet<_> = heads_before
.union(&hashset!(
@ -117,7 +117,7 @@ fn test_import_refs_reimport() {
let heads_before = repo.view().heads().clone();
let mut tx = repo.start_transaction("test");
jujube_lib::git::import_refs(&mut tx, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default();
tx.commit();
// Delete feature1 and rewrite feature2
@ -127,7 +127,7 @@ fn test_import_refs_reimport() {
Arc::get_mut(&mut repo).unwrap().reload();
let mut tx = repo.start_transaction("test");
jujube_lib::git::import_refs(&mut tx, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default();
let view = tx.view();
// TODO: commit3 and commit4 should probably be removed
@ -199,7 +199,7 @@ fn test_import_refs_merge() {
git_ref(&git_repo, "refs/heads/forward-remove", commit1.id());
git_ref(&git_repo, "refs/heads/remove-forward", commit1.id());
let mut tx = repo.start_transaction("initial import");
jujube_lib::git::import_refs(&mut tx, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default();
tx.commit();
Arc::get_mut(&mut repo).unwrap().reload();
@ -212,7 +212,7 @@ fn test_import_refs_merge() {
delete_git_ref(&git_repo, "refs/heads/remove-forward");
git_ref(&git_repo, "refs/heads/add-add", commit3.id());
let mut tx1 = repo.start_transaction("concurrent import 1");
jujube_lib::git::import_refs(&mut tx1, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx1.mut_repo(), &git_repo).unwrap_or_default();
tx1.commit();
// The other concurrent operation:
@ -224,7 +224,7 @@ fn test_import_refs_merge() {
git_ref(&git_repo, "refs/heads/remove-forward", commit2.id());
git_ref(&git_repo, "refs/heads/add-add", commit4.id());
let mut tx2 = repo.start_transaction("concurrent import 2");
jujube_lib::git::import_refs(&mut tx2, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx2.mut_repo(), &git_repo).unwrap_or_default();
tx2.commit();
// Reload the repo, causing the operations to be merged.
@ -280,7 +280,7 @@ fn test_import_refs_empty_git_repo() {
let repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, git_repo_dir);
let heads_before = repo.view().heads().clone();
let mut tx = repo.start_transaction("test");
jujube_lib::git::import_refs(&mut tx, &git_repo).unwrap_or_default();
jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default();
assert_eq!(*tx.view().heads(), heads_before);
assert_eq!(tx.view().git_refs().len(), 0);
tx.discard();
@ -325,7 +325,7 @@ fn test_fetch_success() {
// The new commit is visible after git::fetch().
let mut tx = jj_repo.start_transaction("test");
git::fetch(&mut tx, &clone_git_repo, "origin").unwrap();
git::fetch(tx.mut_repo(), &clone_git_repo, "origin").unwrap();
assert!(tx.view().heads().contains(&commit_id(&new_git_commit)));
tx.discard();
@ -342,7 +342,7 @@ fn test_fetch_no_such_remote() {
let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, source_repo_dir);
let mut tx = jj_repo.start_transaction("test");
let result = git::fetch(&mut tx, &git_repo, "invalid-remote");
let result = git::fetch(tx.mut_repo(), &git_repo, "invalid-remote");
assert!(matches!(result, Err(GitFetchError::NoSuchRemote(_))));
tx.discard();

View File

@ -607,7 +607,7 @@ fn cmd_init(
repo = ReadonlyRepo::init_external_git(ui.settings(), wc_path, git_store_path);
let git_repo = repo.store().git_repo().unwrap();
let mut tx = repo.start_transaction("import git refs");
git::import_refs(&mut tx, &git_repo).unwrap();
git::import_refs(tx.mut_repo(), &git_repo).unwrap();
// TODO: Check out a recent commit. Maybe one with the highest generation
// number.
tx.commit();
@ -2065,7 +2065,7 @@ fn cmd_git_fetch(
let git_repo = get_git_repo(repo.store())?;
let remote_name = cmd_matches.value_of("remote").unwrap();
let mut tx = repo.start_transaction(&format!("fetch from git remote {}", remote_name));
git::fetch(&mut tx, &git_repo, remote_name)
git::fetch(tx.mut_repo(), &git_repo, remote_name)
.map_err(|err| CommandError::UserError(err.to_string()))?;
tx.commit();
Ok(())
@ -2096,7 +2096,7 @@ fn cmd_git_clone(
let remote_name = "origin";
git_repo.remote(remote_name, source).unwrap();
let mut tx = repo.start_transaction("fetch from git remote into empty repo");
git::fetch(&mut tx, &git_repo, remote_name).map_err(|err| match err {
git::fetch(tx.mut_repo(), &git_repo, remote_name).map_err(|err| match err {
GitFetchError::NoSuchRemote(_) => {
panic!("should't happen as we just created the git remote")
}
@ -2124,7 +2124,8 @@ fn cmd_git_push(
git::push_commit(&git_repo, &commit, remote_name, branch_name)
.map_err(|err| CommandError::UserError(err.to_string()))?;
let mut tx = repo.start_transaction("import git refs");
git::import_refs(&mut tx, &git_repo).map_err(|err| CommandError::UserError(err.to_string()))?;
git::import_refs(tx.mut_repo(), &git_repo)
.map_err(|err| CommandError::UserError(err.to_string()))?;
tx.commit();
Ok(())
}
@ -2138,7 +2139,8 @@ fn cmd_git_refresh(
let repo = get_repo(ui, &matches)?;
let git_repo = get_git_repo(repo.store())?;
let mut tx = repo.start_transaction("import git refs");
git::import_refs(&mut tx, &git_repo).map_err(|err| CommandError::UserError(err.to_string()))?;
git::import_refs(tx.mut_repo(), &git_repo)
.map_err(|err| CommandError::UserError(err.to_string()))?;
tx.commit();
Ok(())
}