mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-08 05:39:20 +00:00
git: create no-gc ref by GitBackend
Since we now have an explicit method to import heads, it makes more sense to manage no-gc refs by the backend.
This commit is contained in:
parent
17f502c83a
commit
f744e5920b
2 changed files with 25 additions and 17 deletions
|
@ -26,7 +26,7 @@ use tempfile::NamedTempFile;
|
|||
use thiserror::Error;
|
||||
|
||||
use crate::backend::{BackendError, CommitId, ObjectId};
|
||||
use crate::git_backend::{GitBackend, NO_GC_REF_NAMESPACE};
|
||||
use crate::git_backend::GitBackend;
|
||||
use crate::op_store::{BranchTarget, RefTarget, RefTargetOptionExt};
|
||||
use crate::repo::{MutableRepo, Repo};
|
||||
use crate::revset;
|
||||
|
@ -172,18 +172,6 @@ pub fn get_local_git_tracking_branch<'a>(view: &'a View, branch: &str) -> &'a Re
|
|||
view.get_git_ref(&format!("refs/heads/{branch}"))
|
||||
}
|
||||
|
||||
fn prevent_gc(git_repo: &git2::Repository, id: &CommitId) -> Result<(), git2::Error> {
|
||||
// If multiple processes do git::import_refs() in parallel, this can fail to
|
||||
// acquire a lock file even with force=true.
|
||||
git_repo.reference(
|
||||
&format!("{}{}", NO_GC_REF_NAMESPACE, id.hex()),
|
||||
Oid::from_bytes(id.as_bytes()).unwrap(),
|
||||
true,
|
||||
"used by jj",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reflect changes made in the underlying Git repo in the Jujutsu repo.
|
||||
///
|
||||
/// This function detects conflicts (if both Git and JJ modified a branch) and
|
||||
|
@ -255,9 +243,6 @@ pub fn import_some_refs(
|
|||
head_commits.push(commit);
|
||||
}
|
||||
}
|
||||
for commit in &head_commits {
|
||||
prevent_gc(git_repo, commit.id())?;
|
||||
}
|
||||
mut_repo.add_heads(&head_commits);
|
||||
|
||||
// Apply the change that happened in git since last time we imported refs.
|
||||
|
|
|
@ -43,7 +43,7 @@ use crate::stacked_table::{
|
|||
const HASH_LENGTH: usize = 20;
|
||||
const CHANGE_ID_LENGTH: usize = 16;
|
||||
/// Ref namespace used only for preventing GC.
|
||||
pub const NO_GC_REF_NAMESPACE: &str = "refs/jj/keep/";
|
||||
const NO_GC_REF_NAMESPACE: &str = "refs/jj/keep/";
|
||||
const CONFLICT_SUFFIX: &str = ".jjconflict";
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
@ -233,6 +233,9 @@ impl GitBackend {
|
|||
&table_lock,
|
||||
&missing_head_ids,
|
||||
)?;
|
||||
for &id in &missing_head_ids {
|
||||
prevent_gc(&locked_repo, id)?;
|
||||
}
|
||||
self.save_extra_metadata_table(mut_table, &table_lock)
|
||||
}
|
||||
}
|
||||
|
@ -371,6 +374,18 @@ fn create_no_gc_ref() -> String {
|
|||
format!("{NO_GC_REF_NAMESPACE}{}", hex::encode(random_bytes))
|
||||
}
|
||||
|
||||
fn prevent_gc(git_repo: &git2::Repository, id: &CommitId) -> Result<(), BackendError> {
|
||||
git_repo
|
||||
.reference(
|
||||
&format!("{NO_GC_REF_NAMESPACE}{}", id.hex()),
|
||||
Oid::from_bytes(id.as_bytes()).unwrap(),
|
||||
true,
|
||||
"used by jj",
|
||||
)
|
||||
.map_err(|err| BackendError::Other(Box::new(err)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_git_object_id(id: &impl ObjectId) -> Result<git2::Oid, BackendError> {
|
||||
if id.as_bytes().len() != HASH_LENGTH {
|
||||
return Err(BackendError::InvalidHashLength {
|
||||
|
@ -943,6 +958,14 @@ mod tests {
|
|||
|
||||
// Import the head commit and its ancestors
|
||||
store.import_head_commits([&commit_id2]).unwrap();
|
||||
// Ref should be created only for the head commit
|
||||
let git_refs = store
|
||||
.git_repo()
|
||||
.references_glob("refs/jj/keep/*")
|
||||
.unwrap()
|
||||
.map(|git_ref| git_ref.unwrap().target().unwrap())
|
||||
.collect_vec();
|
||||
assert_eq!(git_refs, vec![git_commit_id2]);
|
||||
|
||||
let commit = store.read_commit(&commit_id).unwrap();
|
||||
assert_eq!(&commit.change_id, &change_id);
|
||||
|
|
Loading…
Reference in a new issue