forked from mirrors/jj
Implement advance-branches for jj new
This commit is contained in:
parent
4e83afd06b
commit
8a218d2d7c
2 changed files with 154 additions and 4 deletions
|
@ -23,7 +23,8 @@ use jj_lib::rewrite::{merge_commit_trees, rebase_commit};
|
|||
use tracing::instrument;
|
||||
|
||||
use crate::cli_util::{
|
||||
resolve_multiple_nonempty_revsets_default_single, short_commit_hash, CommandHelper, RevisionArg,
|
||||
resolve_multiple_nonempty_revsets_default_single, short_commit_hash, AdvanceableBranch,
|
||||
CommandHelper, RevisionArg, WorkspaceCommandHelper,
|
||||
};
|
||||
use crate::command_error::{user_error, CommandError};
|
||||
use crate::description_util::join_message_paragraphs;
|
||||
|
@ -101,6 +102,7 @@ Please use `jj new 'all:x|y'` instead of `jj new --allow-large-revsets x y`.",
|
|||
.into_iter()
|
||||
.collect_vec();
|
||||
let target_ids = target_commits.iter().map(|c| c.id().clone()).collect_vec();
|
||||
let advanceable_branches = get_advanceable_branches(args, &workspace_command, &target_commits)?;
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
let mut num_rebased;
|
||||
let new_commit;
|
||||
|
@ -138,11 +140,11 @@ Please use `jj new 'all:x|y'` instead of `jj new --allow-large-revsets x y`.",
|
|||
.set_description(join_message_paragraphs(&args.message_paragraphs))
|
||||
.write()?;
|
||||
num_rebased = target_ids.len();
|
||||
for child_commit in target_commits {
|
||||
for child_commit in &target_commits {
|
||||
rebase_commit(
|
||||
command.settings(),
|
||||
tx.mut_repo(),
|
||||
&child_commit,
|
||||
child_commit,
|
||||
&[new_commit.clone()],
|
||||
)?;
|
||||
}
|
||||
|
@ -199,6 +201,26 @@ Please use `jj new 'all:x|y'` instead of `jj new --allow-large-revsets x y`.",
|
|||
if num_rebased > 0 {
|
||||
writeln!(ui.stderr(), "Rebased {num_rebased} descendant commits")?;
|
||||
}
|
||||
|
||||
// Does nothing if there's no branches to advance.
|
||||
tx.advance_branches(advanceable_branches, target_commits[0].id());
|
||||
|
||||
tx.finish(ui, "new empty commit")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Branches are only advanced if `jj new` has a single target commit and the
|
||||
// new commit is not being inserted before or after the target.
|
||||
fn get_advanceable_branches(
|
||||
args: &NewArgs,
|
||||
ws: &WorkspaceCommandHelper,
|
||||
target_commits: &[Commit],
|
||||
) -> Result<Vec<AdvanceableBranch>, CommandError> {
|
||||
let should_advance_branches =
|
||||
target_commits.len() == 1 && !args.insert_before && !args.insert_after;
|
||||
if should_advance_branches {
|
||||
ws.get_advanceable_branches(target_commits[0].parent_ids())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ fn set_advance_branches(test_env: &TestEnvironment, enabled: bool) {
|
|||
} else {
|
||||
test_env.add_config(
|
||||
r#"[experimental-advance-branches]
|
||||
enabled-branches = [""]
|
||||
enabled-branches = []
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -37,8 +37,15 @@ fn commit_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str
|
|||
env.jj_cmd_ok(workspace_path, &["commit", "-m", commit_message]);
|
||||
}
|
||||
|
||||
// Implements CommitFn using the `jj describe` and `jj new`.
|
||||
fn describe_new_cmd(env: &TestEnvironment, workspace_path: &Path, commit_message: &str) {
|
||||
env.jj_cmd_ok(workspace_path, &["describe", "-m", commit_message]);
|
||||
env.jj_cmd_ok(workspace_path, &["new"]);
|
||||
}
|
||||
|
||||
// Check that enabling and disabling advance-branches works as expected.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_enabled(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
|
@ -86,6 +93,7 @@ fn test_advance_branches_enabled(make_commit: CommitFn) {
|
|||
// Check that only a branch pointing to @- advances. Branches pointing to @ are
|
||||
// not advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_at_minus(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
|
@ -127,6 +135,7 @@ fn test_advance_branches_at_minus(make_commit: CommitFn) {
|
|||
// Test that per-branch overrides invert the behavior of
|
||||
// experimental-advance-branches.enabled.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_overrides(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
|
@ -237,6 +246,7 @@ fn test_advance_branches_overrides(make_commit: CommitFn) {
|
|||
|
||||
// If multiple eligible branches point to @-, all of them will be advanced.
|
||||
#[test_case(commit_cmd ; "commit")]
|
||||
#[test_case(describe_new_cmd; "new")]
|
||||
fn test_advance_branches_multiple_branches(make_commit: CommitFn) {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
|
@ -270,3 +280,121 @@ fn test_advance_branches_multiple_branches(make_commit: CommitFn) {
|
|||
"###);
|
||||
}
|
||||
}
|
||||
|
||||
// Call `jj new` on an interior commit and see that the branch pointing to its
|
||||
// parent's parent is advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_interior() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// First, test with advance-branches enabled. Start by creating a branch on the
|
||||
// root commit.
|
||||
set_advance_branches(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@---", "test_branch"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc: third
|
||||
◉ branches{} desc: second
|
||||
◉ branches{test_branch} desc: first
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "-r", "@--"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
│ ◉ branches{} desc: third
|
||||
├─╯
|
||||
◉ branches{test_branch} desc: second
|
||||
◉ branches{} desc: first
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--before` flag is passed to `jj new`, branches are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_before() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// First, test with advance-branches enabled. Start by creating a branch on the
|
||||
// root commit.
|
||||
set_advance_branches(&test_env, true);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
|
||||
// Create a gap in the commits for us to insert our new commit with --before.
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "second"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["commit", "-m", "third"]);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@---", "test_branch"],
|
||||
);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc: third
|
||||
◉ branches{} desc: second
|
||||
◉ branches{test_branch} desc: first
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--before", "-r", "@-"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
◉ branches{} desc: third
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc: second
|
||||
◉ branches{test_branch} desc: first
|
||||
◉ branches{} desc:
|
||||
"###);
|
||||
}
|
||||
|
||||
// If the `--after` flag is passed to `jj new`, branches are not advanced.
|
||||
#[test]
|
||||
fn test_new_advance_branches_after() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
|
||||
// First, test with advance-branches enabled. Start by creating a branch on the
|
||||
// root commit.
|
||||
set_advance_branches(&test_env, true);
|
||||
test_env.jj_cmd_ok(
|
||||
&workspace_path,
|
||||
&["branch", "create", "-r", "@-", "test_branch"],
|
||||
);
|
||||
|
||||
// Check the initial state of the repo.
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{test_branch} desc:
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&workspace_path, &["describe", "-m", "first"]);
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new", "--after"]);
|
||||
insta::assert_snapshot!(get_log_output_with_branches(&test_env, &workspace_path), @r###"
|
||||
@ branches{} desc:
|
||||
◉ branches{} desc: first
|
||||
◉ branches{test_branch} desc:
|
||||
"###);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue