ok/jj
1
0
Fork 0
forked from mirrors/jj

git_backend: use lower-level API to create no-gc refs

This will allow us to issue multiple prevent_gc() requests all at once. It's
not important here, but will be unavoidable when implementing GC. Deleting
tons of refs from packed refs is super slow if the requests were processed one
by one.
This commit is contained in:
Yuya Nishihara 2024-01-13 12:58:10 +09:00
parent 4b224c45e0
commit f66c859fe4

View file

@ -584,16 +584,31 @@ fn deserialize_extras(commit: &mut Commit, bytes: &[u8]) {
/// Creates a ref in refs/jj/. Used for preventing GC of commits we create.
fn prevent_gc(git_repo: &gix::Repository, id: &CommitId) -> Result<(), BackendError> {
git_repo
.reference(
format!("{NO_GC_REF_NAMESPACE}{}", id.hex()),
validate_git_object_id(id).unwrap(),
gix::refs::transaction::PreviousValue::Any,
"used by jj",
)
.edit_reference(to_no_gc_ref_update(id))
.map_err(|err| BackendError::Other(Box::new(err)))?;
Ok(())
}
/// Returns `RefEdit` that will create a ref in `refs/jj/keep` if not exist.
/// Used for preventing GC of commits we create.
fn to_no_gc_ref_update(id: &CommitId) -> gix::refs::transaction::RefEdit {
let name = format!("{NO_GC_REF_NAMESPACE}{}", id.hex());
let new = gix::refs::Target::Peeled(validate_git_object_id(id).unwrap());
let expected = gix::refs::transaction::PreviousValue::Any;
gix::refs::transaction::RefEdit {
change: gix::refs::transaction::Change::Update {
log: gix::refs::transaction::LogChange {
message: "used by jj".into(),
..Default::default()
},
expected,
new,
},
name: name.try_into().unwrap(),
deref: false,
}
}
fn validate_git_object_id(id: &impl ObjectId) -> Result<gix::ObjectId, BackendError> {
if id.as_bytes().len() != HASH_LENGTH {
return Err(BackendError::InvalidHashLength {