Skip to content

Commit

Permalink
view: try to guess the default workspace id
Browse files Browse the repository at this point in the history
`jj workspace rename` exists now. This means that people currently using
JJ with colocated repos and renaming their default workspace may lose
their git HEAD briefly when they next upgrade. This guesswork limits that
to cases where they both:

- rename their default workspace
- AND create a second workspace (which cannot be --colocate as that is
  being added in the same PR as View.git_heads)

But it's not a huge deal -- JJ will re-add the git HEAD when it next
does almost anything.
  • Loading branch information
cormacrelf committed Oct 13, 2024
1 parent 80fd3e7 commit 2b7b683
Showing 1 changed file with 103 additions and 8 deletions.
111 changes: 103 additions & 8 deletions lib/src/simple_op_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,14 +526,46 @@ fn view_from_proto(proto: crate::protos::op_store::View) -> View {
#[allow(deprecated)]
if !proto.git_heads.is_empty() {
view.git_heads = git_heads_from_proto(proto.git_heads);
} else if proto.git_head.is_some() {
view.git_heads = hashmap! {
WorkspaceId::default() => ref_target_from_proto(proto.git_head),
};
} else if !proto.git_head_legacy.is_empty() {
view.git_heads = hashmap! {
WorkspaceId::default() => RefTarget::normal(CommitId::new(proto.git_head_legacy)),
};
} else if let Some(fallback) =
proto
.git_head
.map(Some)
.map(ref_target_from_proto)
.or(Some(proto.git_head_legacy)
.filter(|id| !id.is_empty())
.map(CommitId::new)
.map(RefTarget::normal))
{
// Fallback means this view was written when there could only be one HEAD@git.
// At that time, there could be other workspaces, but these could not be
// colocated with .git, so they didn't have HEADs.
//
// So we need to figure out which is the default workspace, that should be
// assigned the only HEAD we have.

let default = WorkspaceId::default();
if let Ok(only_one) = view.wc_commit_ids.keys().exactly_one().cloned() {
// Easy. The user has renamed the default workspace.
view.git_heads = hashmap! {
only_one => fallback,
};
} else if view.wc_commit_ids.contains_key(&default) {
// If one of them is named default, assume it is the default, and behave the
// most correctly we can -- only one git head is set, and we wait for the
// other workspaces to reset their git heads on their own in normal operation.
view.git_heads = hashmap! {
default => fallback,
};
} else {
// We can't tell from the view. Someone has used a nonstandard
// default workspace name, and also created more than
// one workspace, so we have no way to guess on the data
// we have here.
//
// So we do nothing. Eventually JJ will add git_heads entries for
// any workspaces you interact with. So it's not the end
// of the world.
}
}

if !proto.has_git_refs_migrated_to_remote {
Expand Down Expand Up @@ -1083,4 +1115,67 @@ mod tests {
let maybe_proto = ref_target_to_proto_legacy(&target);
assert_eq!(ref_target_from_proto(maybe_proto), target);
}

#[allow(deprecated)]
#[test]
fn test_upgrade_deprecated_git_heads() {
let default = crate::protos::op_store::View {
wc_commit_id: vec![],
wc_commit_ids: hashmap! {},
git_head_legacy: vec![],
git_head: None,
git_heads: vec![],
bookmarks: vec![],
git_refs: vec![],
has_git_refs_migrated_to_remote: false,
head_ids: vec![],
tags: vec![],
};
let wsd = WorkspaceId::default();
{
let proto = crate::protos::op_store::View {
wc_commit_id: b"def".to_vec(),
git_head_legacy: b"abc".to_vec(),
..default.clone()
};
let view = view_from_proto(proto);
assert!(view.git_heads.contains_key(&wsd));
}
{
let proto = crate::protos::op_store::View {
wc_commit_ids: hashmap! {
wsd.as_str().to_owned() => b"def".to_vec(),
},
git_head_legacy: b"abc".to_vec(),
..default.clone()
};
let view = view_from_proto(proto);
assert!(view.git_heads.contains_key(&wsd));
}
let rt = RefTarget::normal(CommitId::new(b"abc".to_vec()));
let rtp = ref_target_to_proto(&rt);
{
let proto = crate::protos::op_store::View {
wc_commit_ids: hashmap! {
wsd.as_str().to_owned() => b"def".to_vec(),
},
git_head: Some(rtp.clone()),
..default.clone()
};
let view = view_from_proto(proto);
assert!(view.git_heads.contains_key(&wsd));
}
{
let proto = crate::protos::op_store::View {
wc_commit_ids: hashmap! {
wsd.as_str().to_owned() => b"def".to_vec(),
"second".to_owned() => b"xyz".to_vec(),
},
git_head: Some(rtp.clone()),
..default.clone()
};
let view = view_from_proto(proto);
assert!(view.git_heads.contains_key(&wsd));
}
}
}

0 comments on commit 2b7b683

Please sign in to comment.