// Copyright 2022 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use std::path::Path; use crate::common::TestEnvironment; #[test]fn test_bookmark_multiple_names() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo", "bar"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Created 2 bookmarks pointing to qpvuntsm 230dd059 bar foo | (empty) (no description set) Hint: Use -r to specify the target revision. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar foo 230dd059e1b0 ◆ 000000000000 "###); test_env.jj_cmd_ok(&repo_path, &["new"]); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo", "bar"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Moved 2 bookmarks to zsuskuln 8bb159bc bar foo | (empty) (no description set) Hint: Use -r to specify the target revision. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar foo 8bb159bc30a9 ○ 230dd059e1b0 ◆ 000000000000 "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo", "bar", "foo"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Deleted 2 bookmarks. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ 8bb159bc30a9 ○ 230dd059e1b0 ◆ 000000000000 "###); // Hint should be omitted if -r is specified let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "-r@-", "foo", "bar"]); insta::assert_snapshot!(stderr, @r###" Created 2 bookmarks pointing to qpvuntsm 230dd059 bar foo | (empty) (no description set) "###); // Create and move with explicit -r let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-r@", "bar", "baz"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to zsuskuln 8bb159bc bar baz | (empty) (no description set) Moved 1 bookmarks to zsuskuln 8bb159bc bar baz | (empty) (no description set) Hint: Consider using `jj bookmark move` if your intention was to move existing bookmarks. "###); // Noop changes should not be included in the stats let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-r@", "foo", "bar", "baz"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to zsuskuln 8bb159bc bar baz foo | (empty) (no description set) "###);} #[test]fn test_bookmark_at_root() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "fred", "-r=root()"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to zzzzzzzz 00000000 fred | (empty) (no description set) "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Nothing changed. Warning: Failed to export some bookmarks: fred: Ref cannot point to the root commit in Git "###);} #[test]fn test_bookmark_empty_name() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "create", ""]); insta::assert_snapshot!(stderr, @r###" error: a value is required for '<NAMES>...' but none was supplied For more information, try '--help'. "###); let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "set", ""]); insta::assert_snapshot!(stderr, @r###" error: a value is required for '<NAMES>...' but none was supplied For more information, try '--help'. "###);} #[test]fn test_bookmark_move() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); // Set up remote let git_repo_path = test_env.env_root().join("git-repo"); git2::Repository::init_bare(git_repo_path).unwrap(); test_env.jj_cmd_ok( &repo_path, &["git", "remote", "add", "origin", "../git-repo"], ); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: No such bookmark: foo "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to qpvuntsm 230dd059 foo | (empty) (no description set) Hint: Consider using `jj bookmark move` if your intention was to move existing bookmarks. "###); test_env.jj_cmd_ok(&repo_path, &["new"]); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Bookmark already exists: foo Hint: Use `jj bookmark set` to update it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 167f90e7 foo | (empty) (no description set) "###); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "set", "-r@-", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "set", "-r@-", "--allow-backwards", "foo"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to qpvuntsm 230dd059 foo | (empty) (no description set) "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 167f90e7 foo | (empty) (no description set) "###); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "--to=@-", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "move", "--to=@-", "--allow-backwards", "foo"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to qpvuntsm 230dd059 foo | (empty) (no description set) "###); // Delete bookmark locally, but is still tracking remote test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "-mcommit"]); test_env.jj_cmd_ok(&repo_path, &["git", "push", "-r@-"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo"]); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo (deleted) @origin: qpvuntsm 1eb845f3 (empty) commit "###); // Deleted tracking bookmark name should still be allocated let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Tracked remote bookmarks exist for deleted bookmark: foo Hint: Use `jj bookmark set` to recreate the local bookmark. Run `jj bookmark untrack 'glob:foo@*'` to disassociate them. "###); // Restoring local target shouldn't invalidate tracking state let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 66d48752 foo* | (empty) (no description set) "###); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo: mzvwutvl 66d48752 (empty) (no description set) @origin (behind by 1 commits): qpvuntsm 1eb845f3 (empty) commit "###); // Untracked remote bookmark shouldn't block creation of local bookmark test_env.jj_cmd_ok(&repo_path, &["bookmark", "untrack", "foo@origin"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to mzvwutvl 66d48752 foo | (empty) (no description set) "###); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo: mzvwutvl 66d48752 (empty) (no description set) foo@origin: qpvuntsm 1eb845f3 (empty) commit "###);} #[test]fn test_bookmark_move_matching() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a1", "a2"]); test_env.jj_cmd_ok(&repo_path, &["new", "-mhead1"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b1"]); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c1"]); test_env.jj_cmd_ok(&repo_path, &["new", "-mhead2"]); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); // The default could be considered "--from=all() glob:*", but is disabled let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "move"]); insta::assert_snapshot!(stderr, @r###" error: the following required arguments were not provided: <--from <REVISIONS>|NAMES> Usage: jj bookmark move <--from <REVISIONS>|NAMES> For more information, try '--help'. "###); // No bookmarks pointing to the source revisions let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--from=none()"]); insta::assert_snapshot!(stderr, @r###" No bookmarks to update. "###); // No matching bookmarks within the source revisions let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "--from=::@", "glob:a?"]); insta::assert_snapshot!(stderr, @r###" Error: No matching bookmarks for patterns: a? "###); // Noop move let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--to=a1", "a2"]); insta::assert_snapshot!(stderr, @r###" No bookmarks to update. "###); // Move from multiple revisions let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--from=::@"]); insta::assert_snapshot!(stderr, @r###" Moved 2 bookmarks to vruxwmqv a2781dd9 b1 c1 | (empty) head2 Hint: Specify bookmark by name to update just one of the bookmarks. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ b1 c1 a2781dd9ee37 ○ f4f38657a3dd ○ f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); test_env.jj_cmd_ok(&repo_path, &["undo"]); // Try to move multiple bookmarks, but one of them isn't fast-forward let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "glob:?1"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: a1 Hint: Use --allow-backwards to allow it. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); // Select by revision and name let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "move", "--from=::a1+", "--to=a1+", "glob:?1"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to kkmpptxz 6b5e840e a1 | (empty) head1 "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ a1 6b5e840ea72b │ ○ a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###);} #[test]fn test_bookmark_move_conflicting() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let get_log = || { let template = r#"separate(" ", description.first_line(), bookmarks)"#; let (stdout, _stderr) = test_env.jj_cmd_ok(&repo_path, &["log", "-T", template]); stdout }; test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mA0"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mB0"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mC0"]); test_env.jj_cmd_ok(&repo_path, &["new", "description(A0)", "-mA1"]); // Set up conflicting bookmark. test_env.jj_cmd_ok( &repo_path, &["bookmark", "create", "-rdescription(A0)", "foo"], ); test_env.jj_cmd_ok( &repo_path, &[ "bookmark", "create", "--at-op=@-", "-rdescription(B0)", "foo", ], ); insta::assert_snapshot!(get_log(), @r###" @ A1 ○ A0 foo?? │ ○ C0 ├─╯ │ ○ B0 foo?? ├─╯ ◆ "###); // Can't move the bookmark to C0 since it's sibling. let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "set", "-rdescription(C0)", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); // Can move the bookmark to A1 since it's descendant of A0. It's not // descendant of B0, though. let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-rdescription(A1)", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 9328d344 foo | (empty) A1 "###); insta::assert_snapshot!(get_log(), @r###" @ A1 foo ○ A0 │ ○ C0 ├─╯ │ ○ B0 ├─╯ ◆ "###);} #[test]fn test_bookmark_rename() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); // Set up remote let git_repo_path = test_env.env_root().join("git-repo"); git2::Repository::init_bare(git_repo_path).unwrap(); test_env.jj_cmd_ok( &repo_path, &["git", "remote", "add", "origin", "../git-repo"], ); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "rename", "bnoexist", "blocal"]); insta::assert_snapshot!(stderr, @r###" Error: No such bookmark: bnoexist "###); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-0"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "blocal"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "blocal", "blocal1"]); insta::assert_snapshot!(stderr, @""); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-1"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bexist"]); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "rename", "blocal1", "bexist"]); insta::assert_snapshot!(stderr, @r###" Error: Bookmark already exists: bexist "###); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-2"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bremote"]); test_env.jj_cmd_ok(&repo_path, &["git", "push", "-b=bremote"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "bremote", "bremote2"]); insta::assert_snapshot!(stderr, @r###" Warning: Tracked remote bookmarks for bookmark bremote were not renamed. Hint: To rename the bookmark on the remote, you can `jj git push --bookmark bremote` first (to delete it on the remote), and then `jj git push --bookmark bremote2`. `jj git push --all` would also be sufficient. "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "bremote2", "bremote"]); insta::assert_snapshot!(stderr, @r###" Warning: Tracked remote bookmarks for bookmark bremote exist. Hint: Run `jj bookmark untrack 'glob:bremote@*'` to disassociate them. "###);} #[test]fn test_bookmark_rename_colocated() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo", "--colocate"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-0"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "blocal"]); // Make sure that git tracking bookmarks don't cause a warning let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "blocal", "blocal1"]); insta::assert_snapshot!(stderr, @"");} #[test]fn test_bookmark_forget_glob() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-1"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar-2"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-3"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-4"]); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar-2 foo-1 foo-3 foo-4 230dd059e1b0 ◆ 000000000000 "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "forget", "glob:foo-[1-3]"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Forgot 2 bookmarks. "###); test_env.jj_cmd_ok(&repo_path, &["undo"]); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "forget", "glob:foo-[1-3]"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Forgot 2 bookmarks.Lines 1–500 of 1908. Load more
// Copyright 2022 The Jujutsu Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::path::Path; use crate::common::TestEnvironment; #[test] fn test_bookmark_multiple_names() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo", "bar"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Created 2 bookmarks pointing to qpvuntsm 230dd059 bar foo | (empty) (no description set) Hint: Use -r to specify the target revision. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar foo 230dd059e1b0 ◆ 000000000000 "###); test_env.jj_cmd_ok(&repo_path, &["new"]); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo", "bar"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Moved 2 bookmarks to zsuskuln 8bb159bc bar foo | (empty) (no description set) Hint: Use -r to specify the target revision. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar foo 8bb159bc30a9 ○ 230dd059e1b0 ◆ 000000000000 "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo", "bar", "foo"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Deleted 2 bookmarks. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ 8bb159bc30a9 ○ 230dd059e1b0 ◆ 000000000000 "###); // Hint should be omitted if -r is specified let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "-r@-", "foo", "bar"]); insta::assert_snapshot!(stderr, @r###" Created 2 bookmarks pointing to qpvuntsm 230dd059 bar foo | (empty) (no description set) "###); // Create and move with explicit -r let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-r@", "bar", "baz"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to zsuskuln 8bb159bc bar baz | (empty) (no description set) Moved 1 bookmarks to zsuskuln 8bb159bc bar baz | (empty) (no description set) Hint: Consider using `jj bookmark move` if your intention was to move existing bookmarks. "###); // Noop changes should not be included in the stats let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-r@", "foo", "bar", "baz"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to zsuskuln 8bb159bc bar baz foo | (empty) (no description set) "###); } #[test] fn test_bookmark_at_root() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "fred", "-r=root()"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to zzzzzzzz 00000000 fred | (empty) (no description set) "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Nothing changed. Warning: Failed to export some bookmarks: fred: Ref cannot point to the root commit in Git "###); } #[test] fn test_bookmark_empty_name() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "create", ""]); insta::assert_snapshot!(stderr, @r###" error: a value is required for '<NAMES>...' but none was supplied For more information, try '--help'. "###); let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "set", ""]); insta::assert_snapshot!(stderr, @r###" error: a value is required for '<NAMES>...' but none was supplied For more information, try '--help'. "###); } #[test] fn test_bookmark_move() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); // Set up remote let git_repo_path = test_env.env_root().join("git-repo"); git2::Repository::init_bare(git_repo_path).unwrap(); test_env.jj_cmd_ok( &repo_path, &["git", "remote", "add", "origin", "../git-repo"], ); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: No such bookmark: foo "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to qpvuntsm 230dd059 foo | (empty) (no description set) Hint: Consider using `jj bookmark move` if your intention was to move existing bookmarks. "###); test_env.jj_cmd_ok(&repo_path, &["new"]); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Bookmark already exists: foo Hint: Use `jj bookmark set` to update it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 167f90e7 foo | (empty) (no description set) "###); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "set", "-r@-", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "set", "-r@-", "--allow-backwards", "foo"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to qpvuntsm 230dd059 foo | (empty) (no description set) "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 167f90e7 foo | (empty) (no description set) "###); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "--to=@-", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "move", "--to=@-", "--allow-backwards", "foo"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to qpvuntsm 230dd059 foo | (empty) (no description set) "###); // Delete bookmark locally, but is still tracking remote test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "-mcommit"]); test_env.jj_cmd_ok(&repo_path, &["git", "push", "-r@-"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo"]); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo (deleted) @origin: qpvuntsm 1eb845f3 (empty) commit "###); // Deleted tracking bookmark name should still be allocated let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Tracked remote bookmarks exist for deleted bookmark: foo Hint: Use `jj bookmark set` to recreate the local bookmark. Run `jj bookmark untrack 'glob:foo@*'` to disassociate them. "###); // Restoring local target shouldn't invalidate tracking state let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 66d48752 foo* | (empty) (no description set) "###); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo: mzvwutvl 66d48752 (empty) (no description set) @origin (behind by 1 commits): qpvuntsm 1eb845f3 (empty) commit "###); // Untracked remote bookmark shouldn't block creation of local bookmark test_env.jj_cmd_ok(&repo_path, &["bookmark", "untrack", "foo@origin"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "delete", "foo"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo"]); insta::assert_snapshot!(stderr, @r###" Created 1 bookmarks pointing to mzvwutvl 66d48752 foo | (empty) (no description set) "###); insta::assert_snapshot!(get_bookmark_output(&test_env, &repo_path), @r###" foo: mzvwutvl 66d48752 (empty) (no description set) foo@origin: qpvuntsm 1eb845f3 (empty) commit "###); } #[test] fn test_bookmark_move_matching() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a1", "a2"]); test_env.jj_cmd_ok(&repo_path, &["new", "-mhead1"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "b1"]); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "c1"]); test_env.jj_cmd_ok(&repo_path, &["new", "-mhead2"]); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); // The default could be considered "--from=all() glob:*", but is disabled let stderr = test_env.jj_cmd_cli_error(&repo_path, &["bookmark", "move"]); insta::assert_snapshot!(stderr, @r###" error: the following required arguments were not provided: <--from <REVISIONS>|NAMES> Usage: jj bookmark move <--from <REVISIONS>|NAMES> For more information, try '--help'. "###); // No bookmarks pointing to the source revisions let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--from=none()"]); insta::assert_snapshot!(stderr, @r###" No bookmarks to update. "###); // No matching bookmarks within the source revisions let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "--from=::@", "glob:a?"]); insta::assert_snapshot!(stderr, @r###" Error: No matching bookmarks for patterns: a? "###); // Noop move let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--to=a1", "a2"]); insta::assert_snapshot!(stderr, @r###" No bookmarks to update. "###); // Move from multiple revisions let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "move", "--from=::@"]); insta::assert_snapshot!(stderr, @r###" Moved 2 bookmarks to vruxwmqv a2781dd9 b1 c1 | (empty) head2 Hint: Specify bookmark by name to update just one of the bookmarks. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ b1 c1 a2781dd9ee37 ○ f4f38657a3dd ○ f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); test_env.jj_cmd_ok(&repo_path, &["undo"]); // Try to move multiple bookmarks, but one of them isn't fast-forward let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "move", "glob:?1"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: a1 Hint: Use --allow-backwards to allow it. "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ 6b5e840ea72b │ ○ a1 a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); // Select by revision and name let (_stdout, stderr) = test_env.jj_cmd_ok( &repo_path, &["bookmark", "move", "--from=::a1+", "--to=a1+", "glob:?1"], ); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to kkmpptxz 6b5e840e a1 | (empty) head1 "###); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ a2781dd9ee37 ○ c1 f4f38657a3dd ○ b1 f652c32197cf │ ○ a1 6b5e840ea72b │ ○ a2 230dd059e1b0 ├─╯ ◆ 000000000000 "###); } #[test] fn test_bookmark_move_conflicting() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); let get_log = || { let template = r#"separate(" ", description.first_line(), bookmarks)"#; let (stdout, _stderr) = test_env.jj_cmd_ok(&repo_path, &["log", "-T", template]); stdout }; test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mA0"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mB0"]); test_env.jj_cmd_ok(&repo_path, &["new", "root()", "-mC0"]); test_env.jj_cmd_ok(&repo_path, &["new", "description(A0)", "-mA1"]); // Set up conflicting bookmark. test_env.jj_cmd_ok( &repo_path, &["bookmark", "create", "-rdescription(A0)", "foo"], ); test_env.jj_cmd_ok( &repo_path, &[ "bookmark", "create", "--at-op=@-", "-rdescription(B0)", "foo", ], ); insta::assert_snapshot!(get_log(), @r###" @ A1 ○ A0 foo?? │ ○ C0 ├─╯ │ ○ B0 foo?? ├─╯ ◆ "###); // Can't move the bookmark to C0 since it's sibling. let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "set", "-rdescription(C0)", "foo"]); insta::assert_snapshot!(stderr, @r###" Error: Refusing to move bookmark backwards or sideways: foo Hint: Use --allow-backwards to allow it. "###); // Can move the bookmark to A1 since it's descendant of A0. It's not // descendant of B0, though. let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "set", "-rdescription(A1)", "foo"]); insta::assert_snapshot!(stderr, @r###" Moved 1 bookmarks to mzvwutvl 9328d344 foo | (empty) A1 "###); insta::assert_snapshot!(get_log(), @r###" @ A1 foo ○ A0 │ ○ C0 ├─╯ │ ○ B0 ├─╯ ◆ "###); } #[test] fn test_bookmark_rename() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); // Set up remote let git_repo_path = test_env.env_root().join("git-repo"); git2::Repository::init_bare(git_repo_path).unwrap(); test_env.jj_cmd_ok( &repo_path, &["git", "remote", "add", "origin", "../git-repo"], ); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "rename", "bnoexist", "blocal"]); insta::assert_snapshot!(stderr, @r###" Error: No such bookmark: bnoexist "###); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-0"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "blocal"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "blocal", "blocal1"]); insta::assert_snapshot!(stderr, @""); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-1"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bexist"]); let stderr = test_env.jj_cmd_failure(&repo_path, &["bookmark", "rename", "blocal1", "bexist"]); insta::assert_snapshot!(stderr, @r###" Error: Bookmark already exists: bexist "###); test_env.jj_cmd_ok(&repo_path, &["new"]); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-2"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bremote"]); test_env.jj_cmd_ok(&repo_path, &["git", "push", "-b=bremote"]); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "bremote", "bremote2"]); insta::assert_snapshot!(stderr, @r###" Warning: Tracked remote bookmarks for bookmark bremote were not renamed. Hint: To rename the bookmark on the remote, you can `jj git push --bookmark bremote` first (to delete it on the remote), and then `jj git push --bookmark bremote2`. `jj git push --all` would also be sufficient. "###); let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "bremote2", "bremote"]); insta::assert_snapshot!(stderr, @r###" Warning: Tracked remote bookmarks for bookmark bremote exist. Hint: Run `jj bookmark untrack 'glob:bremote@*'` to disassociate them. "###); } #[test] fn test_bookmark_rename_colocated() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo", "--colocate"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit-0"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "blocal"]); // Make sure that git tracking bookmarks don't cause a warning let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "rename", "blocal", "blocal1"]); insta::assert_snapshot!(stderr, @""); } #[test] fn test_bookmark_forget_glob() { let test_env = TestEnvironment::default(); test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]); let repo_path = test_env.env_root().join("repo"); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-1"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "bar-2"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-3"]); test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "foo-4"]); insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" @ bar-2 foo-1 foo-3 foo-4 230dd059e1b0 ◆ 000000000000 "###); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "forget", "glob:foo-[1-3]"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Forgot 2 bookmarks. "###); test_env.jj_cmd_ok(&repo_path, &["undo"]); let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["bookmark", "forget", "glob:foo-[1-3]"]); insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(stderr, @r###" Forgot 2 bookmarks.