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
|
||||
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
|
||||
|
||||
Thanks to the people who made this release happen!
|
||||
|
|
|
@ -22,6 +22,7 @@ use thiserror::Error;
|
|||
|
||||
use crate::backend::CommitId;
|
||||
use crate::commit::Commit;
|
||||
use crate::git_backend::NO_GC_REF_NAMESPACE;
|
||||
use crate::op_store;
|
||||
use crate::op_store::RefTarget;
|
||||
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.
|
||||
pub fn import_refs(
|
||||
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 = store.get_commit(&head_commit_id).unwrap();
|
||||
new_git_heads.insert(head_commit_id.clone());
|
||||
prevent_gc(git_repo, &head_commit_id);
|
||||
mut_repo.add_head(&head_commit);
|
||||
mut_repo.set_git_head(head_commit_id);
|
||||
} else {
|
||||
|
@ -112,6 +125,7 @@ pub fn import_refs(
|
|||
let old_target = existing_git_refs.remove(&full_name);
|
||||
let new_target = Some(RefTarget::Normal(id.clone()));
|
||||
if new_target != old_target {
|
||||
prevent_gc(git_repo, &id);
|
||||
mut_repo.set_git_ref(full_name.clone(), RefTarget::Normal(id.clone()));
|
||||
let commit = store.get_commit(&id).unwrap();
|
||||
mut_repo.add_head(&commit);
|
||||
|
|
|
@ -33,7 +33,7 @@ use crate::stacked_table::{TableSegment, TableStore};
|
|||
|
||||
const HASH_LENGTH: usize = 20;
|
||||
/// 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";
|
||||
|
||||
impl From<git2::Error> for BackendError {
|
||||
|
|
Loading…
Reference in a new issue