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

workspace: make recovery commit empty instead of deleting everything

The recovery commit we create when we run into a stale working copy
with a missing operation currently has an empty tree. Our commit
backend at Google creates an index of which files changed in each
commit. That gets really expensive when a commit deletes all files in
the repo, as these recovery commits do. So for our backend, it is much
better to make the recovery commit empty instead. That's what this
patch does.

It almost doesn't matter functionally what tree we use for it since we
don't care much about the current tree when snapshotting the working
copy. It does matter in a few cases, however. One case is for
conflicts. In that case, it's likely better to use the recovery
commit's parent as base tree (as we do by making the recovery commit
empty) than to use an empty tree, as that would guarantee that all
conflicts would be considered resolved. (Side note: perhaps we should
start looking at the current commit's parent instead of looking at the
current commit when snapshotting, but that's a topic for another day.)
This commit is contained in:
Martin von Zweigbergk 2024-02-26 21:30:13 -08:00 committed by Martin von Zweigbergk
parent 9ad2fee72b
commit 81e9ba3d51
2 changed files with 10 additions and 7 deletions

View file

@ -307,14 +307,17 @@ fn create_and_check_out_recovery_commit(
let workspace_id = workspace_command.workspace_id().clone(); let workspace_id = workspace_command.workspace_id().clone();
let mut tx = workspace_command.start_transaction().into_inner(); let mut tx = workspace_command.start_transaction().into_inner();
let tree_id = workspace_command.repo().store().empty_merged_tree_id();
let (mut locked_workspace, commit) = let (mut locked_workspace, commit) =
workspace_command.unchecked_start_working_copy_mutation()?; workspace_command.unchecked_start_working_copy_mutation()?;
let commit_id = commit.id(); let commit_id = commit.id();
let mut_repo = tx.mut_repo(); let mut_repo = tx.mut_repo();
let new_commit = mut_repo let new_commit = mut_repo
.new_commit(command.settings(), vec![commit_id.clone()], tree_id.clone()) .new_commit(
command.settings(),
vec![commit_id.clone()],
commit.tree_id().clone(),
)
.write()?; .write()?;
mut_repo.set_wc_commit(workspace_id, new_commit.id().clone())?; mut_repo.set_wc_commit(workspace_id, new_commit.id().clone())?;
let repo = tx.commit("recovery commit"); let repo = tx.commit("recovery commit");

View file

@ -467,12 +467,12 @@ fn test_workspaces_current_op_discarded_by_other() {
let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["workspace", "update-stale"]); let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["workspace", "update-stale"]);
insta::assert_snapshot!(stderr, @r###" insta::assert_snapshot!(stderr, @r###"
Failed to read working copy's current operation; attempting recovery. Error message from read attempt: Object 47f1ad5e1adfaa1e9863181e6e45ae12b9db553e82bde82e278c0c6288053c833b4039a5baf2415871964bcdcd4b7875692979e66f2ec18bfc3896355091cf53 of type operation not found Failed to read working copy's current operation; attempting recovery. Error message from read attempt: Object 47f1ad5e1adfaa1e9863181e6e45ae12b9db553e82bde82e278c0c6288053c833b4039a5baf2415871964bcdcd4b7875692979e66f2ec18bfc3896355091cf53 of type operation not found
Created and checked out recovery commit 9d040f9a433c Created and checked out recovery commit df3e46148439
"###); "###);
insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(get_log_output(&test_env, &main_path), @r###" insta::assert_snapshot!(get_log_output(&test_env, &main_path), @r###"
e5b7d155229f587a96678aaa23b771c694f5bb8ad690e1312b90dd3c73b01ab26ea0a2946aa2760f3c672f1587f2742718a6596c46c3a3b881122906164c081a secondary@ 54400d0c58b790c53de57a1c28090d23739010b300ac17cb47c26d1e48d41bb6583c94a5e4e71b32bbe1e50190c67141525e92aba9ae7b7a413ed1c989629874 secondary@
4278b78fb503846224c4328785f8557558aab32b1e3d6ad6b343e94575dd5c67492acea9aa1c417817b4943e78547877e031208a51f8eadcd1ac55d6ebe77983 4278b78fb503846224c4328785f8557558aab32b1e3d6ad6b343e94575dd5c67492acea9aa1c417817b4943e78547877e031208a51f8eadcd1ac55d6ebe77983
@ 6dc8f254cd3cbe5c086fb99adc66724303d7ceb12790e585e5946940dffca60dbb928b852e3c309b20dee351df5897f49b83c89d583a756fd736772b3e5f206a default@ @ 6dc8f254cd3cbe5c086fb99adc66724303d7ceb12790e585e5946940dffca60dbb928b852e3c309b20dee351df5897f49b83c89d583a756fd736772b3e5f206a default@
@ -484,16 +484,16 @@ fn test_workspaces_current_op_discarded_by_other() {
insta::assert_snapshot!(stdout, @r###" insta::assert_snapshot!(stdout, @r###"
Working copy changes: Working copy changes:
A file A file
Working copy : znkkpsqq e5b7d155 (no description set) Working copy : znkkpsqq 54400d0c (no description set)
Parent commit: pmmvwywv 4278b78f (empty) (no description set) Parent commit: pmmvwywv 4278b78f (empty) (no description set)
"###); "###);
let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["obslog"]); let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["obslog"]);
insta::assert_snapshot!(stderr, @""); insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(stdout, @r###" insta::assert_snapshot!(stdout, @r###"
@ znkkpsqq test.user@example.com 2001-02-03 04:05:16.000 +07:00 secondary@ e5b7d155 @ znkkpsqq test.user@example.com 2001-02-03 04:05:16.000 +07:00 secondary@ 54400d0c
(no description set) (no description set)
znkkpsqq hidden test.user@example.com 2001-02-03 04:05:16.000 +07:00 9d040f9a znkkpsqq hidden test.user@example.com 2001-02-03 04:05:16.000 +07:00 df3e4614
(empty) (no description set) (empty) (no description set)
"###); "###);
} }