Skip to content

Commit

Permalink
next/prev: Implement next/prev --conflict
Browse files Browse the repository at this point in the history
This allows users to jump to the next conflict in the ancestors or children of 
the start commit.

Continues work on #2126
  • Loading branch information
PhilipMetzger committed Mar 7, 2024
1 parent c3a41e2 commit 409b105
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ No code changes (fixing Rust `Cargo.toml` stuff).
* `ui.default-command` now accepts multiple string arguments, for more complex
default `jj` commands.

* `jj prev` and `jj next` have gained a `--conflict` flag which moves you
to the next conflict in a child commit.

### Fixed bugs

* On Windows, symlinks in the repo are now supported when Developer Mode is enabled.
Expand Down
11 changes: 10 additions & 1 deletion cli/src/commands/next.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub(crate) struct NextArgs {
/// edit`).
#[arg(long)]
edit: bool,
/// Jump to the next conflicted descendant.
#[arg(long, conflicts_with = "amount")]
conflict: bool,
}

pub fn choose_commit<'a>(
Expand Down Expand Up @@ -113,6 +116,7 @@ pub(crate) fn cmd_next(
.view()
.heads()
.contains(current_wc_id);
let conflict = args.conflict;
let current_wc = workspace_command.repo().store().get_commit(current_wc_id)?;
// If we're editing, start at the working-copy commit.
// Otherwise start from our direct parent.
Expand All @@ -124,7 +128,12 @@ pub(crate) fn cmd_next(
_ => return Err(user_error("Cannot run `jj next` on a merge commit")),
}
};
let descendant_expression = RevsetExpression::commit(start_id.clone()).descendants_at(amount);
let base_expr = RevsetExpression::commit(start_id.clone());
let descendant_expression = if conflict {
base_expr.descendants().conflicts()
} else {
base_expr.descendants_at(amount)
};
let target_expression = if edit {
descendant_expression
} else {
Expand Down
11 changes: 10 additions & 1 deletion cli/src/commands/prev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub(crate) struct PrevArgs {
/// Edit the parent directly, instead of moving the working-copy commit.
#[arg(long)]
edit: bool,
/// Jump to nearest the conflicted ancestor.
#[arg(long, conflicts_with = "amount")]
conflict: bool,
}

pub(crate) fn cmd_prev(
Expand All @@ -68,6 +71,7 @@ pub(crate) fn cmd_prev(
) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let amount = args.amount;
let conflict = args.conflict;
let current_wc_id = workspace_command
.get_wc_commit_id()
.ok_or_else(|| user_error("This command requires a working copy"))?;
Expand All @@ -86,7 +90,12 @@ pub(crate) fn cmd_prev(
_ => return Err(user_error("Cannot run `jj prev` on a merge commit")),
}
};
let ancestor_expression = RevsetExpression::commit(start_id.clone()).ancestors_at(amount);
let base_expr = RevsetExpression::commit(start_id.clone());
let ancestor_expression = if conflict {
base_expr.ancestors().conflicts()
} else {
base_expr.ancestors_at(amount)
};
let target_revset = if edit {
ancestor_expression
} else {
Expand Down
8 changes: 8 additions & 0 deletions cli/tests/cli-reference@.md.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,10 @@ implied.
Possible values: `true`, `false`
* `--conflict` — Jump to the next conflicted descendant
Possible values: `true`, `false`
Expand Down Expand Up @@ -1385,6 +1389,10 @@ implied.
Possible values: `true`, `false`
* `--conflict` — Jump to nearest the conflicted ancestor
Possible values: `true`, `false`
Expand Down
52 changes: 52 additions & 0 deletions cli/tests/test_next_prev_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,55 @@ fn test_next_editing() {
Parent commit : kkmpptxz 3fa8931e (empty) third
"###);
}

// #[test]
// fn test_prev_conflict() {
// // Edit the third commit.
// 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");
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "first"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "second"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "third"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "fourth"]);
// let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["prev", "--conflict"]);
// insta::assert_snapshot!(stdout, @"");
// insta::assert_snapshot!(stderr, @r###"
// Working copy now at: zsuskuln 009f88bf (empty) fourth
// Parent commit : kkmpptxz 3fa8931e (empty) third
// "###);
// // --edit is implied when already editing a non-head commit
// let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["prev"]);
// insta::assert_snapshot!(stdout, @"");
// insta::assert_snapshot!(stderr, @r###"
// Working copy now at: yqosqzyt d2edc95b (empty) (no description set)
// Parent commit : rlvkpnrz 5c52832c (empty) second
// "###);
// }

// #[test]
// fn test_next_conflict() {
// // There is a conflict in the fourth commit, so after next we should create a
// // new revision on top of it.
// 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");
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "first"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "second"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "third"]);
// test_env.jj_cmd_ok(&repo_path, &["commit", "-m", "fourth"]);
// test_env.jj_cmd_ok(&repo_path, &["edit", "@---"]);
// let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["next", "--conflict"]);
// insta::assert_snapshot!(stdout, @"");
// insta::assert_snapshot!(stderr, @r###"
// Working copy now at: kkmpptxz 3fa8931e (empty) third
// Parent commit : rlvkpnrz 5c52832c (empty) second
// "###);
// // --edit is implied when already editing a non-head commit
// let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["next"]);
// insta::assert_snapshot!(stdout, @"");
// insta::assert_snapshot!(stderr, @r###"
// Working copy now at: zsuskuln 009f88bf (empty) fourth
// Parent commit : kkmpptxz 3fa8931e (empty) third
// "###);
// }

0 comments on commit 409b105

Please sign in to comment.