mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-15 16:53:25 +00:00
cli: simplify-parents: avoid multiple rebases of the same commits
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
The previous iteration of `jj simplify-parents` would only reparent the commits in the target set in the `MutableRepo::transform_descendants` callback. The subsequent `MutableRepo::rebase_descendants` call invoked when the transaction is committed would then rebase all descendants of the target set, which includes the commits in the target set again. This commit updates the `MutableRepo::transform_descendants` callback to perform rebasing of all descendants within the callback. All descendants of the target set will only be rebased at most once.
This commit is contained in:
parent
1ae8f0c77a
commit
4f2e72a140
2 changed files with 32 additions and 55 deletions
|
@ -2,10 +2,7 @@ use std::collections::HashSet;
|
|||
|
||||
use clap_complete::ArgValueCandidates;
|
||||
use itertools::Itertools;
|
||||
use jj_lib::backend::BackendResult;
|
||||
use jj_lib::revset::RevsetExpression;
|
||||
use jj_lib::rewrite::CommitRewriter;
|
||||
use jj_lib::settings::UserSettings;
|
||||
|
||||
use crate::cli_util::CommandHelper;
|
||||
use crate::cli_util::RevisionArg;
|
||||
|
@ -67,63 +64,47 @@ pub(crate) fn cmd_simplify_parents(
|
|||
let num_orig_commits = commit_ids.len();
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
let mut stats = SimplifyStats::default();
|
||||
tx.repo_mut()
|
||||
.transform_descendants(command.settings(), commit_ids, |rewriter| {
|
||||
if commit_ids_set.contains(rewriter.old_commit().id()) {
|
||||
simplify_commit_parents(command.settings(), rewriter, &mut stats)?;
|
||||
}
|
||||
let mut simplified_commits = 0;
|
||||
let mut edges = 0;
|
||||
let mut reparented_descendants = 0;
|
||||
|
||||
tx.repo_mut()
|
||||
.transform_descendants(command.settings(), commit_ids, |mut rewriter| {
|
||||
let num_old_heads = rewriter.new_parents().len();
|
||||
if commit_ids_set.contains(rewriter.old_commit().id()) && num_old_heads > 1 {
|
||||
rewriter.simplify_ancestor_merge();
|
||||
}
|
||||
let num_new_heads = rewriter.new_parents().len();
|
||||
|
||||
if rewriter.parents_changed() {
|
||||
rewriter.reparent(command.settings())?.write()?;
|
||||
|
||||
if num_new_heads < num_old_heads {
|
||||
simplified_commits += 1;
|
||||
edges += num_old_heads - num_new_heads;
|
||||
} else {
|
||||
reparented_descendants += 1;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if let Some(mut formatter) = ui.status_formatter() {
|
||||
if !stats.is_empty() {
|
||||
if simplified_commits > 0 {
|
||||
writeln!(
|
||||
formatter,
|
||||
"Removed {} edges from {} out of {} commits.",
|
||||
stats.edges, stats.commits, num_orig_commits
|
||||
"Removed {edges} edges from {simplified_commits} out of {num_orig_commits} \
|
||||
commits.",
|
||||
)?;
|
||||
if reparented_descendants > 0 {
|
||||
writeln!(
|
||||
formatter,
|
||||
"Rebased {reparented_descendants} descendant commits",
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
tx.finish(ui, format!("simplify {num_orig_commits} commits"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct SimplifyStats {
|
||||
commits: usize,
|
||||
edges: usize,
|
||||
}
|
||||
|
||||
impl SimplifyStats {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.commits == 0 && self.edges == 0
|
||||
}
|
||||
}
|
||||
|
||||
fn simplify_commit_parents(
|
||||
settings: &UserSettings,
|
||||
mut rewriter: CommitRewriter,
|
||||
stats: &mut SimplifyStats,
|
||||
) -> BackendResult<()> {
|
||||
if rewriter.old_commit().parent_ids().len() <= 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let num_old_heads = rewriter.new_parents().len();
|
||||
rewriter.simplify_ancestor_merge();
|
||||
let num_new_heads = rewriter.new_parents().len();
|
||||
|
||||
if rewriter.parents_changed() {
|
||||
rewriter.reparent(settings)?.write()?;
|
||||
|
||||
if num_new_heads < num_old_heads {
|
||||
stats.commits += 1;
|
||||
stats.edges += num_old_heads - num_new_heads;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -208,11 +208,9 @@ fn test_simplify_parents_multiple_redundant_parents() {
|
|||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&repo_path, &["simplify-parents", "-r", "c", "-r", "f"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
// TODO: The output should indicate that edges were removed from 2 commits
|
||||
// (c, f) and 2 descendant commits were rebased (d, e).
|
||||
insta::assert_snapshot!(stderr, @r#"
|
||||
Removed 2 edges from 2 out of 2 commits.
|
||||
Rebased 3 descendant commits
|
||||
Rebased 2 descendant commits
|
||||
Working copy now at: kmkuslsw 8cc01e1b f | f
|
||||
Parent commit : znkkpsqq 040ae3a6 e | e
|
||||
"#);
|
||||
|
@ -232,11 +230,9 @@ fn test_simplify_parents_multiple_redundant_parents() {
|
|||
test_env.jj_cmd_ok(&repo_path, &["op", "restore", &setup_opid]);
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["simplify-parents", "-s", "c"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
// TODO: The output should indicate that edges were removed from 2 commits
|
||||
// (c, f) and 2 descendant commits were rebased (d, e).
|
||||
insta::assert_snapshot!(stderr, @r#"
|
||||
Removed 2 edges from 2 out of 4 commits.
|
||||
Rebased 3 descendant commits
|
||||
Rebased 2 descendant commits
|
||||
Working copy now at: kmkuslsw 70a39dff f | f
|
||||
Parent commit : znkkpsqq a021fee9 e | e
|
||||
"#);
|
||||
|
|
Loading…
Reference in a new issue