cleanup: rename checkout to wc_commit

`wc_commit` seems clearer than `checkout` and not too much longer. I
considered `working_copy` but it was less clear (could be the path to
the working copy, or an instance of `WorkingCopy`). I also considered
`working_copy_commit`, but that seems a bit too long.
This commit is contained in:
Martin von Zweigbergk 2022-09-18 14:46:12 -07:00 committed by Martin von Zweigbergk
parent c36b720dd4
commit 6812bd9584
20 changed files with 220 additions and 182 deletions

View file

@ -173,8 +173,8 @@ pub struct View {
pub git_head: Option<CommitId>,
// The commit that *should be* checked out in the workspace. Note that the working copy
// (.jj/working_copy/) has the source of truth about which commit *is* checked out (to be
// precise: the commit to which we most recently completed a checkout to).
pub checkouts: HashMap<WorkspaceId, CommitId>,
// precise: the commit to which we most recently completed an update to).
pub wc_commit_ids: HashMap<WorkspaceId, CommitId>,
}
/// Represents an operation (transaction) on the repo view, just like how a

View file

@ -61,8 +61,8 @@ message Tag {
message View {
repeated bytes head_ids = 1;
repeated bytes public_head_ids = 4;
bytes checkout = 2 [deprecated = true];
map<string, bytes> checkouts = 8;
bytes wc_commit_id = 2 [deprecated = true];
map<string, bytes> wc_commit_ids = 8;
repeated Branch branches = 5;
repeated Tag tags = 6;
// Only a subset of the refs. For example, does not include refs/notes/.

View file

@ -49,8 +49,8 @@ message Checkout {
// TODO: Is it better to make this a UUID and a have map that to a name in
// config? That way users can rename a workspace.
string workspace_id = 3;
// The checked-out commit, which can be viewed as a cache of the checkout
// recorded in `operation_id`'s operation. No longer used.
// The checked-out commit, which can be viewed as a cache of the working-copy
// commit ID recorded in `operation_id`'s operation. No longer used.
// TODO: Delete this mid 2022 or so
bytes commit_id = 1;
}

View file

@ -574,12 +574,12 @@ impl MutableRepo {
Ok(rebaser.rebased().len())
}
pub fn set_checkout(&mut self, workspace_id: WorkspaceId, commit_id: CommitId) {
self.view_mut().set_checkout(workspace_id, commit_id);
pub fn set_wc_commit(&mut self, workspace_id: WorkspaceId, commit_id: CommitId) {
self.view_mut().set_wc_commit(workspace_id, commit_id);
}
pub fn remove_checkout(&mut self, workspace_id: &WorkspaceId) {
self.view_mut().remove_checkout(workspace_id);
pub fn remove_wc_commit(&mut self, workspace_id: &WorkspaceId) {
self.view_mut().remove_wc_commit(workspace_id);
}
pub fn check_out(
@ -592,25 +592,25 @@ impl MutableRepo {
let open_commit =
CommitBuilder::for_open_commit(settings, commit.id().clone(), commit.tree_id().clone())
.write_to_repo(self);
self.set_checkout(workspace_id, open_commit.id().clone());
self.set_wc_commit(workspace_id, open_commit.id().clone());
open_commit
}
pub fn edit(&mut self, workspace_id: WorkspaceId, commit: &Commit) {
self.leave_commit(&workspace_id);
self.set_checkout(workspace_id, commit.id().clone());
self.set_wc_commit(workspace_id, commit.id().clone());
}
fn leave_commit(&mut self, workspace_id: &WorkspaceId) {
let maybe_current_checkout_id = self.view.borrow().get_checkout(workspace_id).cloned();
if let Some(current_checkout_id) = maybe_current_checkout_id {
let current_checkout = self.store().get_commit(&current_checkout_id).unwrap();
if current_checkout.is_empty()
&& current_checkout.description().is_empty()
&& self.view().heads().contains(current_checkout.id())
let maybe_wc_commit_id = self.view.borrow().get_wc_commit_id(workspace_id).cloned();
if let Some(wc_commit_id) = maybe_wc_commit_id {
let wc_commit = self.store().get_commit(&wc_commit_id).unwrap();
if wc_commit.is_empty()
&& wc_commit.description().is_empty()
&& self.view().heads().contains(wc_commit.id())
{
// Abandon the checkout we're leaving if it's empty and a head commit
self.record_abandoned_commit(current_checkout_id);
self.record_abandoned_commit(wc_commit_id);
}
}
}
@ -770,30 +770,30 @@ impl MutableRepo {
fn merge_view(&mut self, base: &View, other: &View) {
// Merge checkouts. If there's a conflict, we keep the self side.
for (workspace_id, base_checkout) in base.checkouts() {
let self_checkout = self.view().get_checkout(workspace_id);
let other_checkout = other.get_checkout(workspace_id);
for (workspace_id, base_checkout) in base.wc_commit_ids() {
let self_checkout = self.view().get_wc_commit_id(workspace_id);
let other_checkout = other.get_wc_commit_id(workspace_id);
if other_checkout == Some(base_checkout) || other_checkout == self_checkout {
// The other side didn't change or both sides changed in the
// same way.
} else if let Some(other_checkout) = other_checkout {
if self_checkout == Some(base_checkout) {
self.view_mut()
.set_checkout(workspace_id.clone(), other_checkout.clone());
.set_wc_commit(workspace_id.clone(), other_checkout.clone());
}
} else {
// The other side removed the workspace. We want to remove it even if the self
// side changed the checkout.
self.view_mut().remove_checkout(workspace_id);
self.view_mut().remove_wc_commit(workspace_id);
}
}
for (workspace_id, other_checkout) in other.checkouts() {
if self.view().get_checkout(workspace_id).is_none()
&& base.get_checkout(workspace_id).is_none()
for (workspace_id, other_checkout) in other.wc_commit_ids() {
if self.view().get_wc_commit_id(workspace_id).is_none()
&& base.get_wc_commit_id(workspace_id).is_none()
{
// The other side added the workspace.
self.view_mut()
.set_checkout(workspace_id.clone(), other_checkout.clone());
.set_wc_commit(workspace_id.clone(), other_checkout.clone());
}
}

View file

@ -142,7 +142,7 @@ pub fn resolve_symbol(
} else {
WorkspaceId::new(symbol.strip_suffix('@').unwrap().to_string())
};
if let Some(commit_id) = repo.view().get_checkout(&target_workspace) {
if let Some(commit_id) = repo.view().get_wc_commit_id(&target_workspace) {
Ok(vec![commit_id.clone()])
} else {
Err(RevsetError::NoSuchRevision(symbol.to_owned()))

View file

@ -295,7 +295,7 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> {
edit: bool,
) -> Result<(), BackendError> {
// We arbitrarily pick a new checkout among the candidates.
self.update_checkouts(&old_commit_id, &new_commit_ids[0], edit)?;
self.update_wc_commits(&old_commit_id, &new_commit_ids[0], edit)?;
if let Some(branch_names) = self.branches.get(&old_commit_id).cloned() {
let mut branch_updates = vec![];
@ -331,13 +331,16 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> {
Ok(())
}
fn update_checkouts(
fn update_wc_commits(
&mut self,
old_commit_id: &CommitId,
new_commit_id: &CommitId,
edit: bool,
) -> Result<(), BackendError> {
let workspaces_to_update = self.mut_repo.view().workspaces_for_checkout(old_commit_id);
let workspaces_to_update = self
.mut_repo
.view()
.workspaces_for_wc_commit_id(old_commit_id);
if workspaces_to_update.is_empty() {
return Ok(());
}

View file

@ -200,9 +200,9 @@ fn operation_from_proto(proto: &crate::protos::op_store::Operation) -> Operation
fn view_to_proto(view: &View) -> crate::protos::op_store::View {
let mut proto = crate::protos::op_store::View::new();
for (workspace_id, commit_id) in &view.checkouts {
for (workspace_id, commit_id) in &view.wc_commit_ids {
proto
.checkouts
.wc_commit_ids
.insert(workspace_id.as_str().to_string(), commit_id.to_bytes());
}
for head_id in &view.head_ids {
@ -252,14 +252,14 @@ fn view_from_proto(proto: &crate::protos::op_store::View) -> View {
let mut view = View::default();
// For compatibility with old repos before we had support for multiple working
// copies
if !proto.checkout.is_empty() {
view.checkouts.insert(
if !proto.wc_commit_id.is_empty() {
view.wc_commit_ids.insert(
WorkspaceId::default(),
CommitId::new(proto.checkout.clone()),
CommitId::new(proto.wc_commit_id.clone()),
);
}
for (workspace_id, commit_id) in &proto.checkouts {
view.checkouts.insert(
for (workspace_id, commit_id) in &proto.wc_commit_ids {
view.wc_commit_ids.insert(
WorkspaceId::new(workspace_id.clone()),
CommitId::new(commit_id.clone()),
);
@ -412,7 +412,7 @@ mod tests {
"refs/heads/feature".to_string() => git_refs_feature_target
},
git_head: Some(CommitId::from_hex("fff111")),
checkouts: hashmap! {
wc_commit_ids: hashmap! {
WorkspaceId::default() => default_checkout_id,
WorkspaceId::new("test".to_string()) => test_checkout_id,
},

View file

@ -42,26 +42,26 @@ impl View {
}
}
pub fn checkouts(&self) -> &HashMap<WorkspaceId, CommitId> {
&self.data.checkouts
pub fn wc_commit_ids(&self) -> &HashMap<WorkspaceId, CommitId> {
&self.data.wc_commit_ids
}
pub fn get_checkout(&self, workspace_id: &WorkspaceId) -> Option<&CommitId> {
self.data.checkouts.get(workspace_id)
pub fn get_wc_commit_id(&self, workspace_id: &WorkspaceId) -> Option<&CommitId> {
self.data.wc_commit_ids.get(workspace_id)
}
pub fn workspaces_for_checkout(&self, commit_id: &CommitId) -> Vec<WorkspaceId> {
pub fn workspaces_for_wc_commit_id(&self, commit_id: &CommitId) -> Vec<WorkspaceId> {
let mut workspaces_ids = vec![];
for (workspace_id, checkout_id) in &self.data.checkouts {
if checkout_id == commit_id {
for (workspace_id, wc_commit_id) in &self.data.wc_commit_ids {
if wc_commit_id == commit_id {
workspaces_ids.push(workspace_id.clone());
}
}
workspaces_ids
}
pub fn is_checkout(&self, commit_id: &CommitId) -> bool {
self.data.checkouts.values().contains(commit_id)
pub fn is_wc_commit_id(&self, commit_id: &CommitId) -> bool {
self.data.wc_commit_ids.values().contains(commit_id)
}
pub fn heads(&self) -> &HashSet<CommitId> {
@ -88,12 +88,12 @@ impl View {
self.data.git_head.clone()
}
pub fn set_checkout(&mut self, workspace_id: WorkspaceId, commit_id: CommitId) {
self.data.checkouts.insert(workspace_id, commit_id);
pub fn set_wc_commit(&mut self, workspace_id: WorkspaceId, commit_id: CommitId) {
self.data.wc_commit_ids.insert(workspace_id, commit_id);
}
pub fn remove_checkout(&mut self, workspace_id: &WorkspaceId) {
self.data.checkouts.remove(workspace_id);
pub fn remove_wc_commit(&mut self, workspace_id: &WorkspaceId) {
self.data.wc_commit_ids.remove(workspace_id);
}
pub fn add_head(&mut self, head_id: &CommitId) {

View file

@ -86,22 +86,22 @@ fn test_init_no_config_set(use_git: bool) {
let settings = UserSettings::from_config(config::Config::default());
let test_workspace = TestWorkspace::init(&settings, use_git);
let repo = &test_workspace.repo;
let checkout_id = repo.view().get_checkout(&WorkspaceId::default()).unwrap();
let checkout_commit = repo.store().get_commit(checkout_id).unwrap();
let wc_commit_id = repo
.view()
.get_wc_commit_id(&WorkspaceId::default())
.unwrap();
let wc_commit = repo.store().get_commit(wc_commit_id).unwrap();
assert_eq!(wc_commit.author().name, "(no name configured)".to_string());
assert_eq!(
checkout_commit.author().name,
"(no name configured)".to_string()
);
assert_eq!(
checkout_commit.author().email,
wc_commit.author().email,
"(no email configured)".to_string()
);
assert_eq!(
checkout_commit.committer().name,
wc_commit.committer().name,
"(no name configured)".to_string()
);
assert_eq!(
checkout_commit.committer().email,
wc_commit.committer().email,
"(no email configured)".to_string()
);
}
@ -113,15 +113,18 @@ fn test_init_checkout(use_git: bool) {
let settings = testutils::user_settings();
let test_workspace = TestWorkspace::init(&settings, use_git);
let repo = &test_workspace.repo;
let checkout_id = repo.view().get_checkout(&WorkspaceId::default()).unwrap();
let checkout_commit = repo.store().get_commit(checkout_id).unwrap();
assert_eq!(checkout_commit.tree_id(), repo.store().empty_tree_id());
assert_eq!(checkout_commit.store_commit().parents, vec![]);
assert_eq!(checkout_commit.predecessors(), vec![]);
assert_eq!(checkout_commit.description(), "");
assert!(checkout_commit.is_open());
assert_eq!(checkout_commit.author().name, settings.user_name());
assert_eq!(checkout_commit.author().email, settings.user_email());
assert_eq!(checkout_commit.committer().name, settings.user_name());
assert_eq!(checkout_commit.committer().email, settings.user_email());
let wc_commit_id = repo
.view()
.get_wc_commit_id(&WorkspaceId::default())
.unwrap();
let wc_commit = repo.store().get_commit(wc_commit_id).unwrap();
assert_eq!(wc_commit.tree_id(), repo.store().empty_tree_id());
assert_eq!(wc_commit.store_commit().parents, vec![]);
assert_eq!(wc_commit.predecessors(), vec![]);
assert_eq!(wc_commit.description(), "");
assert!(wc_commit.is_open());
assert_eq!(wc_commit.author().name, settings.user_name());
assert_eq!(wc_commit.author().email, settings.user_email());
assert_eq!(wc_commit.committer().name, settings.user_name());
assert_eq!(wc_commit.committer().email, settings.user_email());
}

View file

@ -31,16 +31,16 @@ fn test_edit(use_git: bool) {
let repo = &test_repo.repo;
let mut tx = repo.start_transaction("test");
let checkout = testutils::create_random_commit(&settings, repo)
let wc_commit = testutils::create_random_commit(&settings, repo)
.set_open(true)
.write_to_repo(tx.mut_repo());
let repo = tx.commit();
let mut tx = repo.start_transaction("test");
let ws_id = WorkspaceId::default();
tx.mut_repo().edit(ws_id.clone(), &checkout);
tx.mut_repo().edit(ws_id.clone(), &wc_commit);
let repo = tx.commit();
assert_eq!(repo.view().get_checkout(&ws_id), Some(checkout.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws_id), Some(wc_commit.id()));
}
#[test_case(false ; "local backend")]
@ -67,7 +67,10 @@ fn test_checkout_closed(use_git: bool) {
assert_eq!(actual_checkout.parents().len(), 1);
assert_eq!(actual_checkout.parents()[0].id(), requested_checkout.id());
let repo = tx.commit();
assert_eq!(repo.view().get_checkout(&ws_id), Some(actual_checkout.id()));
assert_eq!(
repo.view().get_wc_commit_id(&ws_id),
Some(actual_checkout.id())
);
}
#[test_case(false ; "local backend")]
@ -121,10 +124,10 @@ fn test_checkout_previous_empty(use_git: bool) {
let mut tx = repo.start_transaction("test");
let mut_repo = tx.mut_repo();
let new_checkout = testutils::create_random_commit(&settings, &repo)
let new_wc_commit = testutils::create_random_commit(&settings, &repo)
.set_open(true)
.write_to_repo(mut_repo);
mut_repo.edit(ws_id, &new_checkout);
mut_repo.edit(ws_id, &new_wc_commit);
mut_repo.rebase_descendants(&settings).unwrap();
assert!(!mut_repo.view().heads().contains(old_checkout.id()));
}
@ -220,7 +223,10 @@ fn test_edit_initial(use_git: bool) {
let workspace_id = WorkspaceId::new("new-workspace".to_string());
tx.mut_repo().edit(workspace_id.clone(), &checkout);
let repo = tx.commit();
assert_eq!(repo.view().get_checkout(&workspace_id), Some(checkout.id()));
assert_eq!(
repo.view().get_wc_commit_id(&workspace_id),
Some(checkout.id())
);
}
#[test_case(false ; "local backend")]
@ -462,7 +468,7 @@ fn test_has_changed(use_git: bool) {
mut_repo.remove_head(commit2.id());
mut_repo.add_public_head(&commit1);
let ws_id = WorkspaceId::default();
mut_repo.set_checkout(ws_id.clone(), commit1.id().clone());
mut_repo.set_wc_commit(ws_id.clone(), commit1.id().clone());
mut_repo.set_local_branch("main".to_string(), RefTarget::Normal(commit1.id().clone()));
mut_repo.set_remote_branch(
"main".to_string(),
@ -479,7 +485,7 @@ fn test_has_changed(use_git: bool) {
mut_repo.add_public_head(&commit1);
mut_repo.add_head(&commit1);
mut_repo.set_checkout(ws_id.clone(), commit1.id().clone());
mut_repo.set_wc_commit(ws_id.clone(), commit1.id().clone());
mut_repo.set_local_branch("main".to_string(), RefTarget::Normal(commit1.id().clone()));
mut_repo.set_remote_branch(
"main".to_string(),
@ -509,9 +515,9 @@ fn test_has_changed(use_git: bool) {
mut_repo.remove_head(commit2.id());
assert!(!mut_repo.has_changes());
mut_repo.set_checkout(ws_id.clone(), commit2.id().clone());
mut_repo.set_wc_commit(ws_id.clone(), commit2.id().clone());
assert!(mut_repo.has_changes());
mut_repo.set_checkout(ws_id, commit1.id().clone());
mut_repo.set_wc_commit(ws_id, commit1.id().clone());
assert!(!mut_repo.has_changes());
mut_repo.set_local_branch("main".to_string(), RefTarget::Normal(commit2.id().clone()));

View file

@ -262,8 +262,8 @@ fn test_resolve_symbol_checkout(use_git: bool) {
);
// Add some workspaces
mut_repo.set_checkout(ws1.clone(), commit1.id().clone());
mut_repo.set_checkout(ws2, commit2.id().clone());
mut_repo.set_wc_commit(ws1.clone(), commit1.id().clone());
mut_repo.set_wc_commit(ws2, commit2.id().clone());
// @ cannot be resolved without a default workspace ID
assert_eq!(
resolve_symbol(mut_repo.as_repo_ref(), "@", None),
@ -386,12 +386,16 @@ fn test_resolve_symbol_git_refs() {
// Cannot shadow checkout ("@") or root symbols
let ws_id = WorkspaceId::default();
mut_repo.set_checkout(ws_id.clone(), commit1.id().clone());
mut_repo.set_wc_commit(ws_id.clone(), commit1.id().clone());
mut_repo.set_git_ref("@".to_string(), RefTarget::Normal(commit2.id().clone()));
mut_repo.set_git_ref("root".to_string(), RefTarget::Normal(commit3.id().clone()));
assert_eq!(
resolve_symbol(mut_repo.as_repo_ref(), "@", Some(&ws_id)),
Ok(vec![mut_repo.view().get_checkout(&ws_id).unwrap().clone()])
Ok(vec![mut_repo
.view()
.get_wc_commit_id(&ws_id)
.unwrap()
.clone()])
);
assert_eq!(
resolve_symbol(mut_repo.as_repo_ref(), "root", None),
@ -449,7 +453,7 @@ fn test_evaluate_expression_root_and_checkout(use_git: bool) {
);
// Can find the current checkout
mut_repo.set_checkout(WorkspaceId::default(), commit1.id().clone());
mut_repo.set_wc_commit(WorkspaceId::default(), commit1.id().clone());
assert_eq!(
resolve_commit_ids_in_workspace(mut_repo.as_repo_ref(), "@", &WorkspaceId::default()),
vec![commit1.id().clone()]
@ -601,7 +605,7 @@ fn test_evaluate_expression_parents(use_git: bool) {
assert_eq!(resolve_commit_ids(mut_repo.as_repo_ref(), "root-"), vec![]);
// Can find parents of the current checkout
mut_repo.set_checkout(WorkspaceId::default(), commit2.id().clone());
mut_repo.set_wc_commit(WorkspaceId::default(), commit2.id().clone());
assert_eq!(
resolve_commit_ids_in_workspace(mut_repo.as_repo_ref(), "@-", &WorkspaceId::default()),
vec![commit1.id().clone()]

View file

@ -1277,11 +1277,11 @@ fn test_rebase_descendants_update_checkout(use_git: bool) {
let ws2_id = WorkspaceId::new("ws2".to_string());
let ws3_id = WorkspaceId::new("ws3".to_string());
tx.mut_repo()
.set_checkout(ws1_id.clone(), commit_b.id().clone());
.set_wc_commit(ws1_id.clone(), commit_b.id().clone());
tx.mut_repo()
.set_checkout(ws2_id.clone(), commit_b.id().clone());
.set_wc_commit(ws2_id.clone(), commit_b.id().clone());
tx.mut_repo()
.set_checkout(ws3_id.clone(), commit_a.id().clone());
.set_wc_commit(ws3_id.clone(), commit_a.id().clone());
let repo = tx.commit();
let mut tx = repo.start_transaction("test");
@ -1293,9 +1293,9 @@ fn test_rebase_descendants_update_checkout(use_git: bool) {
// Workspaces 1 and 2 had B checked out, so they get updated to C. Workspace 3
// had A checked out, so it doesn't get updated.
assert_eq!(repo.view().get_checkout(&ws1_id), Some(commit_c.id()));
assert_eq!(repo.view().get_checkout(&ws2_id), Some(commit_c.id()));
assert_eq!(repo.view().get_checkout(&ws3_id), Some(commit_a.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws1_id), Some(commit_c.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws2_id), Some(commit_c.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws3_id), Some(commit_a.id()));
}
#[test_case(false ; "local backend")]
@ -1321,11 +1321,11 @@ fn test_rebase_descendants_update_checkout_abandoned(use_git: bool) {
let ws2_id = WorkspaceId::new("ws2".to_string());
let ws3_id = WorkspaceId::new("ws3".to_string());
tx.mut_repo()
.set_checkout(ws1_id.clone(), commit_b.id().clone());
.set_wc_commit(ws1_id.clone(), commit_b.id().clone());
tx.mut_repo()
.set_checkout(ws2_id.clone(), commit_b.id().clone());
.set_wc_commit(ws2_id.clone(), commit_b.id().clone());
tx.mut_repo()
.set_checkout(ws3_id.clone(), commit_a.id().clone());
.set_wc_commit(ws3_id.clone(), commit_a.id().clone());
let repo = tx.commit();
let mut tx = repo.start_transaction("test");
@ -1336,16 +1336,16 @@ fn test_rebase_descendants_update_checkout_abandoned(use_git: bool) {
// Workspaces 1 and 2 had B checked out, so they get updated to the same new
// commit on top of C. Workspace 3 had A checked out, so it doesn't get updated.
assert_eq!(
repo.view().get_checkout(&ws1_id),
repo.view().get_checkout(&ws2_id)
repo.view().get_wc_commit_id(&ws1_id),
repo.view().get_wc_commit_id(&ws2_id)
);
let checkout = repo
.store()
.get_commit(repo.view().get_checkout(&ws1_id).unwrap())
.get_commit(repo.view().get_wc_commit_id(&ws1_id).unwrap())
.unwrap();
assert!(checkout.is_open());
assert_eq!(checkout.parent_ids(), vec![commit_a.id().clone()]);
assert_eq!(repo.view().get_checkout(&ws3_id), Some(commit_a.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws3_id), Some(commit_a.id()));
}
#[test_case(false ; "local backend")]
@ -1377,7 +1377,7 @@ fn test_rebase_descendants_update_checkout_abandoned_merge(use_git: bool) {
.write_to_repo(tx.mut_repo());
let workspace_id = WorkspaceId::default();
tx.mut_repo()
.set_checkout(workspace_id.clone(), commit_d.id().clone());
.set_wc_commit(workspace_id.clone(), commit_d.id().clone());
let repo = tx.commit();
let mut tx = repo.start_transaction("test");
@ -1385,7 +1385,7 @@ fn test_rebase_descendants_update_checkout_abandoned_merge(use_git: bool) {
tx.mut_repo().rebase_descendants(&settings).unwrap();
let repo = tx.commit();
let new_checkout_id = repo.view().get_checkout(&workspace_id).unwrap();
let new_checkout_id = repo.view().get_wc_commit_id(&workspace_id).unwrap();
let checkout = repo.store().get_commit(new_checkout_id).unwrap();
assert!(checkout.is_open());
assert_eq!(checkout.parent_ids(), vec![commit_b.id().clone()]);

View file

@ -178,43 +178,43 @@ fn test_merge_views_checkout() {
let ws7_id = WorkspaceId::new("ws7".to_string());
initial_tx
.mut_repo()
.set_checkout(ws1_id.clone(), commit1.id().clone());
.set_wc_commit(ws1_id.clone(), commit1.id().clone());
initial_tx
.mut_repo()
.set_checkout(ws2_id.clone(), commit1.id().clone());
.set_wc_commit(ws2_id.clone(), commit1.id().clone());
initial_tx
.mut_repo()
.set_checkout(ws3_id.clone(), commit1.id().clone());
.set_wc_commit(ws3_id.clone(), commit1.id().clone());
initial_tx
.mut_repo()
.set_checkout(ws4_id.clone(), commit1.id().clone());
.set_wc_commit(ws4_id.clone(), commit1.id().clone());
initial_tx
.mut_repo()
.set_checkout(ws5_id.clone(), commit1.id().clone());
.set_wc_commit(ws5_id.clone(), commit1.id().clone());
let repo = initial_tx.commit();
let mut tx1 = repo.start_transaction("test");
tx1.mut_repo()
.set_checkout(ws1_id.clone(), commit2.id().clone());
.set_wc_commit(ws1_id.clone(), commit2.id().clone());
tx1.mut_repo()
.set_checkout(ws2_id.clone(), commit2.id().clone());
tx1.mut_repo().remove_checkout(&ws4_id);
.set_wc_commit(ws2_id.clone(), commit2.id().clone());
tx1.mut_repo().remove_wc_commit(&ws4_id);
tx1.mut_repo()
.set_checkout(ws5_id.clone(), commit2.id().clone());
.set_wc_commit(ws5_id.clone(), commit2.id().clone());
tx1.mut_repo()
.set_checkout(ws6_id.clone(), commit2.id().clone());
.set_wc_commit(ws6_id.clone(), commit2.id().clone());
tx1.commit();
let mut tx2 = repo.start_transaction("test");
tx2.mut_repo()
.set_checkout(ws1_id.clone(), commit3.id().clone());
.set_wc_commit(ws1_id.clone(), commit3.id().clone());
tx2.mut_repo()
.set_checkout(ws3_id.clone(), commit3.id().clone());
.set_wc_commit(ws3_id.clone(), commit3.id().clone());
tx2.mut_repo()
.set_checkout(ws4_id.clone(), commit3.id().clone());
tx2.mut_repo().remove_checkout(&ws5_id);
.set_wc_commit(ws4_id.clone(), commit3.id().clone());
tx2.mut_repo().remove_wc_commit(&ws5_id);
tx2.mut_repo()
.set_checkout(ws7_id.clone(), commit3.id().clone());
.set_wc_commit(ws7_id.clone(), commit3.id().clone());
// Make sure the end time different, assuming the clock has sub-millisecond
// precision.
std::thread::sleep(std::time::Duration::from_millis(1));
@ -224,13 +224,13 @@ fn test_merge_views_checkout() {
// We currently arbitrarily pick the first transaction's checkout (first by
// transaction end time).
assert_eq!(repo.view().get_checkout(&ws1_id), Some(commit2.id()));
assert_eq!(repo.view().get_checkout(&ws2_id), Some(commit2.id()));
assert_eq!(repo.view().get_checkout(&ws3_id), Some(commit3.id()));
assert_eq!(repo.view().get_checkout(&ws4_id), None);
assert_eq!(repo.view().get_checkout(&ws5_id), None);
assert_eq!(repo.view().get_checkout(&ws6_id), Some(commit2.id()));
assert_eq!(repo.view().get_checkout(&ws7_id), Some(commit3.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws1_id), Some(commit2.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws2_id), Some(commit2.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws3_id), Some(commit3.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws4_id), None);
assert_eq!(repo.view().get_wc_commit_id(&ws5_id), None);
assert_eq!(repo.view().get_wc_commit_id(&ws6_id), Some(commit2.id()));
assert_eq!(repo.view().get_wc_commit_id(&ws7_id), Some(commit3.id()));
}
#[test]

View file

@ -48,7 +48,10 @@ fn test_root(use_git: bool) {
let mut locked_wc = wc.start_mutation();
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty()).unwrap();
locked_wc.discard();
let checkout_id = repo.view().get_checkout(&WorkspaceId::default()).unwrap();
let checkout_id = repo
.view()
.get_wc_commit_id(&WorkspaceId::default())
.unwrap();
let checkout_commit = repo.store().get_commit(checkout_id).unwrap();
assert_eq!(&new_tree_id, checkout_commit.tree_id());
assert_eq!(&new_tree_id, repo.store().empty_tree_id());

View file

@ -28,7 +28,7 @@ use test_case::test_case;
#[test_case(true ; "git backend")]
fn test_concurrent_checkout(use_git: bool) {
// Test that we error out if a concurrent checkout is detected (i.e. if the
// current checkout changed on disk after we read it).
// working-copy commit changed on disk after we read it).
let settings = testutils::user_settings();
let mut test_workspace1 = TestWorkspace::init(&settings, use_git);
let repo1 = test_workspace1.repo.clone();

View file

@ -64,12 +64,12 @@ fn test_init_additional_workspace(use_git: bool) {
ws2_id.clone(),
)
.unwrap();
let checkout_id = repo.view().get_checkout(&ws2_id);
assert_ne!(checkout_id, None);
let checkout_id = checkout_id.unwrap();
let checkout_commit = repo.store().get_commit(checkout_id).unwrap();
let wc_commit_id = repo.view().get_wc_commit_id(&ws2_id);
assert_ne!(wc_commit_id, None);
let wc_commit_id = wc_commit_id.unwrap();
let wc_commit = repo.store().get_commit(wc_commit_id).unwrap();
assert_eq!(
checkout_commit.parent_ids(),
wc_commit.parent_ids(),
vec![repo.store().root_commit_id().clone()]
);
assert_eq!(ws2.workspace_id(), ws2_id);

View file

@ -378,8 +378,9 @@ impl WorkspaceCommandHelper {
if new_git_head != old_git_head && new_git_head.is_some() {
let workspace_id = self.workspace.workspace_id();
let mut locked_working_copy = self.workspace.working_copy_mut().start_mutation();
if let Some(old_checkout) = self.repo.view().get_checkout(&workspace_id) {
tx.mut_repo().record_abandoned_commit(old_checkout.clone());
if let Some(old_wc_commit_id) = self.repo.view().get_wc_commit_id(&workspace_id) {
tx.mut_repo()
.record_abandoned_commit(old_wc_commit_id.clone());
}
let new_checkout = self
.repo
@ -416,7 +417,7 @@ impl WorkspaceCommandHelper {
.peel_to_commit()
.ok()
.map(|commit| commit.id());
if let Some(checkout_id) = mut_repo.view().get_checkout(&self.workspace_id()) {
if let Some(checkout_id) = mut_repo.view().get_wc_commit_id(&self.workspace_id()) {
let first_parent_id =
mut_repo.index().entry_by_id(checkout_id).unwrap().parents()[0].commit_id();
if first_parent_id != *mut_repo.store().root_commit_id() {
@ -451,9 +452,9 @@ impl WorkspaceCommandHelper {
fn start_working_copy_mutation(&mut self) -> Result<(LockedWorkingCopy, Commit), CommandError> {
self.check_working_copy_writable()?;
let current_checkout_id = self.repo.view().get_checkout(&self.workspace_id());
let current_checkout = if let Some(current_checkout_id) = current_checkout_id {
self.repo.store().get_commit(current_checkout_id)?
let wc_commit_id = self.repo.view().get_wc_commit_id(&self.workspace_id());
let wc_commit = if let Some(wc_commit_id) = wc_commit_id {
self.repo.store().get_commit(wc_commit_id)?
} else {
return Err(CommandError::UserError(
"Nothing checked out in this workspace".to_string(),
@ -461,13 +462,13 @@ impl WorkspaceCommandHelper {
};
let locked_working_copy = self.workspace.working_copy_mut().start_mutation();
if current_checkout.tree_id() != locked_working_copy.old_tree_id() {
if wc_commit.tree_id() != locked_working_copy.old_tree_id() {
return Err(CommandError::UserError(
"Concurrent working copy operation. Try again.".to_string(),
));
}
Ok((locked_working_copy, current_checkout))
Ok((locked_working_copy, wc_commit))
}
fn workspace_root(&self) -> &PathBuf {
@ -577,7 +578,7 @@ impl WorkspaceCommandHelper {
fn commit_working_copy(&mut self, ui: &mut Ui) -> Result<(), CommandError> {
let repo = self.repo.clone();
let workspace_id = self.workspace_id();
let checkout_id = match repo.view().get_checkout(&self.workspace_id()) {
let checkout_id = match repo.view().get_wc_commit_id(&self.workspace_id()) {
Some(checkout_id) => checkout_id.clone(),
None => {
// If the workspace has been deleted, it's unclear what to do, so we just skip
@ -662,7 +663,7 @@ impl WorkspaceCommandHelper {
let commit = CommitBuilder::for_rewrite_from(&self.settings, &checkout_commit)
.set_tree(new_tree_id)
.write_to_repo(mut_repo);
mut_repo.set_checkout(workspace_id, commit.id().clone());
mut_repo.set_wc_commit(workspace_id, commit.id().clone());
// Rebase descendants
let num_rebased = mut_repo.rebase_descendants(&self.settings)?;
@ -784,7 +785,7 @@ impl WorkspaceCommandHelper {
let maybe_old_commit = tx
.base_repo()
.view()
.get_checkout(&self.workspace_id())
.get_wc_commit_id(&self.workspace_id())
.map(|commit_id| store.get_commit(commit_id))
.transpose()?;
self.repo = tx.commit();
@ -1005,7 +1006,7 @@ fn update_working_copy(
wc: &mut WorkingCopy,
old_commit: Option<&Commit>,
) -> Result<Option<CheckoutStats>, CommandError> {
let new_commit_id = match repo.view().get_checkout(workspace_id) {
let new_commit_id = match repo.view().get_wc_commit_id(workspace_id) {
Some(new_commit_id) => new_commit_id,
None => {
// It seems the workspace was deleted, so we shouldn't try to update it.
@ -2209,7 +2210,12 @@ fn cmd_checkout(
let target = workspace_command.resolve_single_rev(&args.revision)?;
let workspace_id = workspace_command.workspace_id();
if ui.settings().enable_open_commits() {
if workspace_command.repo().view().get_checkout(&workspace_id) == Some(target.id()) {
if workspace_command
.repo()
.view()
.get_wc_commit_id(&workspace_id)
== Some(target.id())
{
ui.write("Already on that commit\n")?;
} else {
let mut tx = workspace_command
@ -2255,11 +2261,10 @@ fn cmd_untrack(
let mut tx = workspace_command.start_transaction("untrack paths");
let base_ignores = workspace_command.base_ignores();
let (mut locked_working_copy, current_checkout) =
workspace_command.start_working_copy_mutation()?;
let (mut locked_working_copy, wc_commit) = workspace_command.start_working_copy_mutation()?;
// Create a new tree without the unwanted files
let mut tree_builder = store.tree_builder(current_checkout.tree_id().clone());
for (path, _value) in current_checkout.tree().entries_matching(matcher.as_ref()) {
let mut tree_builder = store.tree_builder(wc_commit.tree_id().clone());
for (path, _value) in wc_commit.tree().entries_matching(matcher.as_ref()) {
tree_builder.remove(path);
}
let new_tree_id = tree_builder.write_tree();
@ -2296,7 +2301,7 @@ fn cmd_untrack(
locked_working_copy.reset(&new_tree)?;
}
}
CommitBuilder::for_rewrite_from(ui.settings(), &current_checkout)
CommitBuilder::for_rewrite_from(ui.settings(), &wc_commit)
.set_tree(new_tree_id)
.write_to_repo(tx.mut_repo());
let num_rebased = tx.mut_repo().rebase_descendants(ui.settings())?;
@ -2996,7 +3001,9 @@ fn cmd_status(
) -> Result<(), CommandError> {
let workspace_command = command.workspace_helper(ui)?;
let repo = workspace_command.repo();
let maybe_checkout_id = repo.view().get_checkout(&workspace_command.workspace_id());
let maybe_checkout_id = repo
.view()
.get_wc_commit_id(&workspace_command.workspace_id());
let maybe_checkout = maybe_checkout_id
.map(|id| repo.store().get_commit(id))
.transpose()?;
@ -3129,7 +3136,7 @@ fn cmd_log(ui: &mut Ui, command: &CommandHelper, args: &LogArgs) -> Result<(), C
let revset_expression = revset::parse(&args.revisions)?;
let repo = workspace_command.repo();
let workspace_id = workspace_command.workspace_id();
let checkout_id = repo.view().get_checkout(&workspace_id);
let checkout_id = repo.view().get_wc_commit_id(&workspace_id);
let matcher = matcher_from_values(ui, workspace_command.workspace_root(), &args.paths)?;
let mut revset = revset_expression.evaluate(repo.as_repo_ref(), Some(&workspace_id))?;
if !args.paths.is_empty() {
@ -3265,7 +3272,10 @@ fn cmd_obslog(ui: &mut Ui, command: &CommandHelper, args: &ObslogArgs) -> Result
let start_commit = workspace_command.resolve_single_rev(&args.revision)?;
let workspace_id = workspace_command.workspace_id();
let checkout_id = workspace_command.repo().view().get_checkout(&workspace_id);
let wc_commit_id = workspace_command
.repo()
.view()
.get_wc_commit_id(&workspace_id);
let diff_format = (args.patch || args.diff_format.git || args.diff_format.summary)
.then(|| diff_format_for(ui, &args.diff_format));
@ -3315,7 +3325,7 @@ fn cmd_obslog(ui: &mut Ui, command: &CommandHelper, args: &ObslogArgs) -> Result
diff_format,
)?;
}
let node_symbol = if Some(commit.id()) == checkout_id {
let node_symbol = if Some(commit.id()) == wc_commit_id {
b"@"
} else {
b"o"
@ -3524,7 +3534,10 @@ fn cmd_close(ui: &mut Ui, command: &CommandHelper, args: &CloseArgs) -> Result<(
let mut tx =
workspace_command.start_transaction(&format!("close commit {}", commit.id().hex()));
let new_commit = commit_builder.write_to_repo(tx.mut_repo());
let workspace_ids = tx.mut_repo().view().workspaces_for_checkout(commit.id());
let workspace_ids = tx
.mut_repo()
.view()
.workspaces_for_wc_commit_id(commit.id());
if !workspace_ids.is_empty() {
let new_checkout = CommitBuilder::for_open_commit(
ui.settings(),
@ -3611,7 +3624,12 @@ fn cmd_edit(ui: &mut Ui, command: &CommandHelper, args: &EditArgs) -> Result<(),
let mut workspace_command = command.workspace_helper(ui)?;
let new_commit = workspace_command.resolve_single_rev(&args.revision)?;
let workspace_id = workspace_command.workspace_id();
if workspace_command.repo().view().get_checkout(&workspace_id) == Some(new_commit.id()) {
if workspace_command
.repo()
.view()
.get_wc_commit_id(&workspace_id)
== Some(new_commit.id())
{
ui.write("Already editing that commit\n")?;
} else {
let mut tx =
@ -4904,7 +4922,7 @@ fn cmd_workspace_add(
};
let workspace_id = WorkspaceId::new(name.clone());
let repo = old_workspace_command.repo();
if repo.view().get_checkout(&workspace_id).is_some() {
if repo.view().get_wc_commit_id(&workspace_id).is_some() {
return Err(UserError(format!(
"Workspace named '{}' already exists",
name
@ -4936,7 +4954,7 @@ fn cmd_workspace_add(
let new_checkout_commit = if let Some(old_checkout_id) = new_workspace_command
.repo()
.view()
.get_checkout(&old_workspace_command.workspace_id())
.get_wc_commit_id(&old_workspace_command.workspace_id())
{
new_workspace_command
.repo()
@ -4971,7 +4989,7 @@ fn cmd_workspace_forget(
if workspace_command
.repo()
.view()
.get_checkout(&workspace_id)
.get_wc_commit_id(&workspace_id)
.is_none()
{
return Err(UserError("No such workspace".to_string()));
@ -4979,7 +4997,7 @@ fn cmd_workspace_forget(
let mut tx =
workspace_command.start_transaction(&format!("forget workspace {}", workspace_id.as_str()));
tx.mut_repo().remove_checkout(&workspace_id);
tx.mut_repo().remove_wc_commit(&workspace_id);
workspace_command.finish_transaction(ui, tx)?;
Ok(())
}
@ -4991,7 +5009,7 @@ fn cmd_workspace_list(
) -> Result<(), CommandError> {
let workspace_command = command.workspace_helper(ui)?;
let repo = workspace_command.repo();
for (workspace_id, checkout_id) in repo.view().checkouts().iter().sorted() {
for (workspace_id, checkout_id) in repo.view().wc_commit_ids().iter().sorted() {
write!(ui, "{}: ", workspace_id.as_str())?;
let commit = repo.store().get_commit(checkout_id)?;
ui.write_commit_summary(repo.as_repo_ref(), workspace_id, &commit)?;
@ -5011,7 +5029,7 @@ fn cmd_sparse(ui: &mut Ui, command: &CommandHelper, args: &SparseArgs) -> Result
let mut workspace_command = command.workspace_helper(ui)?;
let workspace_root = workspace_command.workspace_root().clone();
let paths_to_add = repo_paths_from_values(ui, &workspace_root, &args.add)?;
let (mut locked_wc, _current_checkout) = workspace_command.start_working_copy_mutation()?;
let (mut locked_wc, _wc_commit) = workspace_command.start_working_copy_mutation()?;
let mut new_patterns = HashSet::new();
if args.reset {
new_patterns.insert(RepoPath::root());
@ -5326,7 +5344,7 @@ fn cmd_git_push(
match workspace_command
.repo()
.view()
.get_checkout(&workspace_command.workspace_id())
.get_wc_commit_id(&workspace_command.workspace_id())
{
None => {
return Err(UserError(

View file

@ -24,11 +24,12 @@ use pest::Parser;
use crate::formatter::PlainTextFormatter;
use crate::templater::{
AuthorProperty, BranchProperty, ChangeIdProperty, CheckoutsProperty, CommitIdKeyword,
CommitterProperty, ConditionalTemplate, ConflictProperty, ConstantTemplateProperty,
CurrentCheckoutProperty, DescriptionProperty, DivergentProperty, DynamicLabelTemplate,
GitRefsProperty, IsGitHeadProperty, LabelTemplate, ListTemplate, LiteralTemplate, OpenProperty,
AuthorProperty, BranchProperty, ChangeIdProperty, CommitIdKeyword, CommitterProperty,
ConditionalTemplate, ConflictProperty, ConstantTemplateProperty, DescriptionProperty,
DivergentProperty, DynamicLabelTemplate, GitRefsProperty, IsGitHeadProperty,
IsWorkingCopyProperty, LabelTemplate, ListTemplate, LiteralTemplate, OpenProperty,
StringPropertyTemplate, TagProperty, Template, TemplateFunction, TemplateProperty,
WorkingCopiesProperty,
};
#[derive(Parser)]
@ -243,8 +244,8 @@ fn parse_commit_keyword<'a>(
"author" => Property::Signature(Box::new(AuthorProperty)),
"committer" => Property::Signature(Box::new(CommitterProperty)),
"open" => Property::Boolean(Box::new(OpenProperty)),
"working_copies" => Property::String(Box::new(CheckoutsProperty { repo })),
"current_working_copy" => Property::Boolean(Box::new(CurrentCheckoutProperty {
"working_copies" => Property::String(Box::new(WorkingCopiesProperty { repo })),
"current_working_copy" => Property::Boolean(Box::new(IsWorkingCopyProperty {
repo,
workspace_id: workspace_id.clone(),
})),

View file

@ -207,19 +207,19 @@ impl TemplateProperty<Commit, bool> for OpenProperty {
}
}
pub struct CheckoutsProperty<'a> {
pub struct WorkingCopiesProperty<'a> {
pub repo: RepoRef<'a>,
}
impl TemplateProperty<Commit, String> for CheckoutsProperty<'_> {
impl TemplateProperty<Commit, String> for WorkingCopiesProperty<'_> {
fn extract(&self, context: &Commit) -> String {
let checkouts = self.repo.view().checkouts();
if checkouts.len() <= 1 {
let wc_commit_ids = self.repo.view().wc_commit_ids();
if wc_commit_ids.len() <= 1 {
return "".to_string();
}
let mut names = vec![];
for (workspace_id, checkout_id) in checkouts.iter().sorted() {
if checkout_id == context.id() {
for (workspace_id, wc_commit_id) in wc_commit_ids.iter().sorted() {
if wc_commit_id == context.id() {
names.push(format!("{}@", workspace_id.as_str()));
}
}
@ -227,14 +227,14 @@ impl TemplateProperty<Commit, String> for CheckoutsProperty<'_> {
}
}
pub struct CurrentCheckoutProperty<'a> {
pub struct IsWorkingCopyProperty<'a> {
pub repo: RepoRef<'a>,
pub workspace_id: WorkspaceId,
}
impl TemplateProperty<Commit, bool> for CurrentCheckoutProperty<'_> {
impl TemplateProperty<Commit, bool> for IsWorkingCopyProperty<'_> {
fn extract(&self, context: &Commit) -> bool {
Some(context.id()) == self.repo.view().get_checkout(&self.workspace_id)
Some(context.id()) == self.repo.view().get_wc_commit_id(&self.workspace_id)
}
}

View file

@ -163,7 +163,7 @@ fn test_workspaces_forget() {
No working copy
"###);
// The old checkout doesn't get an "@" in the log output
// The old working copy doesn't get an "@" in the log output
// TODO: We should abandon the empty working copy commit
// TODO: It seems useful to still have the "secondary@" marker here even though
// there's only one workspace. We should show it when the command is not run
@ -198,5 +198,5 @@ fn test_workspaces_forget() {
}
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
test_env.jj_cmd_success(cwd, &["log", "-T", r#"commit_id " " checkouts"#])
test_env.jj_cmd_success(cwd, &["log", "-T", r#"commit_id " " working_copies"#])
}