forked from mirrors/jj
git: on import, add GC-preventing refs to all seen refs
To prevent git's GC from breaking a repo, we already add a git ref to commits we create in the git backend. However, we don't add refs to commits we import from git. This fixes that. Closes #815.
This commit is contained in:
parent
9df247f87c
commit
be383cebc7
3 changed files with 19 additions and 1 deletions
|
@ -105,6 +105,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
later removed if you checked out another commit. You can now use `git` to
|
later removed if you checked out another commit. You can now use `git` to
|
||||||
populate the submodule directory and `jj` will leave it alone.
|
populate the submodule directory and `jj` will leave it alone.
|
||||||
|
|
||||||
|
* Git's GC could remove commits that were referenced from jj in some cases. We
|
||||||
|
are now better at adding Git refs to prevent that.
|
||||||
|
[#815](https://github.com/martinvonz/jj/issues/815)
|
||||||
|
|
||||||
### Contributors
|
### Contributors
|
||||||
|
|
||||||
Thanks to the people who made this release happen!
|
Thanks to the people who made this release happen!
|
||||||
|
|
|
@ -22,6 +22,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::backend::CommitId;
|
use crate::backend::CommitId;
|
||||||
use crate::commit::Commit;
|
use crate::commit::Commit;
|
||||||
|
use crate::git_backend::NO_GC_REF_NAMESPACE;
|
||||||
use crate::op_store;
|
use crate::op_store;
|
||||||
use crate::op_store::RefTarget;
|
use crate::op_store::RefTarget;
|
||||||
use crate::repo::MutableRepo;
|
use crate::repo::MutableRepo;
|
||||||
|
@ -50,6 +51,17 @@ fn parse_git_ref(ref_name: &str) -> Option<RefName> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prevent_gc(git_repo: &git2::Repository, id: &CommitId) {
|
||||||
|
git_repo
|
||||||
|
.reference(
|
||||||
|
&format!("{}{}", NO_GC_REF_NAMESPACE, id.hex()),
|
||||||
|
Oid::from_bytes(id.as_bytes()).unwrap(),
|
||||||
|
true,
|
||||||
|
"used by jj",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
/// Reflect changes made in the underlying Git repo in the Jujutsu repo.
|
/// Reflect changes made in the underlying Git repo in the Jujutsu repo.
|
||||||
pub fn import_refs(
|
pub fn import_refs(
|
||||||
mut_repo: &mut MutableRepo,
|
mut_repo: &mut MutableRepo,
|
||||||
|
@ -75,6 +87,7 @@ pub fn import_refs(
|
||||||
let head_commit_id = CommitId::from_bytes(head_git_commit.id().as_bytes());
|
let head_commit_id = CommitId::from_bytes(head_git_commit.id().as_bytes());
|
||||||
let head_commit = store.get_commit(&head_commit_id).unwrap();
|
let head_commit = store.get_commit(&head_commit_id).unwrap();
|
||||||
new_git_heads.insert(head_commit_id.clone());
|
new_git_heads.insert(head_commit_id.clone());
|
||||||
|
prevent_gc(git_repo, &head_commit_id);
|
||||||
mut_repo.add_head(&head_commit);
|
mut_repo.add_head(&head_commit);
|
||||||
mut_repo.set_git_head(head_commit_id);
|
mut_repo.set_git_head(head_commit_id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -112,6 +125,7 @@ pub fn import_refs(
|
||||||
let old_target = existing_git_refs.remove(&full_name);
|
let old_target = existing_git_refs.remove(&full_name);
|
||||||
let new_target = Some(RefTarget::Normal(id.clone()));
|
let new_target = Some(RefTarget::Normal(id.clone()));
|
||||||
if new_target != old_target {
|
if new_target != old_target {
|
||||||
|
prevent_gc(git_repo, &id);
|
||||||
mut_repo.set_git_ref(full_name.clone(), RefTarget::Normal(id.clone()));
|
mut_repo.set_git_ref(full_name.clone(), RefTarget::Normal(id.clone()));
|
||||||
let commit = store.get_commit(&id).unwrap();
|
let commit = store.get_commit(&id).unwrap();
|
||||||
mut_repo.add_head(&commit);
|
mut_repo.add_head(&commit);
|
||||||
|
|
|
@ -33,7 +33,7 @@ use crate::stacked_table::{TableSegment, TableStore};
|
||||||
|
|
||||||
const HASH_LENGTH: usize = 20;
|
const HASH_LENGTH: usize = 20;
|
||||||
/// Ref namespace used only for preventing GC.
|
/// Ref namespace used only for preventing GC.
|
||||||
const NO_GC_REF_NAMESPACE: &str = "refs/jj/keep/";
|
pub const NO_GC_REF_NAMESPACE: &str = "refs/jj/keep/";
|
||||||
const CONFLICT_SUFFIX: &str = ".jjconflict";
|
const CONFLICT_SUFFIX: &str = ".jjconflict";
|
||||||
|
|
||||||
impl From<git2::Error> for BackendError {
|
impl From<git2::Error> for BackendError {
|
||||||
|
|
Loading…
Reference in a new issue