diff --git a/CHANGELOG.md b/CHANGELOG.md index 6def871dc..c5c7a8af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * The `jj touchup` command was renamed to `jj diffedit`. +* The `-i` option to `jj restore` was removed in favor of new `--from`/`--to` + options to `jj diffedit`. + ### New features * The default log format now uses the committer timestamp instead of the author diff --git a/docs/tutorial.md b/docs/tutorial.md index 25c235137..4b2f56001 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -393,7 +393,7 @@ Unlike `jj squash -i`, which left the content state of the commit unchanged, `jj diffedit` (typically) results in a different state, which means that descendant commits may have conflicts. -Other commands for rewriting contents of existing commits are `jj restore -i`, -`jj split`, `jj unsquash -i`. Now that you've seen how `jj squash -i` and -`jj diffedit` work, you can hopefully figure out how those work (with the help of +Other commands for rewriting contents of existing commits are `jj split`, `jj +unsquash -i` and `jj move -i`. Now that you've seen how `jj squash -i` and `jj +diffedit` work, you can hopefully figure out how those work (with the help of the instructions in the diff). diff --git a/src/commands.rs b/src/commands.rs index 6c47f4b52..08749c318 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -521,6 +521,9 @@ struct ResolveArgs { /// When neither `--from` nor `--to` is specified, the command restores into the /// working copy from its parent. If one of `--from` or `--to` is specified, the /// other one defaults to the working copy. +/// +/// See `jj diffedit` if you'd like to restore portions of files rather than +/// entire files. #[derive(clap::Args, Clone, Debug)] struct RestoreArgs { /// Revision to restore from (source) @@ -529,11 +532,8 @@ struct RestoreArgs { /// Revision to restore into (destination) #[arg(long)] to: Option, - /// Interactively choose which parts to restore - #[arg(long, short)] - interactive: bool, /// Restore only these paths (instead of all paths) - #[arg(conflicts_with = "interactive", value_hint = clap::ValueHint::AnyPath)] + #[arg(value_hint = clap::ValueHint::AnyPath)] paths: Vec, } @@ -2351,30 +2351,9 @@ fn cmd_restore( let from_commit = workspace_command.resolve_single_rev(from_str)?; let to_commit = workspace_command.resolve_single_rev(to_str)?; workspace_command.check_rewriteable(&to_commit)?; - let tree_id; - if args.interactive { - let instructions = format!( - "\ -You are restoring state from: {} -into: {} - -The left side of the diff shows the contents of the commit you're -restoring from. The right side initially shows the contents of the -commit you're restoring into. - -Adjust the right side until it has the changes you wanted from the left -side. If you don't make any changes, then the operation will be aborted. -", - short_commit_description(&from_commit), - short_commit_description(&to_commit) - ); - tree_id = workspace_command.edit_diff( - ui, - &from_commit.tree(), - &to_commit.tree(), - &instructions, - )?; - } else if !args.paths.is_empty() { + let tree_id = if args.paths.is_empty() { + from_commit.tree_id().clone() + } else { let matcher = workspace_command.matcher_from_values(&args.paths)?; let mut tree_builder = workspace_command .repo() @@ -2390,10 +2369,8 @@ side. If you don't make any changes, then the operation will be aborted. } } } - tree_id = tree_builder.write_tree(); - } else { - tree_id = from_commit.tree_id().clone(); - } + tree_builder.write_tree() + }; if &tree_id == to_commit.tree_id() { ui.write("Nothing changed.\n")?; } else { diff --git a/tests/test_restore_command.rs b/tests/test_restore_command.rs index be3378e88..abacede13 100644 --- a/tests/test_restore_command.rs +++ b/tests/test_restore_command.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use regex::Regex; - use crate::common::TestEnvironment; pub mod common; @@ -102,104 +100,3 @@ fn test_restore() { R file1 "###); } - -#[test] -fn test_restore_interactive() { - let mut test_env = TestEnvironment::default(); - test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); - let repo_path = test_env.env_root().join("repo"); - - std::fs::write(repo_path.join("file1"), "a\n").unwrap(); - std::fs::write(repo_path.join("file2"), "a\n").unwrap(); - test_env.jj_cmd_success(&repo_path, &["new"]); - std::fs::remove_file(repo_path.join("file1")).unwrap(); - std::fs::write(repo_path.join("file2"), "b\n").unwrap(); - std::fs::write(repo_path.join("file3"), "b\n").unwrap(); - - let edit_script = test_env.set_up_fake_diff_editor(); - - // Nothing happens if we make no changes - std::fs::write(&edit_script, "").unwrap(); - let stdout = test_env.jj_cmd_success(&repo_path, &["restore", "-i"]); - insta::assert_snapshot!(stdout, @r###" - Nothing changed. - "###); - let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); - insta::assert_snapshot!(stdout, @r###" - R file1 - M file2 - A file3 - "###); - - // Nothing happens if the diff-editor exits with an error - std::fs::write(&edit_script, "rm file2\0fail").unwrap(); - let stderr = test_env.jj_cmd_failure(&repo_path, &["restore", "-i"]); - insta::assert_snapshot!(Regex::new(r"Details: [^\n]+").unwrap().replace(&stderr, "Details: "), @r###" - Error: Failed to edit diff: Tool exited with a non-zero code. - Details: - "###); - let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); - insta::assert_snapshot!(stdout, @r###" - R file1 - M file2 - A file3 - "###); - - // Can restore changes to individual files - std::fs::write(&edit_script, "reset file2\0reset file3").unwrap(); - let stdout = test_env.jj_cmd_success(&repo_path, &["restore", "-i"]); - insta::assert_snapshot!(stdout, @r###" - Created abdbf6271a1c (no description set) - Working copy now at: abdbf6271a1c (no description set) - Added 0 files, modified 1 files, removed 1 files - "###); - let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); - insta::assert_snapshot!(stdout, @r###" - R file1 - "###); - - // Can make unrelated edits - test_env.jj_cmd_success(&repo_path, &["undo"]); - std::fs::write(&edit_script, "write file3\nunrelated\n").unwrap(); - let stdout = test_env.jj_cmd_success(&repo_path, &["restore", "-i"]); - insta::assert_snapshot!(stdout, @r###" - Created e31f7f33ad07 (no description set) - Working copy now at: e31f7f33ad07 (no description set) - Added 0 files, modified 1 files, removed 0 files - "###); - let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]); - insta::assert_snapshot!(stdout, @r###" - diff --git a/file1 b/file1 - deleted file mode 100644 - index 7898192261..0000000000 - --- a/file1 - +++ /dev/null - @@ -1,1 +1,0 @@ - -a - diff --git a/file2 b/file2 - index 7898192261...6178079822 100644 - --- a/file2 - +++ b/file2 - @@ -1,1 +1,1 @@ - -a - +b - diff --git a/file3 b/file3 - new file mode 100644 - index 0000000000..c21c9352f7 - --- /dev/null - +++ b/file3 - @@ -1,0 +1,1 @@ - +unrelated - "###); - - // Combining paths with -i is not yet supported - std::fs::write(&edit_script, "").unwrap(); - let stderr = test_env.jj_cmd_cli_error(&repo_path, &["restore", "-i", "file2"]); - insta::assert_snapshot!(stderr, @r###" - error: The argument '--interactive' cannot be used with '[PATHS]...' - - Usage: jj restore --interactive [PATHS]... - - For more information try '--help' - "###); -} diff --git a/tests/test_touchup_command.rs b/tests/test_touchup_command.rs index 732b78a84..46494bd11 100644 --- a/tests/test_touchup_command.rs +++ b/tests/test_touchup_command.rs @@ -171,3 +171,93 @@ fn test_diffedit_merge() { >>>>>>> "###); } + +#[test] +fn test_diffedit_old_restore_interactive_tests() { + let mut test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + + std::fs::write(repo_path.join("file1"), "a\n").unwrap(); + std::fs::write(repo_path.join("file2"), "a\n").unwrap(); + test_env.jj_cmd_success(&repo_path, &["new"]); + std::fs::remove_file(repo_path.join("file1")).unwrap(); + std::fs::write(repo_path.join("file2"), "b\n").unwrap(); + std::fs::write(repo_path.join("file3"), "b\n").unwrap(); + + let edit_script = test_env.set_up_fake_diff_editor(); + + // Nothing happens if we make no changes + std::fs::write(&edit_script, "").unwrap(); + let stdout = test_env.jj_cmd_success(&repo_path, &["diffedit", "--from", "@-"]); + insta::assert_snapshot!(stdout, @r###" + Nothing changed. + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); + insta::assert_snapshot!(stdout, @r###" + R file1 + M file2 + A file3 + "###); + + // Nothing happens if the diff-editor exits with an error + std::fs::write(&edit_script, "rm file2\0fail").unwrap(); + let stderr = test_env.jj_cmd_failure(&repo_path, &["diffedit", "--from", "@-"]); + insta::assert_snapshot!(Regex::new(r"Details: [^\n]+").unwrap().replace(&stderr, "Details: "), @r###" + Error: Failed to edit diff: Tool exited with a non-zero code. + Details: + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); + insta::assert_snapshot!(stdout, @r###" + R file1 + M file2 + A file3 + "###); + + // Can restore changes to individual files + std::fs::write(&edit_script, "reset file2\0reset file3").unwrap(); + let stdout = test_env.jj_cmd_success(&repo_path, &["diffedit", "--from", "@-"]); + insta::assert_snapshot!(stdout, @r###" + Created abdbf6271a1c (no description set) + Working copy now at: abdbf6271a1c (no description set) + Added 0 files, modified 1 files, removed 1 files + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]); + insta::assert_snapshot!(stdout, @r###" + R file1 + "###); + + // Can make unrelated edits + test_env.jj_cmd_success(&repo_path, &["undo"]); + std::fs::write(&edit_script, "write file3\nunrelated\n").unwrap(); + let stdout = test_env.jj_cmd_success(&repo_path, &["diffedit", "--from", "@-"]); + insta::assert_snapshot!(stdout, @r###" + Created e31f7f33ad07 (no description set) + Working copy now at: e31f7f33ad07 (no description set) + Added 0 files, modified 1 files, removed 0 files + "###); + let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]); + insta::assert_snapshot!(stdout, @r###" + diff --git a/file1 b/file1 + deleted file mode 100644 + index 7898192261..0000000000 + --- a/file1 + +++ /dev/null + @@ -1,1 +1,0 @@ + -a + diff --git a/file2 b/file2 + index 7898192261...6178079822 100644 + --- a/file2 + +++ b/file2 + @@ -1,1 +1,1 @@ + -a + +b + diff --git a/file3 b/file3 + new file mode 100644 + index 0000000000..c21c9352f7 + --- /dev/null + +++ b/file3 + @@ -1,0 +1,1 @@ + +unrelated + "###); +}