ok/jj
1
0
Fork 0
forked from mirrors/jj

diffedit: add --restore-descendants flag

This commit is contained in:
Samuel Tardieu 2024-09-17 08:11:21 +02:00
parent 90280ad2fd
commit f76ee1872f
5 changed files with 69 additions and 5 deletions

View file

@ -69,6 +69,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
* `jj commit` and `jj describe` now accept `--author` option allowing to quickly change
author of given commit.
* `jj diffedit` now accepts a `--restore-descendants` flag. When used,
descendants of the edited commit will keep their original content.
### Fixed bugs
* Update working copy before reporting changes. This prevents errors during reporting

View file

@ -38,8 +38,8 @@ use crate::ui::Ui;
///
/// Edit the right side of the diff until it looks the way you want. Once you
/// close the editor, the revision specified with `-r` or `--to` will be
/// updated. Descendants will be rebased on top as usual, which may result in
/// conflicts.
/// updated. Unless `--restore-descendants` is used, descendants will be
/// rebased on top as usual, which may result in conflicts.
///
/// See `jj restore` if you want to move entire files from one revision to
/// another. See `jj squash -i` or `jj unsquash -i` if you instead want to move
@ -64,6 +64,14 @@ pub(crate) struct DiffeditArgs {
/// Specify diff editor to be used
#[arg(long, value_name = "NAME")]
tool: Option<String>,
/// Preserve the content (not the diff) when rebasing descendants
///
/// When rebasing a descendant on top of the rewritten revision, its diff
/// compared to its parent(s) is normally preserved, i.e. the same way that
/// descendants are always rebased. This flag makes it so the content/state
/// is preserved instead of preserving the diff.
#[arg(long)]
restore_descendants: bool,
}
#[instrument(skip_all)]
@ -119,13 +127,23 @@ don't make any changes, then the operation will be aborted.",
.write()?;
// rebase_descendants early; otherwise `new_commit` would always have
// a conflicted change id at this point.
let num_rebased = tx.repo_mut().rebase_descendants(command.settings())?;
let (num_rebased, extra_msg) = if args.restore_descendants {
(
tx.repo_mut().reparent_descendants(command.settings())?,
" (while preserving their content)",
)
} else {
(tx.repo_mut().rebase_descendants(command.settings())?, "")
};
if let Some(mut formatter) = ui.status_formatter() {
write!(formatter, "Created ")?;
tx.write_commit_summary(formatter.as_mut(), &new_commit)?;
writeln!(formatter)?;
if num_rebased > 0 {
writeln!(formatter, "Rebased {num_rebased} descendant commits")?;
writeln!(
formatter,
"Rebased {num_rebased} descendant commits{extra_msg}"
)?;
}
}
tx.finish(ui, format!("edit commit {}", target_commit.id().hex()))?;

View file

@ -655,7 +655,7 @@ With the `--from` and/or `--to` options, starts a [diff editor] comparing the "f
[diff editor]: https://martinvonz.github.io/jj/latest/config/#editing-diffs
Edit the right side of the diff until it looks the way you want. Once you close the editor, the revision specified with `-r` or `--to` will be updated. Descendants will be rebased on top as usual, which may result in conflicts.
Edit the right side of the diff until it looks the way you want. Once you close the editor, the revision specified with `-r` or `--to` will be updated. Unless `--restore-descendants` is used, descendants will be rebased on top as usual, which may result in conflicts.
See `jj restore` if you want to move entire files from one revision to another. See `jj squash -i` or `jj unsquash -i` if you instead want to move changes into or out of the parent revision.
@ -673,6 +673,9 @@ See `jj restore` if you want to move entire files from one revision to another.
Defaults to @ if --from is specified.
* `--tool <NAME>` — Specify diff editor to be used
* `--restore-descendants` — Preserve the content (not the diff) when rebasing descendants
When rebasing a descendant on top of the rewritten revision, its diff compared to its parent(s) is normally preserved, i.e. the same way that descendants are always rebased. This flag makes it so the content/state is preserved instead of preserving the diff.

View file

@ -514,3 +514,42 @@ fn test_diffedit_old_restore_interactive_tests() {
+unrelated
"###);
}
#[test]
fn test_diffedit_restore_descendants() {
let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");
std::fs::write(repo_path.join("file"), "println!(\"foo\")\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file"), "println!(\"bar\")\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file"), "println!(\"baz\");\n").unwrap();
let edit_script = test_env.set_up_fake_diff_editor();
// Add a ";" after the line with "bar". There should be no conflict.
std::fs::write(edit_script, "write file\nprintln!(\"bar\");\n").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(
&repo_path,
&["diffedit", "-r", "@-", "--restore-descendants"],
);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r#"
Created rlvkpnrz 62b8c2ce (no description set)
Rebased 1 descendant commits (while preserving their content)
Working copy now at: kkmpptxz 321d1cd1 (no description set)
Parent commit : rlvkpnrz 62b8c2ce (no description set)
"#);
let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git"]);
insta::assert_snapshot!(stdout, @r#"
diff --git a/file b/file
index 1a598a8fc9..7b6a85ab5a 100644
--- a/file
+++ b/file
@@ -1,1 +1,1 @@
-println!("bar");
+println!("baz");
"#);
}

View file

@ -602,6 +602,7 @@ fn test_help() {
--from <FROM> Show changes from this revision
--to <TO> Edit changes in this revision
--tool <NAME> Specify diff editor to be used
--restore-descendants Preserve the content (not the diff) when rebasing descendants
-h, --help Print help (see more with '--help')
Global Options: