mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-17 13:14:26 +00:00
We haven't had any reports of problems from people who opted in. Since it's early in the release cycle now, let's now test it on everyone who builds from head, so we get almost a month of testing from those people before it's enabled by default in a released version. This impacts lots of test cases because the change-id header is added to the Git commit. Most are uninteresting. `test_git_fetch` now sees some divergent changes where it used to see only divergent bookmarks, which makes sense.
2404 lines
80 KiB
Rust
2404 lines
80 KiB
Rust
// 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 testutils::git;
|
|
|
|
use crate::common::CommandOutput;
|
|
use crate::common::TestEnvironment;
|
|
use crate::common::TestWorkDir;
|
|
|
|
fn create_commit_with_refs(
|
|
repo: &gix::Repository,
|
|
message: &str,
|
|
content: &[u8],
|
|
ref_names: &[&str],
|
|
) {
|
|
let git::CommitResult {
|
|
tree_id: _,
|
|
commit_id,
|
|
} = git::add_commit(repo, "refs/heads/dummy", "file", content, message, &[]);
|
|
repo.find_reference("dummy").unwrap().delete().unwrap();
|
|
|
|
for name in ref_names {
|
|
repo.reference(
|
|
*name,
|
|
commit_id,
|
|
gix::refs::transaction::PreviousValue::Any,
|
|
"log message",
|
|
)
|
|
.unwrap();
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_multiple_names() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", "foo", "bar"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 2 bookmarks pointing to qpvuntsm e8849ae1 bar foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar foo e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "set", "foo", "bar", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 2 bookmarks to zsuskuln 0e555a27 bar foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar foo 0e555a27ac99
|
|
○ e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "delete", "foo", "bar", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Deleted 2 bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ 0e555a27ac99
|
|
○ e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Hint should be omitted if -r is specified
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@-", "foo", "bar"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 2 bookmarks pointing to qpvuntsm e8849ae1 bar foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Create and move with explicit -r
|
|
let output = work_dir.run_jj(["bookmark", "set", "-r@", "bar", "baz"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to zsuskuln 0e555a27 bar baz | (empty) (no description set)
|
|
Moved 1 bookmarks to zsuskuln 0e555a27 bar baz | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Noop changes should not be included in the stats
|
|
let output = work_dir.run_jj(["bookmark", "set", "-r@", "foo", "bar", "baz"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to zsuskuln 0e555a27 bar baz foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_at_root() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "create", "fred", "-r=root()"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to zzzzzzzz 00000000 fred | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
let output = work_dir.run_jj(["git", "export"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Nothing changed.
|
|
Warning: Failed to export some bookmarks:
|
|
fred@git: Ref cannot point to the root commit in Git
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_bad_name() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", ""]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value '' for '<NAMES>...': Failed to parse bookmark name: Syntax error
|
|
|
|
For more information, try '--help'.
|
|
Caused by: --> 1:1
|
|
|
|
|
1 |
|
|
| ^---
|
|
|
|
|
= expected <identifier>, <string_literal>, or <raw_string_literal>
|
|
Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for how to quote symbols.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "''"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value '''' for '<NAMES>...': Failed to parse bookmark name: Expected non-empty string
|
|
|
|
For more information, try '--help'.
|
|
Caused by: --> 1:1
|
|
|
|
|
1 | ''
|
|
| ^^
|
|
|
|
|
= Expected non-empty string
|
|
Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for how to quote symbols.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "rename", "x", ""]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value '' for '<NEW>': Failed to parse bookmark name: Syntax error
|
|
|
|
For more information, try '--help'.
|
|
Caused by: --> 1:1
|
|
|
|
|
1 |
|
|
| ^---
|
|
|
|
|
= expected <identifier>, <string_literal>, or <raw_string_literal>
|
|
Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for how to quote symbols.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// common errors
|
|
let output = work_dir.run_jj(["bookmark", "set", "@-", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value '@-' for '<NAMES>...': Failed to parse bookmark name: Syntax error
|
|
|
|
For more information, try '--help'.
|
|
Caused by: --> 1:1
|
|
|
|
|
1 | @-
|
|
| ^---
|
|
|
|
|
= expected <identifier>, <string_literal>, or <raw_string_literal>
|
|
Hint: See https://jj-vcs.github.io/jj/latest/revsets/ or use `jj help -k revsets` for how to quote symbols.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
let stderr = work_dir.run_jj(["bookmark", "set", "-r@-", "foo@bar"]);
|
|
insta::assert_snapshot!(stderr, @r"
|
|
------- stderr -------
|
|
error: invalid value 'foo@bar' for '<NAMES>...': Failed to parse bookmark name: Syntax error
|
|
|
|
For more information, try '--help'.
|
|
Caused by: --> 1:4
|
|
|
|
|
1 | foo@bar
|
|
| ^---
|
|
|
|
|
= expected <EOI>
|
|
Hint: Looks like remote bookmark. Run `jj bookmark track foo@bar` to track it.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// quoted name works
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", "'foo@bar'"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to qpvuntsm e8849ae1 foo@bar | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_move() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Set up remote
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
git::init_bare(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
let output = work_dir.run_jj(["bookmark", "move", "foo", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No such bookmark: foo
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "foo", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Bookmark already exists: foo
|
|
Hint: Use `jj bookmark set` to update it.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "foo", "--revision", "@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to mzvwutvl 8afc18ff foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "-r@-", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Refusing to move bookmark backwards or sideways: foo
|
|
Hint: Use --allow-backwards to allow it.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "-r@-", "--allow-backwards", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "move", "foo", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to mzvwutvl 8afc18ff foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "move", "--to=@-", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Refusing to move bookmark backwards or sideways: foo
|
|
Hint: Use --allow-backwards to allow it.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "move", "--to=@-", "--allow-backwards", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Delete bookmark locally, but is still tracking remote
|
|
work_dir.run_jj(["describe", "@-", "-mcommit"]).success();
|
|
work_dir
|
|
.run_jj(["git", "push", "--allow-new", "-r@-"])
|
|
.success();
|
|
work_dir.run_jj(["bookmark", "delete", "foo"]).success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
foo (deleted)
|
|
@origin: qpvuntsm 5f3ceb1e (empty) commit
|
|
[EOF]
|
|
");
|
|
|
|
// Deleted tracking bookmark name should still be allocated
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
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.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Restoring local target shouldn't invalidate tracking state
|
|
let output = work_dir.run_jj(["bookmark", "set", "foo", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to mzvwutvl 91b59745 foo* | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
foo: mzvwutvl 91b59745 (empty) (no description set)
|
|
@origin (behind by 1 commits): qpvuntsm 5f3ceb1e (empty) commit
|
|
[EOF]
|
|
");
|
|
|
|
// Untracked remote bookmark shouldn't block creation of local bookmark
|
|
work_dir
|
|
.run_jj(["bookmark", "untrack", "foo@origin"])
|
|
.success();
|
|
work_dir.run_jj(["bookmark", "delete", "foo"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "create", "-r@", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to mzvwutvl 91b59745 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
foo: mzvwutvl 91b59745 (empty) (no description set)
|
|
foo@origin: qpvuntsm 5f3ceb1e (empty) commit
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_move_matching() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "a1", "a2"])
|
|
.success();
|
|
work_dir.run_jj(["new", "-mhead1"]).success();
|
|
work_dir.run_jj(["new", "root()"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "b1"])
|
|
.success();
|
|
work_dir.run_jj(["new"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "c1"])
|
|
.success();
|
|
work_dir.run_jj(["new", "-mhead2"]).success();
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ 0dd9a4b12283
|
|
○ c1 2cbf65662e56
|
|
○ b1 c2934cfbfb19
|
|
│ ○ 9328ecc52471
|
|
│ ○ a1 a2 e8849ae12c70
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// The default could be considered "--from=all() glob:*", but is disabled
|
|
let output = work_dir.run_jj(["bookmark", "move", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: the following required arguments were not provided:
|
|
<--from <REVSETS>|NAMES>
|
|
|
|
Usage: jj bookmark move --to <REVSET> <--from <REVSETS>|NAMES>
|
|
|
|
For more information, try '--help'.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// No bookmarks pointing to the source revisions
|
|
let output = work_dir.run_jj(["bookmark", "move", "--from=none()", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
No bookmarks to update.
|
|
[EOF]
|
|
");
|
|
|
|
// No matching bookmarks within the source revisions
|
|
let output = work_dir.run_jj(["bookmark", "move", "--from=::@", "glob:a?", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No matching bookmarks for patterns: a?
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Noop move
|
|
let output = work_dir.run_jj(["bookmark", "move", "--to=a1", "a2"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
No bookmarks to update.
|
|
[EOF]
|
|
");
|
|
|
|
// Move from multiple revisions
|
|
let output = work_dir.run_jj(["bookmark", "move", "--from=::@", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 2 bookmarks to vruxwmqv 0dd9a4b1 b1 c1 | (empty) head2
|
|
Hint: Specify bookmark by name to update just one of the bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ b1 c1 0dd9a4b12283
|
|
○ 2cbf65662e56
|
|
○ c2934cfbfb19
|
|
│ ○ 9328ecc52471
|
|
│ ○ a1 a2 e8849ae12c70
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
work_dir.run_jj(["undo"]).success();
|
|
|
|
// Try to move multiple bookmarks, but one of them isn't fast-forward
|
|
let output = work_dir.run_jj(["bookmark", "move", "glob:?1", "--to=@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Refusing to move bookmark backwards or sideways: a1
|
|
Hint: Use --allow-backwards to allow it.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ 0dd9a4b12283
|
|
○ c1 2cbf65662e56
|
|
○ b1 c2934cfbfb19
|
|
│ ○ 9328ecc52471
|
|
│ ○ a1 a2 e8849ae12c70
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Select by revision and name
|
|
let output = work_dir.run_jj(["bookmark", "move", "--from=::a1+", "--to=a1+", "glob:?1"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to kkmpptxz 9328ecc5 a1 | (empty) head1
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ 0dd9a4b12283
|
|
○ c1 2cbf65662e56
|
|
○ b1 c2934cfbfb19
|
|
│ ○ a1 9328ecc52471
|
|
│ ○ a2 e8849ae12c70
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_move_conflicting() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
let get_log = || {
|
|
let template = r#"separate(" ", description.first_line(), bookmarks)"#;
|
|
work_dir.run_jj(["log", "-T", template])
|
|
};
|
|
|
|
work_dir.run_jj(["new", "root()", "-mA0"]).success();
|
|
work_dir.run_jj(["new", "root()", "-mB0"]).success();
|
|
work_dir.run_jj(["new", "root()", "-mC0"]).success();
|
|
work_dir
|
|
.run_jj(["new", "description(A0)", "-mA1"])
|
|
.success();
|
|
|
|
// Set up conflicting bookmark.
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-rdescription(A0)", "foo"])
|
|
.success();
|
|
work_dir
|
|
.run_jj([
|
|
"bookmark",
|
|
"create",
|
|
"--at-op=@-",
|
|
"-rdescription(B0)",
|
|
"foo",
|
|
])
|
|
.success();
|
|
insta::assert_snapshot!(get_log(), @r"
|
|
@ A1
|
|
○ A0 foo??
|
|
│ ○ C0
|
|
├─╯
|
|
│ ○ B0 foo??
|
|
├─╯
|
|
◆
|
|
[EOF]
|
|
------- stderr -------
|
|
Concurrent modification detected, resolving automatically.
|
|
[EOF]
|
|
");
|
|
|
|
// Can't move the bookmark to C0 since it's sibling.
|
|
let output = work_dir.run_jj(["bookmark", "set", "-rdescription(C0)", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Refusing to move bookmark backwards or sideways: foo
|
|
Hint: Use --allow-backwards to allow it.
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Can move the bookmark to A1 since it's descendant of A0. It's not
|
|
// descendant of B0, though.
|
|
let output = work_dir.run_jj(["bookmark", "set", "-rdescription(A1)", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Moved 1 bookmarks to mzvwutvl 0f5f3e2c foo | (empty) A1
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log(), @r"
|
|
@ A1 foo
|
|
○ A0
|
|
│ ○ C0
|
|
├─╯
|
|
│ ○ B0
|
|
├─╯
|
|
◆
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_rename() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Set up remote
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
git::init_bare(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
let output = work_dir.run_jj(["bookmark", "rename", "bnoexist", "blocal"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No such bookmark: bnoexist
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
work_dir.run_jj(["describe", "-m=commit-0"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "blocal"])
|
|
.success();
|
|
let output = work_dir.run_jj(["bookmark", "rename", "blocal", "blocal1"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
work_dir.run_jj(["describe", "-m=commit-1"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "bexist"])
|
|
.success();
|
|
let output = work_dir.run_jj(["bookmark", "rename", "blocal1", "bexist"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Bookmark already exists: bexist
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
work_dir.run_jj(["describe", "-m=commit-2"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "bremote"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["git", "push", "--allow-new", "-b=bremote"])
|
|
.success();
|
|
let output = work_dir.run_jj(["bookmark", "rename", "bremote", "bremote2"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
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.
|
|
[EOF]
|
|
");
|
|
let output = work_dir.run_jj(["bookmark", "rename", "bremote2", "bremote"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Tracked remote bookmarks for bookmark bremote exist.
|
|
Hint: Run `jj bookmark untrack 'glob:bremote@*'` to disassociate them.
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_rename_colocated() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env
|
|
.run_jj_in(".", ["git", "init", "repo", "--colocate"])
|
|
.success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
work_dir.run_jj(["describe", "-m=commit-0"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "blocal"])
|
|
.success();
|
|
|
|
// Make sure that git tracking bookmarks don't cause a warning
|
|
let output = work_dir.run_jj(["bookmark", "rename", "blocal", "blocal1"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_forget_glob() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-1"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "bar-2"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-3"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-4"])
|
|
.success();
|
|
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 foo-1 foo-3 foo-4 e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
let output = work_dir.run_jj(["bookmark", "forget", "glob:foo-[1-3]"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Forgot 2 local bookmarks.
|
|
[EOF]
|
|
");
|
|
work_dir.run_jj(["undo"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "forget", "glob:foo-[1-3]"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Forgot 2 local bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 foo-4 e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Forgetting a bookmark via both explicit name and glob pattern, or with
|
|
// multiple glob patterns, shouldn't produce an error.
|
|
let output = work_dir.run_jj(["bookmark", "forget", "foo-4", "glob:foo-*", "glob:foo-*"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Forgot 1 local bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 e8849ae12c70
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Malformed glob
|
|
let output = work_dir.run_jj(["bookmark", "forget", "glob:foo-[1-3"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value 'glob:foo-[1-3' for '<NAMES>...': Pattern syntax error near position 4: invalid range pattern
|
|
|
|
For more information, try '--help'.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// We get an error if none of the globs match anything
|
|
let output = work_dir.run_jj(["bookmark", "forget", "glob:bar*", "glob:baz*", "glob:boom*"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No matching bookmarks for patterns: baz*, boom*
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_delete_glob() {
|
|
// Set up a git repo with a bookmark and a jj repo that has it as a remote.
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
let git_repo = git::init_bare(git_repo_path);
|
|
let blob_oid = git_repo.write_blob(b"content").unwrap();
|
|
let mut tree_editor = git_repo
|
|
.edit_tree(gix::ObjectId::empty_tree(gix::hash::Kind::default()))
|
|
.unwrap();
|
|
tree_editor
|
|
.upsert("file", gix::object::tree::EntryKind::Blob, blob_oid)
|
|
.unwrap();
|
|
let _tree_id = tree_editor.write().unwrap();
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
work_dir.run_jj(["describe", "-m=commit"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-1"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "bar-2"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-3"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo-4"])
|
|
.success();
|
|
// Push to create remote-tracking bookmarks
|
|
work_dir.run_jj(["git", "push", "--all"]).success();
|
|
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 foo-1 foo-3 foo-4 8e056f6b8c37
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
let output = work_dir.run_jj(["bookmark", "delete", "glob:foo-[1-3]"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Deleted 2 bookmarks.
|
|
[EOF]
|
|
");
|
|
work_dir.run_jj(["undo"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "delete", "glob:foo-[1-3]"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Deleted 2 bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 foo-1@origin foo-3@origin foo-4 8e056f6b8c37
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// We get an error if none of the globs match live bookmarks. Unlike `jj
|
|
// bookmark forget`, it's not allowed to delete already deleted bookmarks.
|
|
let output = work_dir.run_jj(["bookmark", "delete", "glob:foo-[1-3]"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No matching bookmarks for patterns: foo-[1-3]
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Deleting a bookmark via both explicit name and glob pattern, or with
|
|
// multiple glob patterns, shouldn't produce an error.
|
|
let output = work_dir.run_jj(["bookmark", "delete", "foo-4", "glob:foo-*", "glob:foo-*"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Deleted 1 bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ bar-2 foo-1@origin foo-3@origin foo-4@origin 8e056f6b8c37
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// The deleted bookmarks are still there
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
bar-2: qpvuntsm 8e056f6b (empty) commit
|
|
@origin: qpvuntsm 8e056f6b (empty) commit
|
|
foo-1 (deleted)
|
|
@origin: qpvuntsm 8e056f6b (empty) commit
|
|
foo-3 (deleted)
|
|
@origin: qpvuntsm 8e056f6b (empty) commit
|
|
foo-4 (deleted)
|
|
@origin: qpvuntsm 8e056f6b (empty) commit
|
|
[EOF]
|
|
");
|
|
|
|
// Malformed glob
|
|
let output = work_dir.run_jj(["bookmark", "delete", "glob:foo-[1-3"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value 'glob:foo-[1-3' for '<NAMES>...': Pattern syntax error near position 4: invalid range pattern
|
|
|
|
For more information, try '--help'.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// Unknown pattern kind
|
|
let output = work_dir.run_jj(["bookmark", "forget", "whatever:bookmark"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
error: invalid value 'whatever:bookmark' for '<NAMES>...': Invalid string pattern kind `whatever:`
|
|
|
|
For more information, try '--help'.
|
|
Hint: Try prefixing with one of `exact:`, `glob:`, `regex:`, `substring:`, or one of these with `-i` suffix added (e.g. `glob-i:`) for case-insensitive matching
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_delete_export() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo"])
|
|
.success();
|
|
work_dir.run_jj(["git", "export"]).success();
|
|
|
|
work_dir.run_jj(["bookmark", "delete", "foo"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "list", "--all-remotes"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
foo (deleted)
|
|
@git: rlvkpnrz 43444d88 (empty) (no description set)
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted will be deleted from the underlying Git repo on the next `jj git export`.
|
|
[EOF]
|
|
");
|
|
|
|
work_dir.run_jj(["git", "export"]).success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_forget_export() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "foo"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
foo: rlvkpnrz 43444d88 (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Exporting the bookmark to git creates a local-git tracking bookmark
|
|
let output = work_dir.run_jj(["git", "export"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
let output = work_dir.run_jj(["bookmark", "forget", "--include-remotes", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Forgot 1 local bookmarks.
|
|
Forgot 1 remote bookmarks.
|
|
[EOF]
|
|
");
|
|
// Forgetting a bookmark with --include-remotes deletes local and
|
|
// remote-tracking bookmarks including the corresponding git-tracking bookmark.
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
let output = work_dir.run_jj(["log", "-r=foo", "--no-graph"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: Revision `foo` doesn't exist
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// `jj git export` will delete the bookmark from git. In a colocated repo,
|
|
// this will happen automatically immediately after a `jj bookmark forget`.
|
|
// This is demonstrated in `test_git_colocated_bookmark_forget` in
|
|
// test_git_colocated.rs
|
|
let output = work_dir.run_jj(["git", "export"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_forget_fetched_bookmark() {
|
|
// Much of this test is borrowed from `test_git_fetch_remote_only_bookmark` in
|
|
// test_git_fetch.rs
|
|
|
|
// Set up a git repo with a bookmark and a jj repo that has it as a remote.
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
let git_repo = git::init_bare(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
// Create a commit and a bookmark in the git repo
|
|
let git::CommitResult {
|
|
tree_id,
|
|
commit_id: first_git_repo_commit,
|
|
} = git::add_commit(
|
|
&git_repo,
|
|
"refs/heads/feature1",
|
|
"file",
|
|
b"content",
|
|
"message",
|
|
&[],
|
|
);
|
|
|
|
// Fetch normally
|
|
work_dir
|
|
.run_jj(["git", "fetch", "--remote=origin"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qomsplrm ebeb70d8 message
|
|
@origin: qomsplrm ebeb70d8 message
|
|
[EOF]
|
|
");
|
|
|
|
// TEST 1: with export-import
|
|
// Forget the bookmark with --include-remotes
|
|
work_dir
|
|
.run_jj(["bookmark", "forget", "--include-remotes", "feature1"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
|
|
// At this point `jj git export && jj git import` does *not* recreate the
|
|
// bookmark. This behavior is important in colocated repos, as otherwise a
|
|
// forgotten bookmark would be immediately resurrected.
|
|
//
|
|
// Technically, this is because `jj bookmark forget` preserved
|
|
// the ref in jj view's `git_refs` tracking the local git repo's remote-tracking
|
|
// bookmark.
|
|
// TODO: Show that jj git push is also a no-op
|
|
let output = work_dir.run_jj(["git", "export"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
let output = work_dir.run_jj(["git", "import"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Nothing changed.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
|
|
// We can fetch feature1 again.
|
|
let output = work_dir.run_jj(["git", "fetch", "--remote=origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [new] tracked
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qomsplrm ebeb70d8 message
|
|
@origin: qomsplrm ebeb70d8 message
|
|
[EOF]
|
|
");
|
|
|
|
// TEST 2: No export/import (otherwise the same as test 1)
|
|
work_dir
|
|
.run_jj(["bookmark", "forget", "--include-remotes", "feature1"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
// Fetch works even without the export-import
|
|
let output = work_dir.run_jj(["git", "fetch", "--remote=origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [new] tracked
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qomsplrm ebeb70d8 message
|
|
@origin: qomsplrm ebeb70d8 message
|
|
[EOF]
|
|
");
|
|
|
|
// TEST 3: fetch bookmark that was moved & forgotten with --include-remotes
|
|
|
|
// Move the bookmark in the git repo.
|
|
git::write_commit(
|
|
&git_repo,
|
|
"refs/heads/feature1",
|
|
tree_id,
|
|
"another message",
|
|
&[first_git_repo_commit],
|
|
);
|
|
let output = work_dir.run_jj(["bookmark", "forget", "--include-remotes", "feature1"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Forgot 1 local bookmarks.
|
|
Forgot 1 remote bookmarks.
|
|
[EOF]
|
|
");
|
|
|
|
// Fetching a moved bookmark does not create a conflict
|
|
let output = work_dir.run_jj(["git", "fetch", "--remote=origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [new] tracked
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: tyvxnvqr 9175cb32 (empty) another message
|
|
@origin: tyvxnvqr 9175cb32 (empty) another message
|
|
[EOF]
|
|
");
|
|
|
|
// TEST 4: If `--include-remotes` isn't used, remote bookmarks are untracked
|
|
work_dir
|
|
.run_jj(["bookmark", "forget", "feature1"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1@origin: tyvxnvqr 9175cb32 (empty) another message
|
|
[EOF]
|
|
");
|
|
// There should be no output here since the remote bookmark wasn't forgotten
|
|
let output = work_dir.run_jj(["git", "fetch", "--remote=origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Nothing changed.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1@origin: tyvxnvqr 9175cb32 (empty) another message
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_forget_deleted_or_nonexistent_bookmark() {
|
|
// Much of this test is borrowed from `test_git_fetch_remote_only_bookmark` in
|
|
// test_git_fetch.rs
|
|
|
|
// ======== Beginning of test setup ========
|
|
// Set up a git repo with a bookmark and a jj repo that has it as a remote.
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
let git_repo = git::init_bare(git_repo_path);
|
|
// Create a commit and a bookmark in the git repo
|
|
git::add_commit(
|
|
&git_repo,
|
|
"refs/heads/feature1",
|
|
"file",
|
|
b"content",
|
|
"message",
|
|
&[],
|
|
);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
// Fetch and then delete the bookmark
|
|
work_dir
|
|
.run_jj(["git", "fetch", "--remote=origin"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "delete", "feature1"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1 (deleted)
|
|
@origin: qomsplrm ebeb70d8 message
|
|
[EOF]
|
|
");
|
|
|
|
// ============ End of test setup ============
|
|
|
|
// We can forget a deleted bookmark
|
|
work_dir
|
|
.run_jj(["bookmark", "forget", "--include-remotes", "feature1"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @"");
|
|
|
|
// Can't forget a non-existent bookmark
|
|
let output = work_dir.run_jj(["bookmark", "forget", "i_do_not_exist"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Error: No such bookmark: i_do_not_exist
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_track_untrack() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Set up remote
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
let git_repo = git::init(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
// Fetch new commit without auto tracking. No local bookmarks should be
|
|
// created.
|
|
create_commit_with_refs(
|
|
&git_repo,
|
|
"commit 1",
|
|
b"content 1",
|
|
&[
|
|
"refs/heads/main",
|
|
"refs/heads/feature1",
|
|
"refs/heads/feature2",
|
|
],
|
|
);
|
|
test_env.add_config("git.auto-local-bookmark = false");
|
|
let output = work_dir.run_jj(["git", "fetch"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [new] untracked
|
|
bookmark: feature2@origin [new] untracked
|
|
bookmark: main@origin [new] untracked
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1@origin: qxxqrkql bd843888 commit 1
|
|
feature2@origin: qxxqrkql bd843888 commit 1
|
|
main@origin: qxxqrkql bd843888 commit 1
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ e8849ae12c70
|
|
│ ◆ feature1@origin feature2@origin main@origin bd843888ee66
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Track new bookmark. Local bookmark should be created.
|
|
work_dir
|
|
.run_jj(["bookmark", "track", "feature1@origin", "main@origin"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qxxqrkql bd843888 commit 1
|
|
@origin: qxxqrkql bd843888 commit 1
|
|
feature2@origin: qxxqrkql bd843888 commit 1
|
|
main: qxxqrkql bd843888 commit 1
|
|
@origin: qxxqrkql bd843888 commit 1
|
|
[EOF]
|
|
");
|
|
|
|
// Track existing bookmark. Local bookmark should result in conflict.
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "feature2"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "track", "feature2@origin"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qxxqrkql bd843888 commit 1
|
|
@origin: qxxqrkql bd843888 commit 1
|
|
feature2 (conflicted):
|
|
+ qpvuntsm e8849ae1 (empty) (no description set)
|
|
+ qxxqrkql bd843888 commit 1
|
|
@origin (behind by 1 commits): qxxqrkql bd843888 commit 1
|
|
main: qxxqrkql bd843888 commit 1
|
|
@origin: qxxqrkql bd843888 commit 1
|
|
[EOF]
|
|
");
|
|
|
|
// Untrack existing and locally-deleted bookmarks. Bookmark targets should be
|
|
// unchanged
|
|
work_dir
|
|
.run_jj(["bookmark", "delete", "feature2"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "untrack", "feature1@origin", "feature2@origin"])
|
|
.success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qxxqrkql bd843888 commit 1
|
|
feature1@origin: qxxqrkql bd843888 commit 1
|
|
feature2@origin: qxxqrkql bd843888 commit 1
|
|
main: qxxqrkql bd843888 commit 1
|
|
@origin: qxxqrkql bd843888 commit 1
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ e8849ae12c70
|
|
│ ◆ feature1 feature1@origin feature2@origin main bd843888ee66
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Fetch new commit. Only tracking bookmark "main" should be merged.
|
|
create_commit_with_refs(
|
|
&git_repo,
|
|
"commit 2",
|
|
b"content 2",
|
|
&[
|
|
"refs/heads/main",
|
|
"refs/heads/feature1",
|
|
"refs/heads/feature2",
|
|
],
|
|
);
|
|
let output = work_dir.run_jj(["git", "fetch"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [updated] untracked
|
|
bookmark: feature2@origin [updated] untracked
|
|
bookmark: main@origin [updated] tracked
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qxxqrkql bd843888 commit 1
|
|
feature1@origin: psynomvr 48ec79a4 commit 2
|
|
feature2@origin: psynomvr 48ec79a4 commit 2
|
|
main: psynomvr 48ec79a4 commit 2
|
|
@origin: psynomvr 48ec79a4 commit 2
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ e8849ae12c70
|
|
│ ◆ feature1@origin feature2@origin main 48ec79a430e9
|
|
├─╯
|
|
│ ○ feature1 bd843888ee66
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// Fetch new commit with auto tracking. Tracking bookmark "main" and new
|
|
// bookmark "feature3" should be merged.
|
|
create_commit_with_refs(
|
|
&git_repo,
|
|
"commit 3",
|
|
b"content 3",
|
|
&[
|
|
"refs/heads/main",
|
|
"refs/heads/feature1",
|
|
"refs/heads/feature2",
|
|
"refs/heads/feature3",
|
|
],
|
|
);
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
let output = work_dir.run_jj(["git", "fetch"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [updated] untracked
|
|
bookmark: feature2@origin [updated] untracked
|
|
bookmark: feature3@origin [new] tracked
|
|
bookmark: main@origin [updated] tracked
|
|
Abandoned 1 commits that are no longer reachable.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: qxxqrkql bd843888 commit 1
|
|
feature1@origin: yumopmsr d8cd3e02 commit 3
|
|
feature2@origin: yumopmsr d8cd3e02 commit 3
|
|
feature3: yumopmsr d8cd3e02 commit 3
|
|
@origin: yumopmsr d8cd3e02 commit 3
|
|
main: yumopmsr d8cd3e02 commit 3
|
|
@origin: yumopmsr d8cd3e02 commit 3
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_log_output(&work_dir), @r"
|
|
@ e8849ae12c70
|
|
│ ◆ feature1@origin feature2@origin feature3 main d8cd3e020382
|
|
├─╯
|
|
│ ○ feature1 bd843888ee66
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_track_conflict() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
git::init_bare(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "main"])
|
|
.success();
|
|
work_dir.run_jj(["describe", "-m", "a"]).success();
|
|
work_dir
|
|
.run_jj(["git", "push", "--allow-new", "-b", "main"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "untrack", "main@origin"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["describe", "-m", "b", "-r", "main", "--ignore-immutable"])
|
|
.success();
|
|
let output = work_dir.run_jj(["bookmark", "track", "main@origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Started tracking 1 remote bookmarks.
|
|
main (conflicted):
|
|
+ qpvuntsm?? 56b9f16b (empty) b
|
|
+ qpvuntsm?? 7d5ca8e4 (empty) a
|
|
@origin (behind by 1 commits): qpvuntsm?? 7d5ca8e4 (empty) a
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_track_untrack_patterns() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Set up remote
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
let git_repo = git::init(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
// Create remote commit
|
|
create_commit_with_refs(
|
|
&git_repo,
|
|
"commit",
|
|
b"content",
|
|
&["refs/heads/feature1", "refs/heads/feature2"],
|
|
);
|
|
|
|
// Fetch new commit without auto tracking
|
|
test_env.add_config("git.auto-local-bookmark = false");
|
|
let output = work_dir.run_jj(["git", "fetch"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
bookmark: feature1@origin [new] untracked
|
|
bookmark: feature2@origin [new] untracked
|
|
[EOF]
|
|
");
|
|
|
|
// Track local bookmark
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "main"])
|
|
.success();
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "track", "main"]), @r"
|
|
------- stderr -------
|
|
error: invalid value 'main' for '<BOOKMARK@REMOTE>...': remote bookmark must be specified in bookmark@remote form
|
|
|
|
For more information, try '--help'.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
|
|
// Track/untrack unknown bookmark
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "track", "main@origin"]), @r"
|
|
------- stderr -------
|
|
Error: No such remote bookmark: main@origin
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "untrack", "main@origin"]), @r"
|
|
------- stderr -------
|
|
Error: No such remote bookmark: main@origin
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "track", "glob:maine@*"]), @r"
|
|
------- stderr -------
|
|
Error: No matching remote bookmarks for patterns: maine@*
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
insta::assert_snapshot!(
|
|
work_dir.run_jj(["bookmark", "untrack", "main@origin", "glob:main@o*"]), @r"
|
|
------- stderr -------
|
|
Error: No matching remote bookmarks for patterns: main@origin, main@o*
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Track already tracked bookmark
|
|
work_dir
|
|
.run_jj(["bookmark", "track", "feature1@origin"])
|
|
.success();
|
|
let output = work_dir.run_jj(["bookmark", "track", "feature1@origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Remote bookmark already tracked: feature1@origin
|
|
Nothing changed.
|
|
[EOF]
|
|
");
|
|
|
|
// Untrack non-tracking bookmark
|
|
let output = work_dir.run_jj(["bookmark", "untrack", "feature2@origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Remote bookmark not tracked yet: feature2@origin
|
|
Nothing changed.
|
|
[EOF]
|
|
");
|
|
|
|
// Untrack Git-tracking bookmark
|
|
work_dir.run_jj(["git", "export"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "untrack", "main@git"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Git-tracking bookmark cannot be untracked: main@git
|
|
Nothing changed.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: yrnqsqlx 41e7a49d commit
|
|
@git: yrnqsqlx 41e7a49d commit
|
|
@origin: yrnqsqlx 41e7a49d commit
|
|
feature2@origin: yrnqsqlx 41e7a49d commit
|
|
main: qpvuntsm e8849ae1 (empty) (no description set)
|
|
@git: qpvuntsm e8849ae1 (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Untrack by pattern
|
|
let output = work_dir.run_jj(["bookmark", "untrack", "glob:*@*"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Git-tracking bookmark cannot be untracked: feature1@git
|
|
Warning: Remote bookmark not tracked yet: feature2@origin
|
|
Warning: Git-tracking bookmark cannot be untracked: main@git
|
|
Stopped tracking 1 remote bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: yrnqsqlx 41e7a49d commit
|
|
@git: yrnqsqlx 41e7a49d commit
|
|
feature1@origin: yrnqsqlx 41e7a49d commit
|
|
feature2@origin: yrnqsqlx 41e7a49d commit
|
|
main: qpvuntsm e8849ae1 (empty) (no description set)
|
|
@git: qpvuntsm e8849ae1 (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
// Track by pattern
|
|
let output = work_dir.run_jj(["bookmark", "track", "glob:feature?@origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Started tracking 2 remote bookmarks.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
feature1: yrnqsqlx 41e7a49d commit
|
|
@git: yrnqsqlx 41e7a49d commit
|
|
@origin: yrnqsqlx 41e7a49d commit
|
|
feature2: yrnqsqlx 41e7a49d commit
|
|
@origin: yrnqsqlx 41e7a49d commit
|
|
main: qpvuntsm e8849ae1 (empty) (no description set)
|
|
@git: qpvuntsm e8849ae1 (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
|
|
// Initialize remote refs
|
|
test_env.run_jj_in(".", ["git", "init", "remote"]).success();
|
|
let remote_dir = test_env.work_dir("remote");
|
|
for bookmark in [
|
|
"remote-sync",
|
|
"remote-unsync",
|
|
"remote-untrack",
|
|
"remote-delete",
|
|
] {
|
|
remote_dir
|
|
.run_jj(["new", "root()", "-m", bookmark])
|
|
.success();
|
|
remote_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
remote_dir.run_jj(["new"]).success();
|
|
remote_dir.run_jj(["git", "export"]).success();
|
|
|
|
// Initialize local refs
|
|
let mut remote_git_path = remote_dir.root().to_owned();
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
|
test_env
|
|
.run_jj_in(
|
|
".",
|
|
["git", "clone", remote_git_path.to_str().unwrap(), "local"],
|
|
)
|
|
.success();
|
|
let local_dir = test_env.work_dir("local");
|
|
local_dir
|
|
.run_jj(["new", "root()", "-m", "local-only"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "create", "-r@", "local-only"])
|
|
.success();
|
|
|
|
// Mutate refs in local repository
|
|
local_dir
|
|
.run_jj(["bookmark", "delete", "remote-delete"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "delete", "remote-untrack"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "untrack", "remote-untrack@origin"])
|
|
.success();
|
|
local_dir
|
|
.run_jj([
|
|
"bookmark",
|
|
"set",
|
|
"--allow-backwards",
|
|
"--to=@",
|
|
"remote-unsync",
|
|
])
|
|
.success();
|
|
|
|
// Synchronized tracking remotes and non-tracking remotes aren't listed by
|
|
// default
|
|
let output = local_dir.run_jj(["bookmark", "list"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
local-only: wqnwkozp 0353dd35 (empty) local-only
|
|
remote-delete (deleted)
|
|
@origin: vruxwmqv b32031cf (empty) remote-delete
|
|
remote-sync: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
remote-unsync: wqnwkozp 0353dd35 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--all-remotes"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
local-only: wqnwkozp 0353dd35 (empty) local-only
|
|
remote-delete (deleted)
|
|
@origin: vruxwmqv b32031cf (empty) remote-delete
|
|
remote-sync: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
@origin: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
remote-unsync: wqnwkozp 0353dd35 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
remote-untrack@origin: royxmykx 149bc756 (empty) remote-untrack
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let template = r#"
|
|
concat(
|
|
"[" ++ name ++ if(remote, "@" ++ remote) ++ "]\n",
|
|
separate(" ", "present:", present) ++ "\n",
|
|
separate(" ", "conflict:", conflict) ++ "\n",
|
|
separate(" ", "normal_target:", normal_target.description().first_line()) ++ "\n",
|
|
separate(" ", "removed_targets:", removed_targets.map(|c| c.description().first_line())) ++ "\n",
|
|
separate(" ", "added_targets:", added_targets.map(|c| c.description().first_line())) ++ "\n",
|
|
separate(" ", "tracked:", tracked) ++ "\n",
|
|
separate(" ", "tracking_present:", tracking_present) ++ "\n",
|
|
separate(" ", "tracking_ahead_count:", tracking_ahead_count.lower()) ++ "\n",
|
|
separate(" ", "tracking_behind_count:", tracking_behind_count.lower()) ++ "\n",
|
|
)
|
|
"#;
|
|
let output = local_dir.run_jj(["bookmark", "list", "--all-remotes", "-T", template]);
|
|
insta::assert_snapshot!(output, @r"
|
|
[local-only]
|
|
present: true
|
|
conflict: false
|
|
normal_target: local-only
|
|
removed_targets:
|
|
added_targets: local-only
|
|
tracked: false
|
|
tracking_present: false
|
|
tracking_ahead_count: <Error: Not a tracked remote ref>
|
|
tracking_behind_count: <Error: Not a tracked remote ref>
|
|
[remote-delete]
|
|
present: false
|
|
conflict: false
|
|
normal_target: <Error: No Commit available>
|
|
removed_targets:
|
|
added_targets:
|
|
tracked: false
|
|
tracking_present: false
|
|
tracking_ahead_count: <Error: Not a tracked remote ref>
|
|
tracking_behind_count: <Error: Not a tracked remote ref>
|
|
[remote-delete@origin]
|
|
present: true
|
|
conflict: false
|
|
normal_target: remote-delete
|
|
removed_targets:
|
|
added_targets: remote-delete
|
|
tracked: true
|
|
tracking_present: false
|
|
tracking_ahead_count: 2
|
|
tracking_behind_count: 0
|
|
[remote-sync]
|
|
present: true
|
|
conflict: false
|
|
normal_target: remote-sync
|
|
removed_targets:
|
|
added_targets: remote-sync
|
|
tracked: false
|
|
tracking_present: false
|
|
tracking_ahead_count: <Error: Not a tracked remote ref>
|
|
tracking_behind_count: <Error: Not a tracked remote ref>
|
|
[remote-sync@origin]
|
|
present: true
|
|
conflict: false
|
|
normal_target: remote-sync
|
|
removed_targets:
|
|
added_targets: remote-sync
|
|
tracked: true
|
|
tracking_present: true
|
|
tracking_ahead_count: 0
|
|
tracking_behind_count: 0
|
|
[remote-unsync]
|
|
present: true
|
|
conflict: false
|
|
normal_target: local-only
|
|
removed_targets:
|
|
added_targets: local-only
|
|
tracked: false
|
|
tracking_present: false
|
|
tracking_ahead_count: <Error: Not a tracked remote ref>
|
|
tracking_behind_count: <Error: Not a tracked remote ref>
|
|
[remote-unsync@origin]
|
|
present: true
|
|
conflict: false
|
|
normal_target: remote-unsync
|
|
removed_targets:
|
|
added_targets: remote-unsync
|
|
tracked: true
|
|
tracking_present: true
|
|
tracking_ahead_count: 1
|
|
tracking_behind_count: 1
|
|
[remote-untrack@origin]
|
|
present: true
|
|
conflict: false
|
|
normal_target: remote-untrack
|
|
removed_targets:
|
|
added_targets: remote-untrack
|
|
tracked: false
|
|
tracking_present: false
|
|
tracking_ahead_count: <Error: Not a tracked remote ref>
|
|
tracking_behind_count: <Error: Not a tracked remote ref>
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_filtered() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#);
|
|
|
|
// Initialize remote refs
|
|
test_env.run_jj_in(".", ["git", "init", "remote"]).success();
|
|
let remote_dir = test_env.work_dir("remote");
|
|
for bookmark in ["remote-keep", "remote-delete", "remote-rewrite"] {
|
|
remote_dir
|
|
.run_jj(["new", "root()", "-m", bookmark])
|
|
.success();
|
|
remote_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
remote_dir.run_jj(["new"]).success();
|
|
remote_dir.run_jj(["git", "export"]).success();
|
|
|
|
// Initialize local refs
|
|
let mut remote_git_path = remote_dir.root().to_owned();
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
|
test_env
|
|
.run_jj_in(
|
|
".",
|
|
["git", "clone", remote_git_path.to_str().unwrap(), "local"],
|
|
)
|
|
.success();
|
|
let local_dir = test_env.work_dir("local");
|
|
local_dir
|
|
.run_jj(["new", "root()", "-m", "local-keep"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "create", "-r@", "local-keep"])
|
|
.success();
|
|
|
|
// Mutate refs in local repository
|
|
local_dir
|
|
.run_jj(["bookmark", "delete", "remote-delete"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["describe", "-mrewritten", "remote-rewrite"])
|
|
.success();
|
|
|
|
let template = r#"separate(" ", commit_id.short(), bookmarks, if(hidden, "(hidden)"))"#;
|
|
insta::assert_snapshot!(
|
|
local_dir.run_jj(["log", "-r::(bookmarks() | remote_bookmarks())", "-T", template]), @r"
|
|
@ 4b2bc95cbda6 local-keep
|
|
│ ○ e6970e0e1f55 remote-rewrite*
|
|
├─╯
|
|
│ ○ 331d500d2fda remote-rewrite@origin (hidden)
|
|
├─╯
|
|
│ ○ 0e6b796871e6 remote-delete@origin
|
|
├─╯
|
|
│ ○ c2f2ee40f03a remote-keep
|
|
├─╯
|
|
◆ 000000000000
|
|
[EOF]
|
|
");
|
|
|
|
// All bookmarks are listed by default.
|
|
let output = local_dir.run_jj(["bookmark", "list"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-delete (deleted)
|
|
@origin: zsuskuln 0e6b7968 (empty) remote-delete
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let query =
|
|
|args: &[&str]| local_dir.run_jj_with(|cmd| cmd.args(["bookmark", "list"]).args(args));
|
|
|
|
// "all()" doesn't include deleted bookmarks since they have no local targets.
|
|
// So "all()" is identical to "bookmarks()".
|
|
insta::assert_snapshot!(query(&["-rall()"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
|
|
// Exclude remote-only bookmarks. "remote-rewrite@origin" is included since
|
|
// local "remote-rewrite" target matches.
|
|
insta::assert_snapshot!(query(&["-rbookmarks()"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
|
|
// Select bookmarks by name.
|
|
insta::assert_snapshot!(query(&["remote-rewrite"]), @r"
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(query(&["-rbookmarks(remote-rewrite)"]), @r"
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
|
|
// Select bookmarks by name, combined with --all-remotes
|
|
local_dir.run_jj(["git", "export"]).success();
|
|
insta::assert_snapshot!(query(&["--all-remotes", "remote-rewrite"]), @r"
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@git: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(query(&["--all-remotes", "-rbookmarks(remote-rewrite)"]), @r"
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@git: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
|
|
// Select bookmarks with --remote
|
|
insta::assert_snapshot!(query(&["--remote", "origin"]), @r"
|
|
remote-delete (deleted)
|
|
@origin: zsuskuln 0e6b7968 (empty) remote-delete
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
@origin: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(query(&["--remote", "glob:gi?"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
@git: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
@git: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@git: royxmykx e6970e0e (empty) rewritten
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(query(&["--remote", "origin", "--remote", "git"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
@git: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-delete (deleted)
|
|
@origin: zsuskuln 0e6b7968 (empty) remote-delete
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
@git: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
@origin: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@git: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
// Can select deleted bookmark by name pattern, but not by revset.
|
|
insta::assert_snapshot!(query(&["remote-delete"]), @r"
|
|
remote-delete (deleted)
|
|
@origin: zsuskuln 0e6b7968 (empty) remote-delete
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(query(&["-rbookmarks(remote-delete)"]), @"");
|
|
insta::assert_snapshot!(query(&["-rremote-delete"]), @r"
|
|
------- stderr -------
|
|
Error: Revision `remote-delete` doesn't exist
|
|
Hint: Did you mean `remote-delete@origin`, `remote-keep`, `remote-rewrite`, `remote-rewrite@origin`?
|
|
[EOF]
|
|
[exit status: 1]
|
|
");
|
|
|
|
// Name patterns are OR-ed.
|
|
insta::assert_snapshot!(query(&["glob:*-keep", "remote-delete"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-delete (deleted)
|
|
@origin: zsuskuln 0e6b7968 (empty) remote-delete
|
|
remote-keep: rlvkpnrz c2f2ee40 (empty) remote-keep
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
// Unmatched name pattern shouldn't be an error. A warning can be added later.
|
|
insta::assert_snapshot!(query(&["local-keep", "glob:push-*"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
[EOF]
|
|
");
|
|
|
|
// Name pattern and revset are OR-ed.
|
|
insta::assert_snapshot!(query(&["local-keep", "-rbookmarks(remote-rewrite)"]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@origin (ahead by 1 commits, behind by 1 commits): royxmykx hidden 331d500d (empty) remote-rewrite
|
|
[EOF]
|
|
");
|
|
|
|
// … but still filtered by --remote
|
|
insta::assert_snapshot!(query(&[
|
|
"local-keep",
|
|
"-rbookmarks(remote-rewrite)",
|
|
"--remote",
|
|
"git",
|
|
]), @r"
|
|
local-keep: kpqxywon 4b2bc95c (empty) local-keep
|
|
@git: kpqxywon 4b2bc95c (empty) local-keep
|
|
remote-rewrite: royxmykx e6970e0e (empty) rewritten
|
|
@git: royxmykx e6970e0e (empty) rewritten
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_much_remote_divergence() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
|
|
// Initialize remote refs
|
|
test_env.run_jj_in(".", ["git", "init", "remote"]).success();
|
|
let remote_dir = test_env.work_dir("remote");
|
|
remote_dir
|
|
.run_jj(["new", "root()", "-m", "remote-unsync"])
|
|
.success();
|
|
for _ in 0..15 {
|
|
remote_dir.run_jj(["new", "-m", "remote-unsync"]).success();
|
|
}
|
|
remote_dir
|
|
.run_jj(["bookmark", "create", "-r@", "remote-unsync"])
|
|
.success();
|
|
remote_dir.run_jj(["new"]).success();
|
|
remote_dir.run_jj(["git", "export"]).success();
|
|
|
|
// Initialize local refs
|
|
let mut remote_git_path = remote_dir.root().to_owned();
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
|
test_env
|
|
.run_jj_in(
|
|
".",
|
|
["git", "clone", remote_git_path.to_str().unwrap(), "local"],
|
|
)
|
|
.success();
|
|
let local_dir = test_env.work_dir("local");
|
|
local_dir
|
|
.run_jj(["new", "root()", "-m", "local-only"])
|
|
.success();
|
|
for _ in 0..15 {
|
|
local_dir.run_jj(["new", "-m", "local-only"]).success();
|
|
}
|
|
local_dir
|
|
.run_jj(["bookmark", "create", "-r@", "local-only"])
|
|
.success();
|
|
|
|
// Mutate refs in local repository
|
|
local_dir
|
|
.run_jj([
|
|
"bookmark",
|
|
"set",
|
|
"--allow-backwards",
|
|
"--to=@",
|
|
"remote-unsync",
|
|
])
|
|
.success();
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
local-only: zkyosouw a30800ad (empty) local-only
|
|
remote-unsync: zkyosouw a30800ad (empty) local-only
|
|
@origin (ahead by at least 10 commits, behind by at least 10 commits): uyznsvlq a52367f8 (empty) remote-unsync
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_tracked() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.add_config("git.auto-local-bookmark = true");
|
|
|
|
// Initialize remote refs
|
|
test_env.run_jj_in(".", ["git", "init", "remote"]).success();
|
|
let remote_dir = test_env.work_dir("remote");
|
|
for bookmark in [
|
|
"remote-sync",
|
|
"remote-unsync",
|
|
"remote-untrack",
|
|
"remote-delete",
|
|
] {
|
|
remote_dir
|
|
.run_jj(["new", "root()", "-m", bookmark])
|
|
.success();
|
|
remote_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
remote_dir.run_jj(["new"]).success();
|
|
remote_dir.run_jj(["git", "export"]).success();
|
|
|
|
// Initialize local refs
|
|
let mut remote_git_path = remote_dir.root().to_owned();
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
|
test_env
|
|
.run_jj_in(
|
|
".",
|
|
[
|
|
"git",
|
|
"clone",
|
|
"--colocate",
|
|
remote_git_path.to_str().unwrap(),
|
|
"local",
|
|
],
|
|
)
|
|
.success();
|
|
|
|
test_env
|
|
.run_jj_in(".", ["git", "init", "upstream"])
|
|
.success();
|
|
|
|
// Initialize a second remote
|
|
let upstream_dir = test_env.work_dir("upstream");
|
|
upstream_dir
|
|
.run_jj(["new", "root()", "-m", "upstream-sync"])
|
|
.success();
|
|
upstream_dir
|
|
.run_jj(["bookmark", "create", "-r@", "upstream-sync"])
|
|
.success();
|
|
upstream_dir.run_jj(["new"]).success();
|
|
upstream_dir.run_jj(["git", "export"]).success();
|
|
|
|
let mut upstream_git_path = upstream_dir.root().to_owned();
|
|
upstream_git_path.extend([".jj", "repo", "store", "git"]);
|
|
|
|
let local_dir = test_env.work_dir("local");
|
|
|
|
local_dir
|
|
.run_jj([
|
|
"git",
|
|
"remote",
|
|
"add",
|
|
"upstream",
|
|
upstream_git_path.to_str().unwrap(),
|
|
])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["git", "fetch", "--all-remotes"])
|
|
.success();
|
|
|
|
local_dir
|
|
.run_jj(["new", "root()", "-m", "local-only"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "create", "-r@", "local-only"])
|
|
.success();
|
|
|
|
// Mutate refs in local repository
|
|
local_dir
|
|
.run_jj(["bookmark", "delete", "remote-delete"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "delete", "remote-untrack"])
|
|
.success();
|
|
local_dir
|
|
.run_jj(["bookmark", "untrack", "remote-untrack@origin"])
|
|
.success();
|
|
local_dir
|
|
.run_jj([
|
|
"git",
|
|
"push",
|
|
"--allow-new",
|
|
"--remote",
|
|
"upstream",
|
|
"--bookmark",
|
|
"remote-unsync",
|
|
])
|
|
.success();
|
|
local_dir
|
|
.run_jj([
|
|
"bookmark",
|
|
"set",
|
|
"--to=@",
|
|
"--allow-backwards",
|
|
"remote-unsync",
|
|
])
|
|
.success();
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--all-remotes"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
local-only: nmzmmopx 2a685e16 (empty) local-only
|
|
@git: nmzmmopx 2a685e16 (empty) local-only
|
|
remote-delete (deleted)
|
|
@origin: vruxwmqv b32031cf (empty) remote-delete
|
|
remote-sync: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
@git: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
@origin: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
remote-unsync: nmzmmopx 2a685e16 (empty) local-only
|
|
@git: nmzmmopx 2a685e16 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
@upstream (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
remote-untrack@origin: royxmykx 149bc756 (empty) remote-untrack
|
|
upstream-sync: lylxulpl 169ba7d9 (empty) upstream-sync
|
|
@git: lylxulpl 169ba7d9 (empty) upstream-sync
|
|
@upstream: lylxulpl 169ba7d9 (empty) upstream-sync
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--tracked"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
remote-delete (deleted)
|
|
@origin: vruxwmqv b32031cf (empty) remote-delete
|
|
remote-sync: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
@origin: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
remote-unsync: nmzmmopx 2a685e16 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
@upstream (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
upstream-sync: lylxulpl 169ba7d9 (empty) upstream-sync
|
|
@upstream: lylxulpl 169ba7d9 (empty) upstream-sync
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--tracked", "--remote", "origin"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
remote-delete (deleted)
|
|
@origin: vruxwmqv b32031cf (empty) remote-delete
|
|
remote-sync: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
@origin: rlvkpnrz 7a07dbee (empty) remote-sync
|
|
remote-unsync: nmzmmopx 2a685e16 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
[EOF]
|
|
------- stderr -------
|
|
Hint: Bookmarks marked as deleted can be *deleted permanently* on the remote by running `jj git push --deleted`. Use `jj bookmark forget` if you don't want that.
|
|
[EOF]
|
|
");
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--tracked", "remote-unsync"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
remote-unsync: nmzmmopx 2a685e16 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
@upstream (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
[EOF]
|
|
");
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--tracked", "remote-untrack"]);
|
|
insta::assert_snapshot!(output, @"");
|
|
|
|
local_dir
|
|
.run_jj(["bookmark", "untrack", "remote-unsync@upstream"])
|
|
.success();
|
|
|
|
let output = local_dir.run_jj(["bookmark", "list", "--tracked", "remote-unsync"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
remote-unsync: nmzmmopx 2a685e16 (empty) local-only
|
|
@origin (ahead by 1 commits, behind by 1 commits): zsuskuln 553203ba (empty) remote-unsync
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_conflicted() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Track existing bookmark. Local bookmark should result in conflict.
|
|
work_dir.run_jj(["new", "root()", "-m", "a"]).success();
|
|
work_dir.run_jj(["new", "root()", "-m", "b"]).success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", "bar"])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "foo", "-r", "description(a)"])
|
|
.success();
|
|
work_dir
|
|
.run_jj([
|
|
"bookmark",
|
|
"create",
|
|
"foo",
|
|
"-r",
|
|
"description(b)",
|
|
"--at-op=@-",
|
|
])
|
|
.success();
|
|
work_dir.run_jj(["status"]).success();
|
|
insta::assert_snapshot!(get_bookmark_output(&work_dir), @r"
|
|
bar: kkmpptxz a82129fb (empty) b
|
|
foo (conflicted):
|
|
+ rlvkpnrz 4e1b2d80 (empty) a
|
|
+ kkmpptxz a82129fb (empty) b
|
|
[EOF]
|
|
");
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "list", "--conflicted"]), @r"
|
|
foo (conflicted):
|
|
+ rlvkpnrz 4e1b2d80 (empty) a
|
|
+ kkmpptxz a82129fb (empty) b
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_sort_unknown_key_error() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "list", "--sort", "date"]), @r"
|
|
------- stderr -------
|
|
error: invalid value 'date' for '--sort <SORT_KEY>'
|
|
[possible values: name, name-, author-name, author-name-, author-email, author-email-, author-date, author-date-, committer-name, committer-name-, committer-email, committer-email-, committer-date, committer-date-]
|
|
|
|
For more information, try '--help'.
|
|
[EOF]
|
|
[exit status: 2]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_sort_multiple_keys() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
for (bookmark, email) in [("c", "bob@g.c"), ("b", "alice@g.c"), ("a", "bob@g.c")] {
|
|
work_dir
|
|
.run_jj([
|
|
&format!("--config=user.email={email}"),
|
|
"new",
|
|
"root()",
|
|
"-m",
|
|
"fix",
|
|
])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
|
|
let template =
|
|
r#"name ++ ": " ++ if(normal_target, normal_target.committer().email()) ++ "\n""#;
|
|
insta::assert_snapshot!(work_dir.run_jj(["bookmark", "list", "-T", template, "--sort", "committer-email,committer-date-"]), @r"
|
|
b: alice@g.c
|
|
a: bob@g.c
|
|
c: bob@g.c
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_sort_using_config() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
for (bookmark, email) in [("c", "bob@g.c"), ("b", "alice@g.c"), ("a", "bob@g.c")] {
|
|
work_dir
|
|
.run_jj([
|
|
&format!("--config=user.email={email}"),
|
|
"new",
|
|
"root()",
|
|
"-m",
|
|
"fix",
|
|
])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
|
|
let template = r#"name ++ ": " ++ if(normal_target, normal_target.author().email()) ++ "\n""#;
|
|
insta::assert_snapshot!(work_dir.run_jj([
|
|
"--config=ui.bookmark-list-sort-keys=['author-email', 'author-date-']",
|
|
"bookmark",
|
|
"list",
|
|
"-T",
|
|
template
|
|
]), @r"
|
|
b: alice@g.c
|
|
a: bob@g.c
|
|
c: bob@g.c
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_list_sort_overriding_config() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
for (bookmark, email) in [("c", "bob@g.c"), ("b", "alice@g.c"), ("a", "bob@g.c")] {
|
|
work_dir
|
|
.run_jj([
|
|
&format!("--config=user.email={email}"),
|
|
"new",
|
|
"root()",
|
|
"-m",
|
|
"fix",
|
|
])
|
|
.success();
|
|
work_dir
|
|
.run_jj(["bookmark", "create", "-r@", bookmark])
|
|
.success();
|
|
}
|
|
|
|
let template = r#"name ++ ": " ++ if(normal_target, normal_target.author().email()) ++ "\n""#;
|
|
insta::assert_snapshot!(work_dir.run_jj([
|
|
"--config=ui.bookmark-list-sort-keys=['author-email', 'author-date-']",
|
|
"bookmark",
|
|
"list",
|
|
"--sort=name-", // overriding config.
|
|
"-T",
|
|
template
|
|
]), @r"
|
|
c: bob@g.c
|
|
b: alice@g.c
|
|
a: bob@g.c
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_create_with_default_target_revision() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "create", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Target revision was not specified, defaulting to the working copy (-r@). In the near future it will be required to explicitly specify target revision.
|
|
Created 1 bookmarks pointing to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_set_with_default_target_revision() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
let output = work_dir.run_jj(["bookmark", "set", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Target revision was not specified, defaulting to the working copy (--revision=@). In the near future it will be required to explicitly specify target revision.
|
|
Created 1 bookmarks pointing to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmark_move_with_default_target_revision() {
|
|
let test_env = TestEnvironment::default();
|
|
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
|
|
let work_dir = test_env.work_dir("repo");
|
|
|
|
// Set up remote
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
git::init_bare(git_repo_path);
|
|
work_dir
|
|
.run_jj(["git", "remote", "add", "origin", "../git-repo"])
|
|
.success();
|
|
|
|
let output = work_dir.run_jj(["bookmark", "create", "foo", "-r@"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Created 1 bookmarks pointing to qpvuntsm e8849ae1 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
|
|
work_dir.run_jj(["new"]).success();
|
|
let output = work_dir.run_jj(["bookmark", "move", "foo"]);
|
|
insta::assert_snapshot!(output, @r"
|
|
------- stderr -------
|
|
Warning: Target revision was not specified, defaulting to the working copy (--to=@). In the near future it will be required to explicitly specify it.
|
|
Moved 1 bookmarks to zsuskuln 0e555a27 foo | (empty) (no description set)
|
|
[EOF]
|
|
");
|
|
}
|
|
|
|
#[must_use]
|
|
fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {
|
|
let template = r#"bookmarks ++ " " ++ commit_id.short()"#;
|
|
work_dir.run_jj(["log", "-T", template])
|
|
}
|
|
|
|
#[must_use]
|
|
fn get_bookmark_output(work_dir: &TestWorkDir) -> CommandOutput {
|
|
// --quiet to suppress deleted bookmarks hint
|
|
work_dir.run_jj(["bookmark", "list", "--all-remotes", "--quiet"])
|
|
}
|