2022-11-26 23:57:50 +00:00
|
|
|
// Copyright 2022 The Jujutsu Authors
|
2022-05-02 20:03:34 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2022-05-02 19:58:32 +00:00
|
|
|
use std::path::Path;
|
|
|
|
|
2023-07-03 10:04:31 +00:00
|
|
|
use crate::common::TestEnvironment;
|
2022-05-02 20:03:34 +00:00
|
|
|
|
|
|
|
pub mod common;
|
|
|
|
|
2022-05-02 19:58:32 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_multiple_names() {
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2022-05-02 19:58:32 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
2023-07-03 10:04:31 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo", "bar"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
warning: Updating multiple branches (2).
|
|
|
|
"###);
|
2022-05-02 19:58:32 +00:00
|
|
|
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-02-09 02:53:47 +00:00
|
|
|
@ bar foo 230dd059e1b0
|
2023-03-15 03:37:56 +00:00
|
|
|
◉ 000000000000
|
2022-05-02 19:58:32 +00:00
|
|
|
"###);
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) =
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "foo", "bar", "foo"]);
|
2023-10-10 11:07:06 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-06-29 02:36:08 +00:00
|
|
|
Deleted 2 branches.
|
|
|
|
"###);
|
2022-05-02 19:58:32 +00:00
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-02-09 02:53:47 +00:00
|
|
|
@ 230dd059e1b0
|
2023-03-15 03:37:56 +00:00
|
|
|
◉ 000000000000
|
2022-05-02 19:58:32 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-04-04 02:02:12 +00:00
|
|
|
#[test]
|
2023-09-03 21:07:15 +00:00
|
|
|
fn test_branch_at_root() {
|
2023-04-04 02:02:12 +00:00
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-04-04 02:02:12 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) =
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "fred", "-r=root()"]);
|
2023-09-03 21:07:15 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-09-03 21:07:15 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-10-10 11:07:06 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-04-04 02:02:12 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-10 11:07:06 +00:00
|
|
|
Nothing changed.
|
2023-09-03 21:07:15 +00:00
|
|
|
Failed to export some branches:
|
|
|
|
fred
|
2023-04-04 02:02:12 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:17:33 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_empty_name() {
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2022-11-28 14:17:33 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
|
|
|
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "create", ""]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-03-17 23:14:20 +00:00
|
|
|
error: a value is required for '<NAMES>...' but none was supplied
|
2022-11-28 14:17:33 +00:00
|
|
|
|
2023-03-17 23:14:20 +00:00
|
|
|
For more information, try '--help'.
|
2022-11-28 14:17:33 +00:00
|
|
|
"###);
|
|
|
|
}
|
2023-06-12 01:04:55 +00:00
|
|
|
|
2022-11-22 23:58:04 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_forget_glob() {
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2022-11-22 23:58:04 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-1"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "bar-2"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-3"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-4"]);
|
2022-11-22 23:58:04 +00:00
|
|
|
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-02-09 02:53:47 +00:00
|
|
|
@ bar-2 foo-1 foo-3 foo-4 230dd059e1b0
|
2023-03-15 03:37:56 +00:00
|
|
|
◉ 000000000000
|
2022-11-22 23:58:04 +00:00
|
|
|
"###);
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) =
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "--glob", "foo-[1-3]"]);
|
2023-10-10 11:07:06 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 21:19:19 +00:00
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
2023-06-29 02:36:08 +00:00
|
|
|
Forgot 2 branches.
|
|
|
|
"###);
|
2023-10-19 20:17:58 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "glob:foo-[1-3]"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Forgot 2 branches.
|
|
|
|
"###);
|
2022-11-22 23:58:04 +00:00
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-02-09 02:53:47 +00:00
|
|
|
@ bar-2 foo-4 230dd059e1b0
|
2023-03-15 03:37:56 +00:00
|
|
|
◉ 000000000000
|
2022-11-22 23:58:04 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Forgetting a branch via both explicit name and glob pattern, or with
|
|
|
|
// multiple glob patterns, shouldn't produce an error.
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(
|
2022-11-22 23:58:04 +00:00
|
|
|
&repo_path,
|
2023-10-19 20:17:58 +00:00
|
|
|
&["branch", "forget", "foo-4", "--glob", "foo-*", "glob:foo-*"],
|
2022-11-22 23:58:04 +00:00
|
|
|
);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-19 21:19:19 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
|
|
|
"###);
|
2022-11-22 23:58:04 +00:00
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-02-09 02:53:47 +00:00
|
|
|
@ bar-2 230dd059e1b0
|
2023-03-15 03:37:56 +00:00
|
|
|
◉ 000000000000
|
2022-11-22 23:58:04 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Malformed glob
|
2023-10-19 20:17:58 +00:00
|
|
|
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "forget", "glob:foo-[1-3"]);
|
2022-11-22 23:58:04 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 20:17:58 +00:00
|
|
|
error: invalid value 'glob:foo-[1-3' for '[NAMES]...': Pattern syntax error near position 4: invalid range pattern
|
2023-10-19 18:49:00 +00:00
|
|
|
|
|
|
|
For more information, try '--help'.
|
2022-11-22 23:58:04 +00:00
|
|
|
"###);
|
2023-06-24 05:52:00 +00:00
|
|
|
|
|
|
|
// We get an error if none of the globs match anything
|
|
|
|
let stderr = test_env.jj_cmd_failure(
|
|
|
|
&repo_path,
|
2023-10-19 20:17:58 +00:00
|
|
|
&["branch", "forget", "glob:bar*", "glob:baz*", "--glob=boom*"],
|
2023-06-24 05:52:00 +00:00
|
|
|
);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 21:19:19 +00:00
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
2023-10-19 18:49:00 +00:00
|
|
|
Error: No matching branches for patterns: baz*, boom*
|
2023-06-24 05:52:00 +00:00
|
|
|
"###);
|
2022-11-22 23:58:04 +00:00
|
|
|
}
|
2022-11-28 14:17:33 +00:00
|
|
|
|
2023-06-24 06:27:48 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_delete_glob() {
|
|
|
|
// Set up a git repo with a branch and a jj repo that has it as a remote.
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-06-24 06:27:48 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
|
|
let git_repo = git2::Repository::init_bare(git_repo_path).unwrap();
|
|
|
|
let mut tree_builder = git_repo.treebuilder(None).unwrap();
|
|
|
|
let file_oid = git_repo.blob(b"content").unwrap();
|
|
|
|
tree_builder
|
|
|
|
.insert("file", file_oid, git2::FileMode::Blob.into())
|
|
|
|
.unwrap();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(
|
2023-06-24 06:27:48 +00:00
|
|
|
&repo_path,
|
|
|
|
&["git", "remote", "add", "origin", "../git-repo"],
|
|
|
|
);
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["describe", "-m=commit"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-1"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "bar-2"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-3"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo-4"]);
|
2023-06-24 06:27:48 +00:00
|
|
|
// Push to create remote-tracking branches
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "push", "--all"]);
|
2023-06-24 06:27:48 +00:00
|
|
|
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
@ bar-2 foo-1 foo-3 foo-4 6fbf398c2d59
|
2023-09-06 05:05:17 +00:00
|
|
|
◉ 000000000000
|
2023-06-24 06:27:48 +00:00
|
|
|
"###);
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) =
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "--glob", "foo-[1-3]"]);
|
2023-10-10 11:07:06 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 21:19:19 +00:00
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
2023-06-29 02:36:08 +00:00
|
|
|
Deleted 2 branches.
|
|
|
|
"###);
|
2023-10-19 20:17:58 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["undo"]);
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "glob:foo-[1-3]"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Deleted 2 branches.
|
|
|
|
"###);
|
2023-06-24 06:27:48 +00:00
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
@ bar-2 foo-1@origin foo-3@origin foo-4 6fbf398c2d59
|
2023-09-06 05:05:17 +00:00
|
|
|
◉ 000000000000
|
2023-06-24 06:27:48 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// We get an error if none of the globs match live branches. Unlike `jj branch
|
|
|
|
// forget`, it's not allowed to delete already deleted branches.
|
|
|
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["branch", "delete", "--glob=foo-[1-3]"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 21:19:19 +00:00
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
2023-10-19 18:49:00 +00:00
|
|
|
Error: No matching branches for patterns: foo-[1-3]
|
2023-06-24 06:27:48 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Deleting a branch via both explicit name and glob pattern, or with
|
|
|
|
// multiple glob patterns, shouldn't produce an error.
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(
|
2023-06-24 06:27:48 +00:00
|
|
|
&repo_path,
|
2023-10-19 20:17:58 +00:00
|
|
|
&["branch", "delete", "foo-4", "--glob", "foo-*", "glob:foo-*"],
|
2023-06-24 06:27:48 +00:00
|
|
|
);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-19 21:19:19 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
--glob has been deprecated. Please prefix the pattern with `glob:` instead.
|
|
|
|
"###);
|
2023-06-24 06:27:48 +00:00
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
@ bar-2 foo-1@origin foo-3@origin foo-4@origin 6fbf398c2d59
|
2023-09-06 05:05:17 +00:00
|
|
|
◉ 000000000000
|
2023-06-24 06:27:48 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// The deleted branches are still there
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
bar-2: qpvuntsm 6fbf398c (empty) commit
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: qpvuntsm 6fbf398c (empty) commit
|
2023-06-24 06:27:48 +00:00
|
|
|
foo-1 (deleted)
|
2023-07-11 01:46:38 +00:00
|
|
|
@origin: qpvuntsm 6fbf398c (empty) commit
|
2023-06-24 06:27:48 +00:00
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
|
|
|
foo-3 (deleted)
|
2023-07-11 01:46:38 +00:00
|
|
|
@origin: qpvuntsm 6fbf398c (empty) commit
|
2023-06-24 06:27:48 +00:00
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
|
|
|
foo-4 (deleted)
|
2023-07-11 01:46:38 +00:00
|
|
|
@origin: qpvuntsm 6fbf398c (empty) commit
|
2023-06-24 06:27:48 +00:00
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Malformed glob
|
2023-10-19 20:17:58 +00:00
|
|
|
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "delete", "glob:foo-[1-3"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
error: invalid value 'glob:foo-[1-3' for '[NAMES]...': Pattern syntax error near position 4: invalid range pattern
|
|
|
|
|
|
|
|
For more information, try '--help'.
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Unknown pattern kind
|
|
|
|
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["branch", "forget", "whatever:branch"]);
|
2023-06-24 06:27:48 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-10-19 20:17:58 +00:00
|
|
|
error: invalid value 'whatever:branch' for '[NAMES]...': Invalid string pattern kind "whatever"
|
2023-10-19 18:49:00 +00:00
|
|
|
|
|
|
|
For more information, try '--help'.
|
2023-06-24 06:27:48 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-09-29 07:40:41 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_delete_export() {
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-09-29 07:40:41 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-09-29 07:40:41 +00:00
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "foo"]);
|
2023-10-18 06:12:17 +00:00
|
|
|
let stdout = test_env.jj_cmd_success(&repo_path, &["branch", "list", "--all"]);
|
2023-09-29 07:40:41 +00:00
|
|
|
insta::assert_snapshot!(stdout, @r###"
|
|
|
|
foo (deleted)
|
|
|
|
@git: rlvkpnrz 65b6b74e (empty) (no description set)
|
|
|
|
(this branch will be deleted from the underlying Git repo on the next `jj git export`)
|
|
|
|
"###);
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-10-18 06:12:17 +00:00
|
|
|
let stdout = test_env.jj_cmd_success(&repo_path, &["branch", "list", "--all"]);
|
2023-09-29 07:40:41 +00:00
|
|
|
insta::assert_snapshot!(stdout, @r###"
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-06-12 01:04:55 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_forget_export() {
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "foo"]);
|
2023-10-18 06:12:17 +00:00
|
|
|
let stdout = test_env.jj_cmd_success(&repo_path, &["branch", "list", "--all"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
insta::assert_snapshot!(stdout, @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
foo: rlvkpnrz 65b6b74e (empty) (no description set)
|
2023-06-12 01:04:55 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Exporting the branch to git creates a local-git tracking branch
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "foo"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-09-25 14:34:09 +00:00
|
|
|
// Forgetting a branch deletes local and remote-tracking branches including
|
|
|
|
// the corresponding git-tracking branch.
|
2023-10-18 06:12:17 +00:00
|
|
|
let stdout = test_env.jj_cmd_success(&repo_path, &["branch", "list", "--all"]);
|
2023-09-25 14:34:09 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-06-12 18:59:15 +00:00
|
|
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r=foo", "--no-graph"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Error: Revision "foo" doesn't exist
|
2023-06-12 01:04:55 +00:00
|
|
|
"###);
|
|
|
|
|
2023-09-25 11:05:24 +00:00
|
|
|
// `jj git export` will delete the branch from git. In a colocated repo,
|
|
|
|
// this will happen automatically immediately after a `jj branch forget`.
|
|
|
|
// This is demonstrated in `test_git_colocated_branch_forget` in
|
|
|
|
// test_git_colocated.rs
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-10-18 06:12:17 +00:00
|
|
|
let stdout = test_env.jj_cmd_success(&repo_path, &["branch", "list", "--all"]);
|
2023-06-12 01:04:55 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
}
|
|
|
|
|
2023-06-13 21:49:51 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_forget_fetched_branch() {
|
|
|
|
// Much of this test is borrowed from `test_git_fetch_remote_only_branch` in
|
|
|
|
// test_git_fetch.rs
|
|
|
|
|
|
|
|
// Set up a git repo with a branch and a jj repo that has it as a remote.
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-06-13 21:49:51 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
2023-06-24 06:27:48 +00:00
|
|
|
let git_repo = git2::Repository::init_bare(git_repo_path).unwrap();
|
2023-06-13 21:49:51 +00:00
|
|
|
let signature =
|
|
|
|
git2::Signature::new("Some One", "some.one@example.com", &git2::Time::new(0, 0)).unwrap();
|
|
|
|
let mut tree_builder = git_repo.treebuilder(None).unwrap();
|
|
|
|
let file_oid = git_repo.blob(b"content").unwrap();
|
|
|
|
tree_builder
|
|
|
|
.insert("file", file_oid, git2::FileMode::Blob.into())
|
|
|
|
.unwrap();
|
|
|
|
let tree_oid = tree_builder.write().unwrap();
|
|
|
|
let tree = git_repo.find_tree(tree_oid).unwrap();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(
|
2023-06-13 21:49:51 +00:00
|
|
|
&repo_path,
|
|
|
|
&["git", "remote", "add", "origin", "../git-repo"],
|
|
|
|
);
|
|
|
|
// Create a commit and a branch in the git repo
|
|
|
|
let first_git_repo_commit = git_repo
|
|
|
|
.commit(
|
|
|
|
Some("refs/heads/feature1"),
|
|
|
|
&signature,
|
|
|
|
&signature,
|
|
|
|
"message",
|
|
|
|
&tree,
|
|
|
|
&[],
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Fetch normally
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
2023-06-13 21:49:51 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
feature1: mzyxwzks 9f01a0e0 message
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: mzyxwzks 9f01a0e0 message
|
2023-06-13 21:49:51 +00:00
|
|
|
"###);
|
|
|
|
|
2023-06-27 22:18:15 +00:00
|
|
|
// TEST 1: with export-import
|
2023-06-13 21:49:51 +00:00
|
|
|
// Forget the branch
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "feature1"]);
|
2023-06-13 21:49:51 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
|
|
|
|
|
|
|
// At this point `jj git export && jj git import` does *not* recreate the
|
|
|
|
// branch. This behavior is important in colocated repos, as otherwise a
|
|
|
|
// forgotten branch would be immediately resurrected.
|
|
|
|
//
|
|
|
|
// Technically, this is because `jj branch forget` preserved
|
|
|
|
// the ref in jj view's `git_refs` tracking the local git repo's remote-tracking
|
|
|
|
// branch.
|
|
|
|
// TODO: Show that jj git push is also a no-op
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @"");
|
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "import"]);
|
2023-10-10 11:07:06 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
2023-06-13 21:49:51 +00:00
|
|
|
Nothing changed.
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
|
|
|
|
2023-06-27 22:18:15 +00:00
|
|
|
// We can fetch feature1 again.
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
2023-06-27 22:18:15 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-06-27 22:18:15 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
feature1: mzyxwzks 9f01a0e0 message
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: mzyxwzks 9f01a0e0 message
|
2023-06-27 22:18:15 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// TEST 2: No export/import (otherwise the same as test 1)
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "feature1"]);
|
2023-06-27 22:18:15 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
2023-06-30 02:20:00 +00:00
|
|
|
// Fetch works even without the export-import
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
2023-06-30 02:20:00 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-06-30 02:20:00 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
feature1: mzyxwzks 9f01a0e0 message
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: mzyxwzks 9f01a0e0 message
|
2023-06-13 21:49:51 +00:00
|
|
|
"###);
|
|
|
|
|
2023-06-27 22:18:15 +00:00
|
|
|
// TEST 3: fetch branch that was moved & forgotten
|
|
|
|
|
2023-06-13 21:49:51 +00:00
|
|
|
// Move the branch in the git repo.
|
|
|
|
git_repo
|
|
|
|
.commit(
|
|
|
|
Some("refs/heads/feature1"),
|
|
|
|
&signature,
|
|
|
|
&signature,
|
|
|
|
"another message",
|
|
|
|
&tree,
|
|
|
|
&[&git_repo.find_commit(first_git_repo_commit).unwrap()],
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "feature1"]);
|
2023-06-30 02:20:00 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-06-13 21:49:51 +00:00
|
|
|
|
2023-06-30 02:20:00 +00:00
|
|
|
// Fetching a moved branch does not create a conflict
|
2023-10-10 11:59:18 +00:00
|
|
|
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
2023-06-13 21:49:51 +00:00
|
|
|
insta::assert_snapshot!(stdout, @"");
|
2023-10-10 11:59:18 +00:00
|
|
|
insta::assert_snapshot!(stderr, @"");
|
2023-06-13 21:49:51 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
feature1: ooosovrs 38aefb17 (empty) another message
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: ooosovrs 38aefb17 (empty) another message
|
2023-06-13 21:49:51 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-06-24 04:40:54 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_forget_deleted_or_nonexistent_branch() {
|
|
|
|
// Much of this test is borrowed from `test_git_fetch_remote_only_branch` in
|
|
|
|
// test_git_fetch.rs
|
|
|
|
|
|
|
|
// ======== Beginning of test setup ========
|
|
|
|
// Set up a git repo with a branch and a jj repo that has it as a remote.
|
|
|
|
let test_env = TestEnvironment::default();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
2023-06-24 04:40:54 +00:00
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
2023-06-24 06:27:48 +00:00
|
|
|
let git_repo = git2::Repository::init_bare(git_repo_path).unwrap();
|
2023-06-24 04:40:54 +00:00
|
|
|
let signature =
|
|
|
|
git2::Signature::new("Some One", "some.one@example.com", &git2::Time::new(0, 0)).unwrap();
|
|
|
|
let mut tree_builder = git_repo.treebuilder(None).unwrap();
|
|
|
|
let file_oid = git_repo.blob(b"content").unwrap();
|
|
|
|
tree_builder
|
|
|
|
.insert("file", file_oid, git2::FileMode::Blob.into())
|
|
|
|
.unwrap();
|
|
|
|
let tree_oid = tree_builder.write().unwrap();
|
|
|
|
let tree = git_repo.find_tree(tree_oid).unwrap();
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(
|
2023-06-24 04:40:54 +00:00
|
|
|
&repo_path,
|
|
|
|
&["git", "remote", "add", "origin", "../git-repo"],
|
|
|
|
);
|
|
|
|
// Create a commit and a branch in the git repo
|
|
|
|
git_repo
|
|
|
|
.commit(
|
|
|
|
Some("refs/heads/feature1"),
|
|
|
|
&signature,
|
|
|
|
&signature,
|
|
|
|
"message",
|
|
|
|
&tree,
|
|
|
|
&[],
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Fetch and then delete the branch
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "feature1"]);
|
2023-06-24 04:40:54 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1 (deleted)
|
2023-07-11 01:46:38 +00:00
|
|
|
@origin: mzyxwzks 9f01a0e0 message
|
2023-06-24 06:35:33 +00:00
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
2023-06-24 04:40:54 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// ============ End of test setup ============
|
|
|
|
|
2023-06-24 04:48:48 +00:00
|
|
|
// We can forget a deleted branch
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "forget", "feature1"]);
|
2023-06-24 04:48:48 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @"");
|
2023-06-24 04:40:54 +00:00
|
|
|
|
|
|
|
// Can't forget a non-existent branch
|
|
|
|
let stderr = test_env.jj_cmd_failure(&repo_path, &["branch", "forget", "i_do_not_exist"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Error: No such branch: i_do_not_exist
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-10-12 18:29:53 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_track_untrack() {
|
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
|
|
|
// Set up remote
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
|
|
let git_repo = git2::Repository::init(git_repo_path).unwrap();
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
&repo_path,
|
|
|
|
&["git", "remote", "add", "origin", "../git-repo"],
|
|
|
|
);
|
|
|
|
let create_remote_commit = |message: &str, data: &[u8], ref_names: &[&str]| {
|
|
|
|
let signature =
|
|
|
|
git2::Signature::new("Some One", "some.one@example.com", &git2::Time::new(0, 0))
|
|
|
|
.unwrap();
|
|
|
|
let mut tree_builder = git_repo.treebuilder(None).unwrap();
|
|
|
|
let file_oid = git_repo.blob(data).unwrap();
|
|
|
|
tree_builder
|
|
|
|
.insert("file", file_oid, git2::FileMode::Blob.into())
|
|
|
|
.unwrap();
|
|
|
|
let tree_oid = tree_builder.write().unwrap();
|
|
|
|
let tree = git_repo.find_tree(tree_oid).unwrap();
|
|
|
|
// Create commit and branches in the remote
|
|
|
|
let git_commit_oid = git_repo
|
|
|
|
.commit(None, &signature, &signature, message, &tree, &[])
|
|
|
|
.unwrap();
|
|
|
|
for name in ref_names {
|
|
|
|
git_repo.reference(name, git_commit_oid, true, "").unwrap();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Fetch new commit without auto tracking. No local branches should be
|
|
|
|
// created.
|
|
|
|
create_remote_commit(
|
|
|
|
"commit 1",
|
|
|
|
b"content 1",
|
|
|
|
&[
|
|
|
|
"refs/heads/main",
|
|
|
|
"refs/heads/feature1",
|
|
|
|
"refs/heads/feature2",
|
|
|
|
],
|
|
|
|
);
|
|
|
|
test_env.add_config("git.auto-local-branch = false");
|
|
|
|
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
|
|
|
insta::assert_snapshot!(stderr, @"");
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
feature2@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
main@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
◉ feature1@origin feature2@origin main@origin 7b33f6295eda
|
|
|
|
│ @ 230dd059e1b0
|
|
|
|
├─╯
|
|
|
|
◉ 000000000000
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Track new branch. Local branch should be created.
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
&repo_path,
|
|
|
|
&["branch", "track", "feature1@origin", "main@origin"],
|
|
|
|
);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: sptzoqmo 7b33f629 commit 1
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: sptzoqmo 7b33f629 commit 1
|
2023-10-12 18:29:53 +00:00
|
|
|
feature2@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
main: sptzoqmo 7b33f629 commit 1
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: sptzoqmo 7b33f629 commit 1
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Track existing branch. Local branch should result in conflict.
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "feature2"]);
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "track", "feature2@origin"]);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: sptzoqmo 7b33f629 commit 1
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: sptzoqmo 7b33f629 commit 1
|
2023-10-12 18:29:53 +00:00
|
|
|
feature2 (conflicted):
|
|
|
|
+ qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
+ sptzoqmo 7b33f629 commit 1
|
|
|
|
@origin (behind by 1 commits): sptzoqmo 7b33f629 commit 1
|
|
|
|
main: sptzoqmo 7b33f629 commit 1
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: sptzoqmo 7b33f629 commit 1
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Untrack existing and locally-deleted branches. Branch targets should be
|
|
|
|
// unchanged
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "delete", "feature2"]);
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
&repo_path,
|
|
|
|
&["branch", "untrack", "feature1@origin", "feature2@origin"],
|
|
|
|
);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: sptzoqmo 7b33f629 commit 1
|
|
|
|
feature1@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
feature2@origin: sptzoqmo 7b33f629 commit 1
|
|
|
|
main: sptzoqmo 7b33f629 commit 1
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: sptzoqmo 7b33f629 commit 1
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
2023-10-15 23:30:45 +00:00
|
|
|
◉ feature1 feature1@origin feature2@origin main 7b33f6295eda
|
2023-10-12 18:29:53 +00:00
|
|
|
│ @ 230dd059e1b0
|
|
|
|
├─╯
|
|
|
|
◉ 000000000000
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Fetch new commit. Only tracking branch "main" should be merged.
|
|
|
|
create_remote_commit(
|
|
|
|
"commit 2",
|
|
|
|
b"content 2",
|
|
|
|
&[
|
|
|
|
"refs/heads/main",
|
|
|
|
"refs/heads/feature1",
|
|
|
|
"refs/heads/feature2",
|
|
|
|
],
|
|
|
|
);
|
|
|
|
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
|
|
|
insta::assert_snapshot!(stderr, @"");
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: sptzoqmo 7b33f629 commit 1
|
|
|
|
feature1@origin: mmqqkyyt 40dabdaf commit 2
|
|
|
|
feature2@origin: mmqqkyyt 40dabdaf commit 2
|
|
|
|
main: mmqqkyyt 40dabdaf commit 2
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: mmqqkyyt 40dabdaf commit 2
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
◉ feature1@origin feature2@origin main 40dabdaf4abe
|
2023-10-15 23:30:45 +00:00
|
|
|
│ ◉ feature1 7b33f6295eda
|
2023-10-12 18:29:53 +00:00
|
|
|
├─╯
|
|
|
|
│ @ 230dd059e1b0
|
|
|
|
├─╯
|
|
|
|
◉ 000000000000
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Fetch new commit with auto tracking. Tracking branch "main" and new
|
|
|
|
// branch "feature3" should be merged.
|
|
|
|
create_remote_commit(
|
|
|
|
"commit 3",
|
|
|
|
b"content 3",
|
|
|
|
&[
|
|
|
|
"refs/heads/main",
|
|
|
|
"refs/heads/feature1",
|
|
|
|
"refs/heads/feature2",
|
|
|
|
"refs/heads/feature3",
|
|
|
|
],
|
|
|
|
);
|
|
|
|
test_env.add_config("git.auto-local-branch = true");
|
|
|
|
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Abandoned 1 commits that are no longer reachable.
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: sptzoqmo 7b33f629 commit 1
|
|
|
|
feature1@origin: wwnpyzpo 3f0f86fa commit 3
|
|
|
|
feature2@origin: wwnpyzpo 3f0f86fa commit 3
|
|
|
|
feature3: wwnpyzpo 3f0f86fa commit 3
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: wwnpyzpo 3f0f86fa commit 3
|
2023-10-12 18:29:53 +00:00
|
|
|
main: wwnpyzpo 3f0f86fa commit 3
|
2023-10-18 06:12:17 +00:00
|
|
|
@origin: wwnpyzpo 3f0f86fa commit 3
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
|
|
|
|
◉ feature1@origin feature2@origin feature3 main 3f0f86fa0e57
|
2023-10-15 23:30:45 +00:00
|
|
|
│ ◉ feature1 7b33f6295eda
|
2023-10-12 18:29:53 +00:00
|
|
|
├─╯
|
|
|
|
│ @ 230dd059e1b0
|
|
|
|
├─╯
|
|
|
|
◉ 000000000000
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-10-19 21:40:58 +00:00
|
|
|
fn test_branch_track_untrack_patterns() {
|
2023-10-12 18:29:53 +00:00
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
|
|
|
let repo_path = test_env.env_root().join("repo");
|
|
|
|
|
|
|
|
// Set up remote
|
|
|
|
let git_repo_path = test_env.env_root().join("git-repo");
|
|
|
|
let git_repo = git2::Repository::init(git_repo_path).unwrap();
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
&repo_path,
|
|
|
|
&["git", "remote", "add", "origin", "../git-repo"],
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create remote commit
|
|
|
|
let signature =
|
|
|
|
git2::Signature::new("Some One", "some.one@example.com", &git2::Time::new(0, 0)).unwrap();
|
|
|
|
let mut tree_builder = git_repo.treebuilder(None).unwrap();
|
|
|
|
let file_oid = git_repo.blob(b"content").unwrap();
|
|
|
|
tree_builder
|
|
|
|
.insert("file", file_oid, git2::FileMode::Blob.into())
|
|
|
|
.unwrap();
|
|
|
|
let tree_oid = tree_builder.write().unwrap();
|
|
|
|
let tree = git_repo.find_tree(tree_oid).unwrap();
|
|
|
|
// Create commit and branches in the remote
|
|
|
|
let git_commit_oid = git_repo
|
|
|
|
.commit(None, &signature, &signature, "commit", &tree, &[])
|
|
|
|
.unwrap();
|
|
|
|
for name in ["refs/heads/feature1", "refs/heads/feature2"] {
|
|
|
|
git_repo.reference(name, git_commit_oid, true, "").unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch new commit without auto tracking
|
|
|
|
test_env.add_config("git.auto-local-branch = false");
|
|
|
|
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["git", "fetch"]);
|
|
|
|
insta::assert_snapshot!(stderr, @"");
|
|
|
|
|
|
|
|
// Track local branch
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "set", "main"]);
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_cli_error(&repo_path, &["branch", "track", "main"]), @r###"
|
|
|
|
error: invalid value 'main' for '<NAMES>...': remote branch must be specified in branch@remote form
|
|
|
|
|
|
|
|
For more information, try '--help'.
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Track/untrack unknown branch
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_failure(&repo_path, &["branch", "track", "main@origin"]), @r###"
|
|
|
|
Error: No such remote branch: main@origin
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_failure(&repo_path, &["branch", "untrack", "main@origin"]), @r###"
|
|
|
|
Error: No such remote branch: main@origin
|
|
|
|
"###);
|
2023-10-19 21:40:58 +00:00
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_failure(&repo_path, &["branch", "track", "glob:maine@*"]), @r###"
|
|
|
|
Error: No matching remote branches for patterns: maine@*
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_failure(
|
|
|
|
&repo_path,
|
|
|
|
&["branch", "untrack", "main@origin", "glob:main@o*"],
|
|
|
|
), @r###"
|
|
|
|
Error: No matching remote branches for patterns: main@origin, main@o*
|
|
|
|
"###);
|
2023-10-12 18:29:53 +00:00
|
|
|
|
|
|
|
// Track already tracked branch
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["branch", "track", "feature1@origin"]);
|
2023-10-20 04:14:09 +00:00
|
|
|
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "track", "feature1@origin"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Remote branch already tracked: feature1@origin
|
|
|
|
Nothing changed.
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Untrack non-tracking branch
|
2023-10-20 04:14:09 +00:00
|
|
|
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "untrack", "feature2@origin"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Remote branch not tracked yet: feature2@origin
|
|
|
|
Nothing changed.
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Untrack Git-tracking branch
|
|
|
|
test_env.jj_cmd_ok(&repo_path, &["git", "export"]);
|
2023-10-20 04:14:09 +00:00
|
|
|
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "untrack", "main@git"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Git-tracking branch cannot be untracked: main@git
|
|
|
|
Nothing changed.
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: omvolwpu 1336caed commit
|
|
|
|
@git: omvolwpu 1336caed commit
|
|
|
|
@origin: omvolwpu 1336caed commit
|
|
|
|
feature2@origin: omvolwpu 1336caed commit
|
|
|
|
main: qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
@git: qpvuntsm 230dd059 (empty) (no description set)
|
2023-10-12 18:29:53 +00:00
|
|
|
"###);
|
2023-10-19 21:40:58 +00:00
|
|
|
|
|
|
|
// Untrack by pattern
|
|
|
|
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "untrack", "glob:*@*"]);
|
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Git-tracking branch cannot be untracked: feature1@git
|
|
|
|
Remote branch not tracked yet: feature2@origin
|
|
|
|
Git-tracking branch cannot be untracked: main@git
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: omvolwpu 1336caed commit
|
|
|
|
@git: omvolwpu 1336caed commit
|
|
|
|
feature1@origin: omvolwpu 1336caed commit
|
|
|
|
feature2@origin: omvolwpu 1336caed commit
|
|
|
|
main: qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
@git: qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// Track by pattern
|
|
|
|
let (_, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "track", "glob:feature?@origin"]);
|
2023-10-20 22:09:29 +00:00
|
|
|
insta::assert_snapshot!(stderr, @r###"
|
|
|
|
Started tracking 2 remote branches.
|
|
|
|
"###);
|
2023-10-19 21:40:58 +00:00
|
|
|
insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###"
|
|
|
|
feature1: omvolwpu 1336caed commit
|
|
|
|
@git: omvolwpu 1336caed commit
|
|
|
|
@origin: omvolwpu 1336caed commit
|
|
|
|
feature2: omvolwpu 1336caed commit
|
|
|
|
@origin: omvolwpu 1336caed commit
|
|
|
|
main: qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
@git: qpvuntsm 230dd059 (empty) (no description set)
|
|
|
|
"###);
|
2023-10-12 18:29:53 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 06:12:17 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_list() {
|
|
|
|
let test_env = TestEnvironment::default();
|
|
|
|
|
|
|
|
// Initialize remote refs
|
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "remote", "--git"]);
|
|
|
|
let remote_path = test_env.env_root().join("remote");
|
|
|
|
for branch in [
|
|
|
|
"remote-sync",
|
|
|
|
"remote-unsync",
|
|
|
|
"remote-untrack",
|
|
|
|
"remote-delete",
|
|
|
|
] {
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["new", "root()", "-m", branch]);
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["branch", "set", branch]);
|
|
|
|
}
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["new"]);
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["git", "export"]);
|
|
|
|
|
|
|
|
// Initialize local refs
|
|
|
|
let mut remote_git_path = remote_path;
|
|
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
test_env.env_root(),
|
|
|
|
&["git", "clone", remote_git_path.to_str().unwrap(), "local"],
|
|
|
|
);
|
|
|
|
let local_path = test_env.env_root().join("local");
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["new", "root()", "-m", "local-only"]);
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "set", "local-only"]);
|
|
|
|
|
|
|
|
// Mutate refs in local repository
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "delete", "remote-delete"]);
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "delete", "remote-untrack"]);
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "untrack", "remote-untrack@origin"]);
|
|
|
|
test_env.jj_cmd_ok(
|
|
|
|
&local_path,
|
|
|
|
&["branch", "set", "--allow-backwards", "remote-unsync"],
|
|
|
|
);
|
|
|
|
|
2023-10-18 06:56:02 +00:00
|
|
|
// Synchronized tracking remotes and non-tracking remotes aren't listed by
|
|
|
|
// default
|
2023-10-18 06:12:17 +00:00
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_success(&local_path, &["branch", "list"]), @r###"
|
|
|
|
local-only: wqnwkozp 4e887f78 (empty) local-only
|
|
|
|
remote-delete (deleted)
|
|
|
|
@origin: mnmymoky 203e60eb (empty) remote-delete
|
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
|
|
|
remote-sync: zwtyzrop c761c7ea (empty) remote-sync
|
|
|
|
remote-unsync: wqnwkozp 4e887f78 (empty) local-only
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
|
|
|
|
"###);
|
|
|
|
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_success(&local_path, &["branch", "list", "--all"]), @r###"
|
|
|
|
local-only: wqnwkozp 4e887f78 (empty) local-only
|
|
|
|
remote-delete (deleted)
|
|
|
|
@origin: mnmymoky 203e60eb (empty) remote-delete
|
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
|
|
|
remote-sync: zwtyzrop c761c7ea (empty) remote-sync
|
|
|
|
@origin: zwtyzrop c761c7ea (empty) remote-sync
|
|
|
|
remote-unsync: wqnwkozp 4e887f78 (empty) local-only
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
|
|
|
|
remote-untrack@origin: vmortlor 71a16b05 (empty) remote-untrack
|
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2023-06-28 02:53:01 +00:00
|
|
|
#[test]
|
|
|
|
fn test_branch_list_filtered_by_revset() {
|
|
|
|
let test_env = TestEnvironment::default();
|
cli: make set of immutable commits configurable
This adds a new `revset-aliases.immutable_heads()s` config for
defining the set of immutable commits. The set is defined as the
configured revset, as well as its ancestors, and the root commit
commit (even if the configured set is empty).
This patch also adds enforcement of the config where we already had
checks preventing rewrite of the root commit. The working-copy commit
is implicitly assumed to be writable in most cases. Specifically, we
won't prevent amending the working copy even if the user includes it
in the config but we do prevent `jj edit @` in that case. That seems
good enough to me. Maybe we should emit a warning when the working
copy is in the set of immutable commits.
Maybe we should add support for something more like [Mercurial's
phases](https://wiki.mercurial-scm.org/Phases), which is propagated on
push and pull. There's already some affordance for that in the view
object's `public_heads` field. However, this is simpler, especially
since we can't propagate the phase to Git remotes, and seems like a
good start. Also, it lets you say that commits authored by other users
are immutable, for example.
For now, the functionality is in the CLI library. I'm not sure if we
want to move it into the library crate. I'm leaning towards letting
library users do whatever they want without being restricted by
immutable commits. I do think we should move the functionality into a
future `ui-lib` or `ui-util` crate. That crate would have most of the
functionality in the current `cli_util` module (but in a
non-CLI-specific form).
2023-09-02 02:12:01 +00:00
|
|
|
test_env.add_config(r#"revset-aliases."immutable_heads()" = "none()""#);
|
2023-06-28 02:53:01 +00:00
|
|
|
|
|
|
|
// Initialize remote refs
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(test_env.env_root(), &["init", "remote", "--git"]);
|
2023-06-28 02:53:01 +00:00
|
|
|
let remote_path = test_env.env_root().join("remote");
|
|
|
|
for branch in ["remote-keep", "remote-delete", "remote-rewrite"] {
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&remote_path, &["new", "root()", "-m", branch]);
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["branch", "set", branch]);
|
2023-06-28 02:53:01 +00:00
|
|
|
}
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&remote_path, &["new"]);
|
|
|
|
test_env.jj_cmd_ok(&remote_path, &["git", "export"]);
|
2023-06-28 02:53:01 +00:00
|
|
|
|
|
|
|
// Initialize local refs
|
|
|
|
let mut remote_git_path = remote_path;
|
|
|
|
remote_git_path.extend([".jj", "repo", "store", "git"]);
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(
|
2023-06-28 02:53:01 +00:00
|
|
|
test_env.env_root(),
|
|
|
|
&["git", "clone", remote_git_path.to_str().unwrap(), "local"],
|
|
|
|
);
|
|
|
|
let local_path = test_env.env_root().join("local");
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&local_path, &["new", "root()", "-m", "local-keep"]);
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "set", "local-keep"]);
|
2023-06-28 02:53:01 +00:00
|
|
|
|
|
|
|
// Mutate refs in local repository
|
2023-10-10 11:59:18 +00:00
|
|
|
test_env.jj_cmd_ok(&local_path, &["branch", "delete", "remote-delete"]);
|
|
|
|
test_env.jj_cmd_ok(&local_path, &["describe", "-mrewritten", "remote-rewrite"]);
|
2023-06-28 02:53:01 +00:00
|
|
|
|
|
|
|
let template = r#"separate(" ", commit_id.short(), branches, if(hidden, "(hidden)"))"#;
|
|
|
|
insta::assert_snapshot!(
|
|
|
|
test_env.jj_cmd_success(
|
|
|
|
&local_path,
|
2023-07-28 00:33:54 +00:00
|
|
|
&["log", "-r::(branches() | remote_branches())", "-T", template],
|
2023-06-28 02:53:01 +00:00
|
|
|
),
|
|
|
|
@r###"
|
|
|
|
◉ e31634b64294 remote-rewrite*
|
|
|
|
│ @ c7b4c09cd77c local-keep
|
|
|
|
├─╯
|
|
|
|
│ ◉ 3e9a5af6ef15 remote-rewrite@origin (hidden)
|
|
|
|
├─╯
|
|
|
|
│ ◉ dad5f298ca57 remote-delete@origin
|
|
|
|
├─╯
|
index: import commits in chronological order
This basically means that heads in a filtered graph appear in reverse
chronological order. Before, "jj log -r 'tags()'" in linux-stable repo would
look randomly sorted once you ran "jj debug reindex" in it.
With this change, indexing is more like breadth-first search, and BFS is
known to be bad at rendering nice graph (because branches run in parallel.)
However, we have a post process to group topological branches, so we don't
have this problem. For serialization formats like Mercurial's revlog iirc,
BFS leads to bad compression ratio, but our index isn't that kind of data.
Reindexing gets slightly slower, but I think this is negligible.
(in Git repository)
% hyperfine --warmup 3 --runs 10 "jj debug reindex --ignore-working-copy"
(original)
Time (mean ± σ): 1.521 s ± 0.027 s [User: 1.307 s, System: 0.211 s]
Range (min … max): 1.486 s … 1.573 s 10 runs
(new)
Time (mean ± σ): 1.568 s ± 0.027 s [User: 1.368 s, System: 0.197 s]
Range (min … max): 1.531 s … 1.625 s 10 runs
Another idea is to sort heads chronologically and run DFS-based topological
sorting. It's ad-hoc, but worked surprisingly well for my local repositories.
For repositories with lots of long-running branches, this commit will provide
more predictable result than DFS-based one.
2023-08-12 10:32:05 +00:00
|
|
|
│ ◉ 911e912015fb remote-keep
|
|
|
|
├─╯
|
2023-06-28 02:53:01 +00:00
|
|
|
◉ 000000000000
|
|
|
|
"###);
|
|
|
|
|
|
|
|
// All branches are listed by default.
|
|
|
|
insta::assert_snapshot!(test_env.jj_cmd_success(&local_path, &["branch", "list"]), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
local-keep: kpqxywon c7b4c09c (empty) local-keep
|
2023-06-28 02:53:01 +00:00
|
|
|
remote-delete (deleted)
|
2023-07-11 01:46:38 +00:00
|
|
|
@origin: yxusvupt dad5f298 (empty) remote-delete
|
2023-06-28 02:53:01 +00:00
|
|
|
(this branch will be *deleted permanently* on the remote on the
|
|
|
|
next `jj git push`. Use `jj branch forget` to prevent this)
|
2023-07-11 01:46:38 +00:00
|
|
|
remote-keep: nlwprzpn 911e9120 (empty) remote-keep
|
|
|
|
remote-rewrite: xyxluytn e31634b6 (empty) rewritten
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): xyxluytn 3e9a5af6 (empty) remote-rewrite
|
2023-06-28 02:53:01 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
let query = |revset| test_env.jj_cmd_success(&local_path, &["branch", "list", "-r", revset]);
|
2023-07-02 00:59:34 +00:00
|
|
|
let query_error =
|
|
|
|
|revset| test_env.jj_cmd_failure(&local_path, &["branch", "list", "-r", revset]);
|
2023-06-28 02:53:01 +00:00
|
|
|
|
|
|
|
// "all()" doesn't include deleted branches since they have no local targets.
|
|
|
|
// So "all()" is identical to "branches()".
|
|
|
|
insta::assert_snapshot!(query("all()"), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
local-keep: kpqxywon c7b4c09c (empty) local-keep
|
|
|
|
remote-keep: nlwprzpn 911e9120 (empty) remote-keep
|
|
|
|
remote-rewrite: xyxluytn e31634b6 (empty) rewritten
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): xyxluytn 3e9a5af6 (empty) remote-rewrite
|
2023-06-28 02:53:01 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Exclude remote-only branches. "remote-rewrite@origin" is included since
|
|
|
|
// local "remote-rewrite" target matches.
|
|
|
|
insta::assert_snapshot!(query("branches()"), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
local-keep: kpqxywon c7b4c09c (empty) local-keep
|
|
|
|
remote-keep: nlwprzpn 911e9120 (empty) remote-keep
|
|
|
|
remote-rewrite: xyxluytn e31634b6 (empty) rewritten
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): xyxluytn 3e9a5af6 (empty) remote-rewrite
|
2023-06-28 02:53:01 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Select branches by name.
|
|
|
|
insta::assert_snapshot!(query("branches(remote-rewrite)"), @r###"
|
2023-07-11 01:46:38 +00:00
|
|
|
remote-rewrite: xyxluytn e31634b6 (empty) rewritten
|
|
|
|
@origin (ahead by 1 commits, behind by 1 commits): xyxluytn 3e9a5af6 (empty) remote-rewrite
|
2023-06-28 02:53:01 +00:00
|
|
|
"###);
|
|
|
|
|
|
|
|
// Can't select deleted branch.
|
2023-07-02 00:59:34 +00:00
|
|
|
insta::assert_snapshot!(query("branches(remote-delete)"), @r###"
|
|
|
|
"###);
|
|
|
|
insta::assert_snapshot!(query_error("remote-delete"), @r###"
|
|
|
|
Error: Revision "remote-delete" doesn't exist
|
2023-07-02 04:57:44 +00:00
|
|
|
Hint: Did you mean "remote-delete@origin", "remote-keep", "remote-rewrite", "remote-rewrite@origin"?
|
2023-06-28 02:53:01 +00:00
|
|
|
"###);
|
|
|
|
}
|
|
|
|
|
2022-05-02 19:58:32 +00:00
|
|
|
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
|
2023-02-28 11:30:57 +00:00
|
|
|
let template = r#"branches ++ " " ++ commit_id.short()"#;
|
2023-02-28 10:43:14 +00:00
|
|
|
test_env.jj_cmd_success(cwd, &["log", "-T", template])
|
2022-05-02 19:58:32 +00:00
|
|
|
}
|
2023-06-13 21:49:51 +00:00
|
|
|
|
|
|
|
fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {
|
2023-10-18 06:12:17 +00:00
|
|
|
test_env.jj_cmd_success(repo_path, &["branch", "list", "--all"])
|
2023-06-13 21:49:51 +00:00
|
|
|
}
|