refs: add stub constructors for absent RefTarget, replace None with it

Now we're mostly ready to reimplement RefTarget on top of
Conflict<Option<CommitId>>.
This commit is contained in:
Yuya Nishihara 2023-07-13 01:56:02 +09:00
parent 9c69a7cb15
commit 0461a8575a
12 changed files with 44 additions and 26 deletions

View File

@ -206,7 +206,7 @@ pub fn import_some_refs(
mut_repo.set_git_head_target(RefTarget::normal(head_commit_id));
}
} else {
mut_repo.set_git_head_target(None);
mut_repo.set_git_head_target(RefTarget::absent());
}
let mut changed_git_refs = BTreeMap::new();
@ -253,7 +253,7 @@ pub fn import_some_refs(
// TODO: or clean up invalid ref in case it was stored due to historical bug?
let ref_name = parse_git_ref(&full_name).expect("stored git ref should be parsable");
if git_ref_filter(&ref_name) {
mut_repo.set_git_ref_target(&full_name, None);
mut_repo.set_git_ref_target(&full_name, RefTarget::absent());
changed_git_refs.insert(ref_name, (Some(target), None));
} else {
pinned_git_heads.insert(ref_name, target.added_ids().cloned().collect());
@ -463,7 +463,7 @@ pub fn export_some_refs(
true
};
if success {
mut_repo.set_git_ref_target(&git_ref_name, None);
mut_repo.set_git_ref_target(&git_ref_name, RefTarget::absent());
} else {
failed_branches.push(parsed_ref_name);
}
@ -536,10 +536,10 @@ pub fn remove_remote(
.filter_map(|r| r.starts_with(&prefix).then(|| r.clone()))
.collect_vec();
for branch in branches_to_delete {
mut_repo.set_remote_branch_target(&branch, remote_name, None);
mut_repo.set_remote_branch_target(&branch, remote_name, RefTarget::absent());
}
for git_ref in git_refs_to_delete {
mut_repo.set_git_ref_target(&git_ref, None);
mut_repo.set_git_ref_target(&git_ref, RefTarget::absent());
}
Ok(())
}
@ -568,7 +568,7 @@ pub fn rename_remote(
})
.collect_vec();
for (old, new, target) in git_refs {
mut_repo.set_git_ref_target(&old, None);
mut_repo.set_git_ref_target(&old, RefTarget::absent());
mut_repo.set_git_ref_target(&new, Some(target));
}
Ok(())

View File

@ -143,6 +143,19 @@ impl ContentHash for RefTarget {
}
impl RefTarget {
/// Creates non-conflicting target pointing to no commit.
pub fn absent() -> Option<Self> {
None
}
/// Returns non-conflicting target pointing to no commit.
///
/// This will typically be used in place of `None` returned by map lookup.
pub fn absent_ref() -> Option<&'static Self> {
// TODO: This will be static ref to Conflict::resolved(None).
None
}
/// Creates non-conflicting target pointing to a commit.
pub fn normal(id: CommitId) -> Option<Self> {
Some(RefTarget::Normal(id))

View File

@ -187,7 +187,7 @@ mod tests {
fn test_classify_branch_push_action_removed() {
let commit_id1 = CommitId::from_hex("11");
let branch = BranchTarget {
local_target: None,
local_target: RefTarget::absent(),
remote_targets: btreemap! {
"origin".to_string() => RefTarget::normal(commit_id1.clone()).unwrap(),
},

View File

@ -396,7 +396,7 @@ mod tests {
}
},
"deleted".to_string() => BranchTarget {
local_target: None,
local_target: RefTarget::absent(),
remote_targets: btreemap! {
"origin".to_string() => branch_deleted_origin_target.unwrap(),
}

View File

@ -183,7 +183,7 @@ impl View {
fn remove_local_branch(&mut self, name: &str) {
if let Some(branch) = self.data.branches.get_mut(name) {
branch.local_target = None;
branch.local_target = RefTarget::absent();
if branch.remote_targets.is_empty() {
self.remove_branch(name);
}

View File

@ -888,7 +888,7 @@ fn test_import_refs_empty_git_repo() {
assert_eq!(repo.view().branches().len(), 0);
assert_eq!(repo.view().tags().len(), 0);
assert_eq!(repo.view().git_refs().len(), 0);
assert_eq!(repo.view().git_head(), None);
assert_eq!(repo.view().git_head(), RefTarget::absent_ref());
}
#[test]
@ -1143,7 +1143,7 @@ fn test_import_export_no_auto_local_branch() {
git::import_refs(mut_repo, &git_repo, &git_settings).unwrap();
let expected_branch = BranchTarget {
local_target: None,
local_target: RefTarget::absent(),
remote_targets: btreemap! {
"origin".to_string() => RefTarget::normal(jj_id(&git_commit)).unwrap(),
},
@ -1159,7 +1159,7 @@ fn test_import_export_no_auto_local_branch() {
// Export the branch to git
assert_eq!(git::export_refs(mut_repo, &git_repo), Ok(vec![]));
assert_eq!(mut_repo.get_git_ref("refs/heads/main"), None);
assert_eq!(mut_repo.get_git_ref("refs/heads/main"), RefTarget::absent());
}
#[test]
@ -1250,7 +1250,7 @@ fn test_export_partial_failure() {
// Now remove the `main` branch and make sure that the `main/sub` gets exported
// even though it didn't change
mut_repo.set_local_branch_target("main", None);
mut_repo.set_local_branch_target("main", RefTarget::absent());
assert_eq!(
git::export_refs(mut_repo, &git_repo),
Ok(vec![
@ -1313,7 +1313,7 @@ fn test_export_reexport_transitions() {
// Make changes on the jj side
for branch in ["AXA", "AXB", "AXX"] {
mut_repo.set_local_branch_target(branch, None);
mut_repo.set_local_branch_target(branch, RefTarget::absent());
}
for branch in ["XAA", "XAB", "XAX"] {
mut_repo.set_local_branch_target(branch, RefTarget::normal(commit_a.id().clone()));

View File

@ -490,8 +490,8 @@ fn test_has_changed(use_git: bool) {
mut_repo.remove_public_head(commit2.id());
mut_repo.remove_head(commit2.id());
mut_repo.set_local_branch_target("stable", None);
mut_repo.set_remote_branch_target("stable", "origin", None);
mut_repo.set_local_branch_target("stable", RefTarget::absent());
mut_repo.set_remote_branch_target("stable", "origin", RefTarget::absent());
assert!(!mut_repo.has_changes());
mut_repo.add_head(&commit2);
@ -614,5 +614,8 @@ fn test_rename_remote(use_git: bool) {
mut_repo.set_remote_branch_target("main", "origin", target.clone());
mut_repo.rename_remote("origin", "upstream");
assert_eq!(mut_repo.get_remote_branch("main", "upstream"), target);
assert_eq!(mut_repo.get_remote_branch("main", "origin"), None);
assert_eq!(
mut_repo.get_remote_branch("main", "origin"),
RefTarget::absent()
);
}

View File

@ -154,13 +154,13 @@ fn test_merge_ref_targets() {
// Left removed
assert_eq!(
merge_ref_targets(index, None, target3.as_ref(), target3.as_ref()),
None
RefTarget::absent()
);
// Right removed
assert_eq!(
merge_ref_targets(index, target3.as_ref(), target3.as_ref(), None),
None
RefTarget::absent()
);
// Left removed, right moved forward

View File

@ -1624,7 +1624,7 @@ fn test_evaluate_expression_git_refs(use_git: bool) {
[commit3.id().clone(), commit4.id().clone()],
),
);
mut_repo.set_git_ref_target("refs/tags/tag2", None);
mut_repo.set_git_ref_target("refs/tags/tag2", RefTarget::absent());
assert_eq!(
resolve_commit_ids(mut_repo, "git_refs()"),
vec![
@ -1713,7 +1713,7 @@ fn test_evaluate_expression_branches(use_git: bool) {
[commit3.id().clone(), commit4.id().clone()],
),
);
mut_repo.set_local_branch_target("branch3", None);
mut_repo.set_local_branch_target("branch3", RefTarget::absent());
assert_eq!(
resolve_commit_ids(mut_repo, "branches()"),
vec![
@ -1822,7 +1822,7 @@ fn test_evaluate_expression_remote_branches(use_git: bool) {
[commit3.id().clone(), commit4.id().clone()],
),
);
mut_repo.set_remote_branch_target("branch3", "origin", None);
mut_repo.set_remote_branch_target("branch3", "origin", RefTarget::absent());
assert_eq!(
resolve_commit_ids(mut_repo, "remote_branches()"),
vec![

View File

@ -1313,7 +1313,7 @@ fn test_rebase_descendants_branch_delete_modify_abandon() {
let mut tx = repo.start_transaction(&settings, "test");
tx.mut_repo().record_abandoned_commit(commit_b.id().clone());
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert_eq!(tx.mut_repo().get_local_branch("main"), None);
assert_eq!(tx.mut_repo().get_local_branch("main"), RefTarget::absent());
}
#[test_case(false ; "local backend")]

View File

@ -279,7 +279,8 @@ fn cmd_branch_delete(
let branch_term = make_branch_term(names.iter().collect_vec().as_slice());
let mut tx = workspace_command.start_transaction(&format!("delete {branch_term}"));
for branch_name in names.iter() {
tx.mut_repo().set_local_branch_target(branch_name, None);
tx.mut_repo()
.set_local_branch_target(branch_name, RefTarget::absent());
}
tx.finish(ui)?;
if names.len() > 1 {

View File

@ -1,7 +1,7 @@
use std::collections::{BTreeMap, BTreeSet};
use clap::Subcommand;
use jj_lib::op_store::{BranchTarget, RefTargetExt as _};
use jj_lib::op_store::{BranchTarget, RefTarget, RefTargetExt as _};
use jj_lib::operation;
use jj_lib::repo::Repo;
@ -187,7 +187,8 @@ fn view_with_desired_portions_restored(
let local_target = new_view
.branches
.get(branch_name)
.and_then(|br| br.local_target.clone());
.map(|br| br.local_target.clone())
.unwrap_or_else(RefTarget::absent);
let remote_targets = branch_source_view
.branches
.get(branch_name)