diff --git a/cli/src/cli_util.rs b/cli/src/cli_util.rs index 221c90e0de..83f8d1f738 100644 --- a/cli/src/cli_util.rs +++ b/cli/src/cli_util.rs @@ -1580,7 +1580,63 @@ See https://github.com/martinvonz/jj/blob/main/docs/working-copy.md#stale-workin } } - // TODO: Hint about doing `jj new `. + // Hint that the user might want to `jj new` to the first conflict commit to + // resolve conflicts. Only show the hints if there were any new or resolved + // conflicts, and only if there are still some conflicts. + if !(added_conflict_commits.is_empty() + || resolved_conflicts_by_change_id.is_empty() && new_conflicts_by_change_id.is_empty()) + { + // If the user just resolved some conflict and squashed them in, there won't be + // any new conflicts. Clarify to them that there are still some other conflicts + // to resolve. (We don't mention conflicts in commits that weren't affected by + // the operation, however.) + if new_conflicts_by_change_id.is_empty() { + writeln!( + fmt, + "There are still unresolved conflicts in rebased descendants.", + )?; + } + let root_conflicts_revset = RevsetExpression::commits( + added_conflict_commits + .iter() + .map(|commit| commit.id().clone()) + .collect(), + ) + .roots() + .evaluate_programmatic(new_repo)?; + + let root_conflict_commits: Vec<_> = root_conflicts_revset + .iter() + .commits(new_repo.store()) + .try_collect()?; + if !root_conflict_commits.is_empty() { + fmt.push_label("hint")?; + if added_conflict_commits.len() == 1 { + writeln!(fmt, "To resolve the conflicts, start by updating to it:",)?; + } else if root_conflict_commits.len() == 1 { + writeln!( + fmt, + "To resolve the conflicts, start by updating to the first one:", + )?; + } else { + writeln!( + fmt, + "To resolve the conflicts, start by updating to one of the first ones:", + )?; + } + for commit in root_conflict_commits { + writeln!(fmt, " jj new {}", short_change_hash(commit.change_id()))?; + } + writeln!( + fmt, + r#"Then use `jj resolve`, or edit the conflict markers in the file directly. +Once the conflicts are resolved, you may want inspect the result with `jj diff`. +Then run `jj squash` to move the resolution into the conflicted commit."#, + )?; + fmt.pop_label()?; + } + } + Ok(()) } } diff --git a/cli/tests/test_chmod_command.rs b/cli/tests/test_chmod_command.rs index 64875b6e92..eab255e2a2 100644 --- a/cli/tests/test_chmod_command.rs +++ b/cli/tests/test_chmod_command.rs @@ -227,6 +227,11 @@ fn test_chmod_file_dir_deletion_conflicts() { insta::assert_snapshot!(stderr, @r###" New conflicts appeared in these commits: kmkuslsw 4cc432b5 file_deletion | (conflict) file_deletion + To resolve the conflicts, start by updating to it: + jj new kmkuslswpqwq + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: kmkuslsw 4cc432b5 file_deletion | (conflict) file_deletion Parent commit : zsuskuln c51c9c55 file | file Parent commit : royxmykx 6b18b3c1 deletion | deletion diff --git a/cli/tests/test_repo_change_report.rs b/cli/tests/test_repo_change_report.rs index e6f7b32e3e..6c07628222 100644 --- a/cli/tests/test_repo_change_report.rs +++ b/cli/tests/test_repo_change_report.rs @@ -37,6 +37,11 @@ fn test_report_conflicts() { New conflicts appeared in these commits: kkmpptxz a2593769 (conflict) C rlvkpnrz 727244df (conflict) B + To resolve the conflicts, start by updating to the first one: + jj new rlvkpnrzqnoo + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: zsuskuln 30928080 (conflict) (empty) (no description set) Parent commit : kkmpptxz a2593769 (conflict) C Added 0 files, modified 1 files, removed 0 files @@ -53,6 +58,44 @@ fn test_report_conflicts() { Parent commit : kkmpptxz ed071401 C Added 0 files, modified 1 files, removed 0 files "###); + + // Can get hint about multiple root commits + let (stdout, stderr) = + test_env.jj_cmd_ok(&repo_path, &["rebase", "-r=description(B)", "-d=root()"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r###" + Also rebased 2 descendant commits onto parent of rebased commit + New conflicts appeared in these commits: + rlvkpnrz 9df65f08 (conflict) B + kkmpptxz 7530822d (conflict) C + To resolve the conflicts, start by updating to one of the first ones: + jj new rlvkpnrzqnoo + jj new kkmpptxzrspx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. + Working copy now at: zsuskuln 203be58b (conflict) (empty) (no description set) + Parent commit : kkmpptxz 7530822d (conflict) C + Added 0 files, modified 1 files, removed 0 files + "###); + + // Resolve one of the conflicts by (mostly) following the instructions + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["new", "rlvkpnrzqnoo"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r###" + Working copy now at: vruxwmqv 406f84d0 (conflict) (empty) (no description set) + Parent commit : rlvkpnrz 9df65f08 (conflict) B + Added 0 files, modified 1 files, removed 0 files + "###); + std::fs::write(repo_path.join("file"), "resolved\n").unwrap(); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["squash"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r###" + Existing conflicts were resolved or abandoned from these commits: + rlvkpnrz hidden 9df65f08 (conflict) B + Working copy now at: yostqsxw 8e160bc4 (empty) (no description set) + Parent commit : rlvkpnrz c5319490 B + "###); } #[test] @@ -80,6 +123,11 @@ fn test_report_conflicts_with_divergent_commits() { zsuskuln?? 76c40a95 (conflict) C3 zsuskuln?? e92329f2 (conflict) C2 kkmpptxz aed319ec (conflict) B + To resolve the conflicts, start by updating to the first one: + jj new kkmpptxzrspx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: zsuskuln?? e92329f2 (conflict) C2 Parent commit : kkmpptxz aed319ec (conflict) B Added 0 files, modified 1 files, removed 0 files @@ -106,6 +154,11 @@ fn test_report_conflicts_with_divergent_commits() { Rebased 1 commits New conflicts appeared in these commits: zsuskuln?? 0d6cb6b7 (conflict) C2 + To resolve the conflicts, start by updating to it: + jj new zsuskulnrvyr + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: zsuskuln?? 0d6cb6b7 (conflict) C2 Parent commit : zzzzzzzz 00000000 (empty) (no description set) Added 0 files, modified 1 files, removed 0 files @@ -118,6 +171,11 @@ fn test_report_conflicts_with_divergent_commits() { Rebased 1 commits New conflicts appeared in these commits: zsuskuln?? 9652a362 (conflict) C3 + To resolve the conflicts, start by updating to it: + jj new zsuskulnrvyr + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. "###); let (stdout, stderr) = test_env.jj_cmd_ok( diff --git a/cli/tests/test_resolve_command.rs b/cli/tests/test_resolve_command.rs index 069d7c035e..ae191e9b34 100644 --- a/cli/tests/test_resolve_command.rs +++ b/cli/tests/test_resolve_command.rs @@ -186,6 +186,11 @@ conflict insta::assert_snapshot!(stderr, @r###" New conflicts appeared in these commits: vruxwmqv ff4e8c6b conflict | (conflict) conflict + To resolve the conflicts, start by updating to it: + jj new vruxwmqvtpmx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: vruxwmqv ff4e8c6b conflict | (conflict) conflict Parent commit : zsuskuln aa493daf a | a Parent commit : royxmykx db6a4daf b | b @@ -639,6 +644,11 @@ fn test_multiple_conflicts() { insta::assert_snapshot!(stderr, @r###" New conflicts appeared in these commits: vruxwmqv c3c25bce conflict | (conflict) conflict + To resolve the conflicts, start by updating to it: + jj new vruxwmqvtpmx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: vruxwmqv c3c25bce conflict | (conflict) conflict Parent commit : zsuskuln de7553ef a | a Parent commit : royxmykx f68bc2f0 b | b @@ -670,6 +680,11 @@ fn test_multiple_conflicts() { insta::assert_snapshot!(stderr, @r###" New conflicts appeared in these commits: vruxwmqv fd3874cd conflict | (conflict) conflict + To resolve the conflicts, start by updating to it: + jj new vruxwmqvtpmx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: vruxwmqv fd3874cd conflict | (conflict) conflict Parent commit : zsuskuln de7553ef a | a Parent commit : royxmykx f68bc2f0 b | b diff --git a/cli/tests/test_restore_command.rs b/cli/tests/test_restore_command.rs index 335ca8213e..ed99ad1379 100644 --- a/cli/tests/test_restore_command.rs +++ b/cli/tests/test_restore_command.rs @@ -65,6 +65,11 @@ fn test_restore() { Rebased 1 descendant commits New conflicts appeared in these commits: kkmpptxz e301deb3 (conflict) (no description set) + To resolve the conflicts, start by updating to it: + jj new kkmpptxzrspx + Then use `jj resolve`, or edit the conflict markers in the file directly. + Once the conflicts are resolved, you may want inspect the result with `jj diff`. + Then run `jj squash` to move the resolution into the conflicted commit. Working copy now at: kkmpptxz e301deb3 (conflict) (no description set) Parent commit : rlvkpnrz e25100af (empty) (no description set) Added 0 files, modified 1 files, removed 0 files