repo: teach OpStore about the root commit id

This removes an invalid View state from the root operation.

Note that the root index will have to be reindexed in order to resolve "root()"
in the root operation. I don't think this would practically matter, so this
patch doesn't bump the index version to invalidate the existing indexes.

See also 48a9f9ef56 "repo: use Transaction for creating repo-init operation."
This commit is contained in:
Yuya Nishihara 2024-10-07 11:00:37 +09:00
parent 2df442299d
commit ae62b5b946
17 changed files with 393 additions and 454 deletions

View file

@ -32,23 +32,21 @@ fn test_concurrent_operation_divergence() {
// "--at-op=@" disables op heads merging, and prints head operation ids.
let stderr = test_env.jj_cmd_failure(&repo_path, &["op", "log", "--at-op=@"]);
insta::assert_snapshot!(stderr, @r###"
insta::assert_snapshot!(stderr, @r#"
Error: The "@" expression resolved to more than one operation
Hint: Try specifying one of the operations by ID: e31015019d90, 48f4a48f3f70
"###);
Hint: Try specifying one of the operations by ID: 0162305507cc, d74dff64472e
"#);
// "op log --at-op" should work without merging the head operations
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log", "--at-op=48f4a48f3f70"]);
insta::assert_snapshot!(stdout, @r###"
@ 48f4a48f3f70 test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log", "--at-op=d74dff64472e"]);
insta::assert_snapshot!(stdout, @r#"
@ d74dff64472e test-username@host.example.com 2001-02-03 04:05:09.000 +07:00 - 2001-02-03 04:05:09.000 +07:00
describe commit 230dd059e1b059aefc0da06a2e5a7dbf22362f22
args: jj describe -m 'message 2' --at-op @-
b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
eac759b9ab75 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
add workspace 'default'
9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
initialize repo
000000000000 root()
"###);
"#);
// We should be informed about the concurrent modification
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["log", "-T", "description"]);
@ -72,19 +70,17 @@ fn test_concurrent_operations_auto_rebase() {
std::fs::write(repo_path.join("file"), "contents").unwrap();
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
insta::assert_snapshot!(stdout, @r###"
@ 66d1dd775c54 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
insta::assert_snapshot!(stdout, @r#"
@ c62ace5c0522 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
describe commit 4e8f9d2be039994f589b4e57ac5e9488703e604d
args: jj describe -m initial
130d67859810 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
82d32fc68fc3 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
snapshot working copy
args: jj describe -m initial
b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
eac759b9ab75 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
add workspace 'default'
9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
initialize repo
000000000000 root()
"###);
"#);
let op_id_hex = stdout[3..15].to_string();
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "rewritten"]);
@ -152,7 +148,7 @@ fn test_concurrent_operations_wc_modified() {
// The working copy should be committed after merging the operations
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log", "-Tdescription"]);
insta::assert_snapshot!(stdout, @r###"
insta::assert_snapshot!(stdout, @r#"
@ snapshot working copy
reconcile divergent operations
@ -162,9 +158,8 @@ fn test_concurrent_operations_wc_modified() {
describe commit 506f4ec3c2c62befa15fabc34ca9d4e6d7bef254
snapshot working copy
add workspace 'default'
initialize repo
"###);
"#);
}
#[test]
@ -187,26 +182,24 @@ fn test_concurrent_snapshot_wc_reloadable() {
let template = r#"id ++ "\n" ++ description ++ "\n" ++ tags"#;
let op_log_stdout = test_env.jj_cmd_success(&repo_path, &["op", "log", "-T", template]);
insta::assert_snapshot!(op_log_stdout, @r###"
@ 9f11958bcf79340028eeabf9b0381cd8d2ae2258d0097b8ce8bd24fe7138eca08d9eb113bb4722ebacd9b7a6fa017e3888f72907be7487f275823c8d21359eed
insta::assert_snapshot!(op_log_stdout, @r#"
@ ec6bf266624bbaed55833a34ae62fa95c0e9efa651b94eb28846972da645845052dcdc8580332a5628849f23f48b9e99fc728dc3fb13106df8d0666d746f8b85
commit 554d22b2c43c1c47e279430197363e8daabe2fd6
args: jj commit -m 'new child1'
f5460e8f43a04fbc61553d12fa5ba8d3b12e4fdcfda1999db6b67cc8e1e473b7e62cc0536196a53b84f34e18c1c6d608f427bb64bd5f834f845a9859e39cb320
23858df860b789e8176a73c0eb21804e3f1848f26d68b70d234c004d08980c41499b6669042bca20fbc2543c437222a084c7cd473e91c7a9a095a02bf38544ab
snapshot working copy
args: jj commit -m 'new child1'
49359b6597ead3fbb66802a6bbd8761c0ad4646a2b089090d6fd72fb6e2568aa99c4a92f9f1f252a83cce56ec84961c36e85f731f19fc5a4c24d6a3f7282b774
e1db5fa988fc66e5cc0491b00c53fb93e25e730341c850cb42e1e0db0c76d2b4065005787563301b1d292c104f381918897f7deabeb92d2532f42ce75d3fe588
commit de71e09289762a65f80bb1c3dae2a949df6bcde7
args: jj commit -m initial
86dbba2b96a4a801abef7f77f8fdf338b6e36f81ea4a531aacf06acbd06f4037731fffef42503c2225fdb206488971c1601ca8b2b4a83a3fe2dce64ee4db085e
7de878155a459b7751097222132c935f9dcbb8f69a72b0f3a9036345a963010a553dc7c92964220128679ead72b087ca3aaf4ab9e20a221d1ffa4f9e92a32193
snapshot working copy
args: jj commit -m initial
b51416386f2685fd5493f2b20e8eec3c24a1776d9e1a7cb5ed7e30d2d9c88c0c1e1fe71b0b7358cba60de42533d1228ed9878f2f89817d892c803395ccf9fe92
eac759b9ab75793fd3da96e60939fb48f2cd2b2a9c1f13ffe723cf620f3005b8d3e7e923634a07ea39513e4f2f360c87b9ad5d331cf90d7a844864b83b72eba1
add workspace 'default'
9a7d829846af88a2f7a1e348fb46ff58729e49632bc9c6a052aec8501563cb0d10f4a4e6010ffde529f84a2b9b5b3a4c211a889106a41f6c076dfdacc79f6af7
initialize repo
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
"###);
"#);
let op_log_lines = op_log_stdout.lines().collect_vec();
let current_op_id = op_log_lines[0].split_once(" ").unwrap().1;
let previous_op_id = op_log_lines[6].split_once(" ").unwrap().1;

View file

@ -235,9 +235,9 @@ fn test_debug_operation_id() {
let workspace_path = test_env.env_root().join("repo");
let stdout =
test_env.jj_cmd_success(&workspace_path, &["debug", "operation", "--display", "id"]);
assert_snapshot!(filter_index_stats(&stdout), @r###"
b51416386f2685fd5493f2b20e8eec3c24a1776d9e1a7cb5ed7e30d2d9c88c0c1e1fe71b0b7358cba60de42533d1228ed9878f2f89817d892c803395ccf9fe92
"###
assert_snapshot!(filter_index_stats(&stdout), @r#"
eac759b9ab75793fd3da96e60939fb48f2cd2b2a9c1f13ffe723cf620f3005b8d3e7e923634a07ea39513e4f2f360c87b9ad5d331cf90d7a844864b83b72eba1
"#
);
}

View file

@ -76,7 +76,7 @@ fn test_duplicate() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["undo"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Undid operation c4b0b2a977fe 2001-02-03 04:05:17.000 +07:00 - 2001-02-03 04:05:17.000 +07:00 duplicate 1 commit(s)
Undid operation b5bdbb51ab28 2001-02-03 04:05:17.000 +07:00 - 2001-02-03 04:05:17.000 +07:00 duplicate 1 commit(s)
"#);
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["duplicate" /* duplicates `c` */]);
insta::assert_snapshot!(stdout, @"");
@ -280,7 +280,7 @@ fn test_undo_after_duplicate() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["undo"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Undid operation 5a2bcfcdd78b 2001-02-03 04:05:11.000 +07:00 - 2001-02-03 04:05:11.000 +07:00 duplicate 1 commit(s)
Undid operation e3dbefa46ed5 2001-02-03 04:05:11.000 +07:00 - 2001-02-03 04:05:11.000 +07:00 duplicate 1 commit(s)
"#);
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
@ 2443ea76b0b1 a

View file

@ -475,11 +475,11 @@ fn test_git_clone_ignore_working_copy() {
// TODO: Correct, but might be better to check out the root commit?
let stderr = test_env.jj_cmd_failure(&clone_path, &["status"]);
insta::assert_snapshot!(stderr, @r###"
Error: The working copy is stale (not updated since operation b51416386f26).
insta::assert_snapshot!(stderr, @r##"
Error: The working copy is stale (not updated since operation eac759b9ab75).
Hint: Run `jj workspace update-stale` to update it.
See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy for more information.
"###);
"##);
}
#[test]

View file

@ -757,7 +757,7 @@ fn test_git_colocated_undo_head_move() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["undo"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Undid operation 951a1c249028 2001-02-03 04:05:13.000 +07:00 - 2001-02-03 04:05:13.000 +07:00 new empty commit
Undid operation b50ec983d1c1 2001-02-03 04:05:13.000 +07:00 - 2001-02-03 04:05:13.000 +07:00 new empty commit
Working copy now at: royxmykx eb08b363 (empty) (no description set)
Parent commit : qpvuntsm 230dd059 (empty) (no description set)
"#);

View file

@ -932,7 +932,7 @@ fn test_git_fetch_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&target_jj_repo_path, &["undo"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Undid operation bbebbf6a6ebe 2001-02-03 04:05:18.000 +07:00 - 2001-02-03 04:05:18.000 +07:00 fetch from git remote(s) origin
Undid operation eb2029853b02 2001-02-03 04:05:18.000 +07:00 - 2001-02-03 04:05:18.000 +07:00 fetch from git remote(s) origin
"#);
// The undo works as expected
insta::assert_snapshot!(get_log_output(&test_env, &target_jj_repo_path), @r###"
@ -1018,7 +1018,7 @@ fn test_fetch_undo_what() {
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Restored to operation b51416386f26 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
Restored to operation eac759b9ab75 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
"#);
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
b (deleted)
@ -1047,7 +1047,7 @@ fn test_fetch_undo_what() {
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Restored to operation b51416386f26 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
Restored to operation eac759b9ab75 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
"#);
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###"
newbookmark: qpvuntsm 230dd059 (empty) (no description set)

View file

@ -101,7 +101,7 @@ fn test_git_export_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "undo"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Undid operation 1bc51ad79d63 2001-02-03 04:05:10.000 +07:00 - 2001-02-03 04:05:10.000 +07:00 export git refs
Undid operation b27a68390bea 2001-02-03 04:05:10.000 +07:00 - 2001-02-03 04:05:10.000 +07:00 export git refs
"#);
insta::assert_debug_snapshot!(get_git_repo_refs(&git_repo), @r###"
[
@ -162,7 +162,7 @@ fn test_git_import_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "restore", &base_operation_id]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Restored to operation b51416386f26 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
Restored to operation eac759b9ab75 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
"#);
insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @"");
// Try "git import" again, which should re-import the bookmark "a".
@ -228,7 +228,7 @@ fn test_git_import_move_export_with_default_undo() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "restore", &base_operation_id]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Restored to operation b51416386f26 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
Restored to operation eac759b9ab75 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00 add workspace 'default'
Working copy now at: qpvuntsm 230dd059 (empty) (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
"#);

File diff suppressed because it is too large Load diff

View file

@ -681,7 +681,7 @@ fn test_rebase_revision_onto_descendant() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Restored to operation 0957966a18b4 2001-02-03 04:05:15.000 +07:00 - 2001-02-03 04:05:15.000 +07:00 create bookmark merge pointing to commit b05964d109522cd06e48f1a2661e1a0f58be0984
Restored to operation cc1a7e3419ad 2001-02-03 04:05:15.000 +07:00 - 2001-02-03 04:05:15.000 +07:00 create bookmark merge pointing to commit b05964d109522cd06e48f1a2661e1a0f58be0984
Working copy now at: vruxwmqv b05964d1 merge | merge
Parent commit : royxmykx cea87a87 b | b
Parent commit : zsuskuln 2c5b7858 a | a

View file

@ -90,9 +90,9 @@ fn test_gc_operation_log() {
// Now this doesn't work.
let stderr = test_env.jj_cmd_failure(&repo_path, &["debug", "operation", &op_to_remove]);
insta::assert_snapshot!(stderr, @r###"
Error: No operation ID matching "54c5f04ab3dbb32ac86f805c819cb1ef78a3c9758ee560680a465e843fa0b05f42706d0641805905ef4bab550ca805effd1ba73d1980f6cdcc42126f008e51f4"
"###);
insta::assert_snapshot!(stderr, @r#"
Error: No operation ID matching "8382f401329617b0c91a63354b86ca48fc28dee8d7a916fdad5310030f9a1260e969c43ed2b13d1d48eaf38f6f45541ecf593bcb6105495d514d21b3b6a98846"
"#);
}
#[test]

View file

@ -224,7 +224,7 @@ fn test_workspaces_add_at_operation() {
"###);
let stdout = test_env.jj_cmd_success(&secondary_path, &["op", "log", "-Tdescription"]);
insta::assert_snapshot!(stdout, @r###"
insta::assert_snapshot!(stdout, @r#"
@ snapshot working copy
reconcile divergent operations
@ -236,9 +236,8 @@ fn test_workspaces_add_at_operation() {
commit 1c867a0762e30de4591890ea208849f793742c1b
snapshot working copy
add workspace 'default'
initialize repo
"###);
"#);
}
/// Test adding a workspace, but at a specific revision using '-r'
@ -500,18 +499,18 @@ fn test_workspaces_conflicting_edits() {
000000000000
"###);
let stderr = test_env.jj_cmd_failure(&secondary_path, &["st"]);
insta::assert_snapshot!(stderr, @r###"
Error: The working copy is stale (not updated since operation 0da24da631e3).
insta::assert_snapshot!(stderr, @r##"
Error: The working copy is stale (not updated since operation c81af45155a2).
Hint: Run `jj workspace update-stale` to update it.
See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy for more information.
"###);
"##);
// Same error on second run, and from another command
let stderr = test_env.jj_cmd_failure(&secondary_path, &["log"]);
insta::assert_snapshot!(stderr, @r###"
Error: The working copy is stale (not updated since operation 0da24da631e3).
insta::assert_snapshot!(stderr, @r##"
Error: The working copy is stale (not updated since operation c81af45155a2).
Hint: Run `jj workspace update-stale` to update it.
See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy for more information.
"###);
"##);
let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["workspace", "update-stale"]);
// It was detected that the working copy is now stale.
// Since there was an uncommitted change in the working copy, it should
@ -587,11 +586,11 @@ fn test_workspaces_updated_by_other() {
000000000000
"###);
let stderr = test_env.jj_cmd_failure(&secondary_path, &["st"]);
insta::assert_snapshot!(stderr, @r###"
Error: The working copy is stale (not updated since operation 0da24da631e3).
insta::assert_snapshot!(stderr, @r##"
Error: The working copy is stale (not updated since operation c81af45155a2).
Hint: Run `jj workspace update-stale` to update it.
See https://martinvonz.github.io/jj/latest/working-copy/#stale-working-copy for more information.
"###);
"##);
let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["workspace", "update-stale"]);
// It was detected that the working copy is now stale, but clean. So no
// divergent commit should be created.
@ -658,18 +657,17 @@ fn test_workspaces_current_op_discarded_by_other() {
r#"id.short(10) ++ " " ++ description"#,
],
);
insta::assert_snapshot!(stdout, @r###"
@ 7337338f0b abandon commit 20dd439c4bd12c6ad56c187ac490bd0141804618f638dc5c4dc92ff9aecba20f152b23160db9dcf61beb31a5cb14091d9def5a36d11c9599cc4d2e5689236af1
f4bd4d046b create initial working-copy commit in workspace secondary
0f99641958 add workspace 'secondary'
5641361f60 new empty commit
3a6c319c59 snapshot working copy
42c6005842 new empty commit
6a45045541 snapshot working copy
a9e6630bf0 add workspace 'default'
cecfee9647 initialize repo
insta::assert_snapshot!(stdout, @r#"
@ 757bc1140b abandon commit 20dd439c4bd12c6ad56c187ac490bd0141804618f638dc5c4dc92ff9aecba20f152b23160db9dcf61beb31a5cb14091d9def5a36d11c9599cc4d2e5689236af1
8d4abed655 create initial working-copy commit in workspace secondary
3de27432e5 add workspace 'secondary'
bcf69de808 new empty commit
a36b99a15c snapshot working copy
ddf023d319 new empty commit
829c93f6a3 snapshot working copy
2557266dd2 add workspace 'default'
0000000000
"###);
"#);
// Abandon ops, including the one the secondary workspace is currently on.
test_env.jj_cmd_ok(&main_path, &["operation", "abandon", "..@-"]);
@ -691,10 +689,10 @@ fn test_workspaces_current_op_discarded_by_other() {
"###);
let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["workspace", "update-stale"]);
insta::assert_snapshot!(stderr, @r###"
Failed to read working copy's current operation; attempting recovery. Error message from read attempt: Object f4bd4d046b3cdf61b0fda7738a0b1414c0aedc6c8229d39a35ee26facc358cad8b588b04d7eba1302a82409c529f69dbb1ff9ea28789d935b74f123f377aa30b of type operation not found
insta::assert_snapshot!(stderr, @r#"
Failed to read working copy's current operation; attempting recovery. Error message from read attempt: Object 8d4abed655badb70b1bab62aa87136619dbc3c8015a8ce8dfb7abfeca4e2f36c713d8f84e070a0613907a6cee7e1cc05323fe1205a319b93fe978f11a060c33c of type operation not found
Created and checked out recovery commit 62f70695e3b0
"###);
"#);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(get_log_output(&test_env, &main_path), @r###"
@ -761,11 +759,10 @@ fn test_workspaces_update_stale_noop() {
"###);
let stdout = test_env.jj_cmd_success(&main_path, &["op", "log", "-Tdescription"]);
insta::assert_snapshot!(stdout, @r###"
insta::assert_snapshot!(stdout, @r#"
@ add workspace 'default'
initialize repo
"###);
"#);
}
/// Test "update-stale" in a dirty, but not stale working copy.
@ -895,11 +892,11 @@ fn test_workspaces_forget_multi_transaction() {
// the op log should have multiple workspaces forgotten in a single tx
let stdout = test_env.jj_cmd_success(&main_path, &["op", "log", "--limit", "1"]);
insta::assert_snapshot!(stdout, @r###"
@ b7ab9f1c16cc test-username@host.example.com 2001-02-03 04:05:12.000 +07:00 - 2001-02-03 04:05:12.000 +07:00
insta::assert_snapshot!(stdout, @r#"
@ 60b2b5a71a84 test-username@host.example.com 2001-02-03 04:05:12.000 +07:00 - 2001-02-03 04:05:12.000 +07:00
forget workspaces second, third
args: jj workspace forget second third
"###);
"#);
// now, undo, and that should restore both workspaces
test_env.jj_cmd_ok(&main_path, &["op", "undo"]);
@ -1051,31 +1048,27 @@ fn test_debug_snapshot() {
std::fs::write(repo_path.join("file"), "contents").unwrap();
test_env.jj_cmd_ok(&repo_path, &["debug", "snapshot"]);
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
insta::assert_snapshot!(stdout, @r###"
@ e1e762d39b39 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
insta::assert_snapshot!(stdout, @r#"
@ c55ebc67e3db test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
snapshot working copy
args: jj debug snapshot
b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
eac759b9ab75 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
add workspace 'default'
9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
initialize repo
000000000000 root()
"###);
"#);
test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "initial"]);
let stdout = test_env.jj_cmd_success(&repo_path, &["op", "log"]);
insta::assert_snapshot!(stdout, @r###"
@ 9ac6e7144e8a test-username@host.example.com 2001-02-03 04:05:10.000 +07:00 - 2001-02-03 04:05:10.000 +07:00
insta::assert_snapshot!(stdout, @r#"
@ c9a40b951848 test-username@host.example.com 2001-02-03 04:05:10.000 +07:00 - 2001-02-03 04:05:10.000 +07:00
describe commit 4e8f9d2be039994f589b4e57ac5e9488703e604d
args: jj describe -m initial
e1e762d39b39 test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
c55ebc67e3db test-username@host.example.com 2001-02-03 04:05:08.000 +07:00 - 2001-02-03 04:05:08.000 +07:00
snapshot working copy
args: jj debug snapshot
b51416386f26 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
eac759b9ab75 test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
add workspace 'default'
9a7d829846af test-username@host.example.com 2001-02-03 04:05:07.000 +07:00 - 2001-02-03 04:05:07.000 +07:00
initialize repo
000000000000 root()
"###);
"#);
}
#[test]

View file

@ -264,7 +264,7 @@ pub struct BookmarkTarget<'a> {
/// Represents the way the repo looks at a given time, just like how a Tree
/// object represents how the file system looks at a given time.
#[derive(ContentHash, PartialEq, Eq, Clone, Debug, Default)]
#[derive(ContentHash, PartialEq, Eq, Clone, Debug)]
pub struct View {
/// All head commits
pub head_ids: HashSet<CommitId>,
@ -282,6 +282,37 @@ pub struct View {
pub wc_commit_ids: HashMap<WorkspaceId, CommitId>,
}
impl View {
/// Creates new truly empty view.
///
/// The caller should add at least one commit ID to `head_ids`. The other
/// fields may be empty.
pub fn empty() -> Self {
View {
head_ids: HashSet::new(),
local_bookmarks: BTreeMap::new(),
tags: BTreeMap::new(),
remote_views: BTreeMap::new(),
git_refs: BTreeMap::new(),
git_head: RefTarget::absent(),
wc_commit_ids: HashMap::new(),
}
}
/// Creates new (mostly empty) view containing the given commit as the head.
pub fn make_root(root_commit_id: CommitId) -> Self {
View {
head_ids: HashSet::from([root_commit_id]),
local_bookmarks: BTreeMap::new(),
tags: BTreeMap::new(),
remote_views: BTreeMap::new(),
git_refs: BTreeMap::new(),
git_head: RefTarget::absent(),
wc_commit_ids: HashMap::new(),
}
}
}
/// Represents the state of the remote repo.
#[derive(ContentHash, Clone, Debug, Default, Eq, PartialEq)]
pub struct RemoteView {
@ -368,7 +399,7 @@ pub struct Operation {
}
impl Operation {
pub fn make_root(empty_view_id: ViewId) -> Operation {
pub fn make_root(root_view_id: ViewId) -> Operation {
let timestamp = Timestamp {
timestamp: MillisSinceEpoch(0),
tz_offset: 0,
@ -383,7 +414,7 @@ impl Operation {
tags: HashMap::new(),
};
Operation {
view_id: empty_view_id,
view_id: root_view_id,
parents: vec![],
metadata,
}

View file

@ -233,24 +233,20 @@ impl ReadonlyRepo {
let root_operation = loader.root_operation();
let root_view = root_operation.view().expect("failed to read root view");
assert!(!root_view.heads().is_empty());
let index = loader
.index_store
.get_index_at_op(&root_operation, &loader.store)
// If the root op index couldn't be read, the index backend wouldn't
// be initialized properly.
.map_err(|err| BackendInitError(err.into()))?;
let repo = Arc::new(ReadonlyRepo {
Ok(Arc::new(ReadonlyRepo {
loader,
operation: root_operation,
index,
change_id_index: OnceCell::new(),
view: root_view,
});
let mut tx = repo.start_transaction(user_settings);
tx.repo_mut()
.add_head(&repo.store().root_commit())
.expect("failed to add root commit as head");
Ok(tx.commit("initialize repo"))
}))
}
pub fn loader(&self) -> &RepoLoader {

View file

@ -82,8 +82,9 @@ impl From<DecodeError> for OpStoreError {
#[derive(Debug)]
pub struct SimpleOpStore {
path: PathBuf,
empty_view_id: ViewId,
root_data: RootOperationData,
root_operation_id: OperationId,
root_view_id: ViewId,
}
impl SimpleOpStore {
@ -99,11 +100,12 @@ impl SimpleOpStore {
}
/// Load an existing OpStore
pub fn load(store_path: &Path, _root_data: RootOperationData) -> Self {
pub fn load(store_path: &Path, root_data: RootOperationData) -> Self {
SimpleOpStore {
path: store_path.to_path_buf(),
empty_view_id: ViewId::from_bytes(&[0; VIEW_ID_LENGTH]),
root_data,
root_operation_id: OperationId::from_bytes(&[0; OPERATION_ID_LENGTH]),
root_view_id: ViewId::from_bytes(&[0; VIEW_ID_LENGTH]),
}
}
@ -130,8 +132,8 @@ impl OpStore for SimpleOpStore {
}
fn read_view(&self, id: &ViewId) -> OpStoreResult<View> {
if *id == self.empty_view_id {
return Ok(View::default());
if *id == self.root_view_id {
return Ok(View::make_root(self.root_data.root_commit_id.clone()));
}
let path = self.view_path(id);
@ -164,7 +166,7 @@ impl OpStore for SimpleOpStore {
fn read_operation(&self, id: &OperationId) -> OpStoreResult<Operation> {
if *id == self.root_operation_id {
return Ok(Operation::make_root(self.empty_view_id.clone()));
return Ok(Operation::make_root(self.root_view_id.clone()));
}
let path = self.operation_path(id);
@ -460,7 +462,7 @@ fn view_to_proto(view: &View) -> crate::protos::op_store::View {
}
fn view_from_proto(proto: crate::protos::op_store::View) -> View {
let mut view = View::default();
let mut view = View::empty();
// For compatibility with old repos before we had support for multiple working
// copies
#[allow(deprecated)]

View file

@ -69,9 +69,9 @@ fn test_commit_parallel(backend: TestRepoBackend) {
// the root commit
assert_eq!(repo.view().heads().len(), num_threads + 1);
// One additional operation for the root commit, one for initializing the repo,
// one for checking out the initial commit.
assert_eq!(count_non_merge_operations(&repo), num_threads + 3);
// One additional operation for the root operation, one for checking out the
// initial commit.
assert_eq!(count_non_merge_operations(&repo), num_threads + 2);
}
#[test_case(TestRepoBackend::Local ; "local backend")]
@ -99,7 +99,7 @@ fn test_commit_parallel_instances(backend: TestRepoBackend) {
let repo = load_repo_at_head(&settings, test_workspace.repo_path());
assert_eq!(repo.view().heads().len(), num_threads + 1);
// One additional operation for the root commit, one for initializing the repo,
// one for checking out the initial commit.
assert_eq!(count_non_merge_operations(&repo), num_threads + 3);
// One additional operation for the root operation, one for checking out the
// initial commit.
assert_eq!(count_non_merge_operations(&repo), num_threads + 2);
}

View file

@ -422,23 +422,22 @@ fn test_resolve_op_id() {
let mut operations = Vec::new();
// The actual value of `i` doesn't matter, we just need to make sure we end
// up with hashes with ambiguous prefixes.
for i in (1..7).chain([16]) {
for i in (1..5).chain([39, 62]) {
let tx = repo.start_transaction(&settings);
let repo = tx.commit(format!("transaction {i}"));
operations.push(repo.operation().clone());
}
// "2" and "0" are ambiguous
insta::assert_debug_snapshot!(operations.iter().map(|op| op.id().hex()).collect_vec(), @r###"
// "b" and "0" are ambiguous
insta::assert_debug_snapshot!(operations.iter().map(|op| op.id().hex()).collect_vec(), @r#"
[
"5aebb24d08d6f5282d9e06bded4b51febbb4ff4bc822cdd4db9043961339955d6af912e783c3864245867d0cf6d609cb004c5ff0cef5e914c15a415ba92e38a2",
"ad1cda629b220f2651d972475fba75e47c30cd57862c51a727e57b7b6e2fbaa937d0bcb881cf6fcff30ba1a088a4ad588cf880765b9d9680b551cdc446f3489e",
"2feaf9eb61232582d35f1cb0203b69425f7a7d07140a5f8ff0d0bf98dd9f433b941e4c9e0882f65a007266affee275e235ae1614b159ceadbf9fe6879077a5da",
"0b183be5767c3ff9945c8a9e3ac7639d249ff9873985a551f4c2070782aea8b5018ebff906036d1658038708ab9de0d867be385b1181aa7a81669e2ef6852355",
"d1c3031dff7b1db4db1bfb592a9aa0ea6faae9300033ef20cb6da488e4b90524c22af8e2541cdb99ca0ee2be3299c213c0f8d48390cd5f11462c4f80c5790f68",
"2369ba98e2596715606978a72608970287aaa064ec890f87c29b7e7df64fdf02b7f24b8b03ee845e132f3e19e3929de359b6cfe1328b42946c45ac5ff80705ca",
"00271842a189d274a2c97ac28f937584a47b84463d5b408c6f998089131e0e1329a287667b2ac5d63f8c576e95323bcf992c99caa4ef4612a1c3798fe8a3f74f",
"bb1ea76bb194556214b1259568d5f3381fb4209f10b86d6c3c7d162a9b8ee1a5d98da57cf21ceadeecd2416c20508348ed4c1a24226c708f035b138fc7a97d5b",
"5c35c6506eedd9c74ffab46940129cb3b66e5e1968b4eea5bb38701d6d3462b4a34d78efcaa81d41fabf6937d79c4431e2adc4361095c9fb795004da420d8a26",
"b43387cf7a5808ebb6cdacd5c95de9d4b315c6edc465a49ff290b731da1c3d57315af49686e5ffd4c2fc4478af40b4a70cba7334bbca8e3d4e69176de807a916",
"fcd828a3033f9a9f44c8f06cd0d7f79570d53895c9d7d794ea51a7ee4b7871c8fe245ec18d2ece76ec7b51a998b04da811c232668c7c2c53f72b5baf0ad20797",
"091574d16d89ab848ac08c9a8e35276484c5e332ea97f1fad7b794763aa280ce5b663d835b555b5b763cbdbb6d8dba5a35ad1f2780ebdca5e598f07f82dcd3c7",
"06e9f38473578a4b1a8672ab474eb2741269fffb2f765a610de47fddafc60a88c002f7cdb9d82a9d1dfdbdd3b4045cd62e34215e7a781ed149332980e90227f1",
]
"###);
"#);
let repo_loader = repo.loader();
let resolve = |op_str: &str| op_walk::resolve_op_for_load(repo_loader, op_str);
@ -457,7 +456,7 @@ fn test_resolve_op_id() {
);
// Ambiguous id
assert_matches!(
resolve("2"),
resolve("b"),
Err(OpsetEvaluationError::OpsetResolution(
OpsetResolutionError::AmbiguousIdPrefix(_)
))
@ -479,8 +478,8 @@ fn test_resolve_op_id() {
// Virtual root id
let root_operation = loader.root_operation();
assert_eq!(resolve(&root_operation.id().hex()).unwrap(), root_operation);
assert_eq!(resolve("000").unwrap(), root_operation);
assert_eq!(resolve("002").unwrap(), operations[6]);
assert_eq!(resolve("00").unwrap(), root_operation);
assert_eq!(resolve("09").unwrap(), operations[4]);
assert_matches!(
resolve("0"),
Err(OpsetEvaluationError::OpsetResolution(
@ -607,7 +606,7 @@ fn test_gc() {
// |/
// B
// A
// 0 (initial)
// 0 (root)
let empty_tx = |repo: &Arc<ReadonlyRepo>| repo.start_transaction(&settings);
let random_tx = |repo: &Arc<ReadonlyRepo>| {
let mut tx = repo.start_transaction(&settings);
@ -624,8 +623,8 @@ fn test_gc() {
// Sanity check for the original state
let mut expected_op_entries = list_dir(&op_dir);
let mut expected_view_entries = list_dir(&view_dir);
assert_eq!(expected_op_entries.len(), 7);
assert_eq!(expected_view_entries.len(), 6);
assert_eq!(expected_op_entries.len(), 6);
assert_eq!(expected_view_entries.len(), 5);
// No heads, but all kept by file modification time
op_store.gc(&[], SystemTime::UNIX_EPOCH).unwrap();
@ -663,6 +662,6 @@ fn test_gc() {
assert_eq!(list_dir(&view_dir), expected_view_entries);
// Sanity check for the last state
assert_eq!(expected_op_entries.len(), 2);
assert_eq!(expected_view_entries.len(), 2);
assert_eq!(expected_op_entries.len(), 1);
assert_eq!(expected_view_entries.len(), 1);
}

View file

@ -957,12 +957,10 @@ fn test_evaluate_expression_root_and_checkout() {
vec![root_commit.id().clone()]
);
// but not in the root operation. It might be okay to pretend that the root
// commit exists in the root operation, but queries like "root()" shouldn't
// panic in any case.
assert_matches!(
resolve_symbol(root_repo.as_ref(), "root()"),
Err(RevsetResolutionError::NoSuchRevision { .. })
// Can find the root commit in the root view
assert_eq!(
resolve_commit_ids(root_repo.as_ref(), "root()"),
vec![root_commit.id().clone()]
);
// Can find the current working-copy commit