Skip to content

Commit

Permalink
jj new --insert
Browse files Browse the repository at this point in the history
  • Loading branch information
samueltardieu committed Feb 1, 2023
1 parent edfba26 commit 7108cd8
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 23 deletions.
86 changes: 63 additions & 23 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ struct EditArgs {
/// For more information, see
/// https://github.com/martinvonz/jj/blob/main/docs/working-copy.md.
#[derive(clap::Args, Clone, Debug)]
#[command(group(ArgGroup::new("order").args(&["rebase_children", "insert"])))]
struct NewArgs {
/// Parent(s) of the new change
#[arg(default_value = "@")]
Expand All @@ -451,6 +452,9 @@ struct NewArgs {
/// Rebase the children of the parents onto the new change
#[arg(long, short = 'C')]
rebase_children: bool,
/// Insert the commit before the given changes
#[arg(long, short = 'I')]
insert: bool,
}

/// Move changes from one revision into another
Expand Down Expand Up @@ -1978,38 +1982,74 @@ fn cmd_new(ui: &mut Ui, command: &CommandHelper, args: &NewArgs) -> Result<(), C
let commits = resolve_base_revs(&workspace_command, &args.revisions)?;
let parent_ids = commits.iter().map(|c| c.id().clone()).collect::<Vec<_>>();
let mut tx = workspace_command.start_transaction("new empty commit");
let merged_tree = merge_commit_trees(tx.base_repo().as_repo_ref(), &commits);
let new_commit = tx
.mut_repo()
.new_commit(
command.settings(),
parent_ids.clone(),
merged_tree.id().clone(),
)
.set_description(&args.message)
.write()?;
let mut num_rebased = 0;
if args.rebase_children {
// Replace parents in all children by the new commit
let old_parents = RevsetExpression::commits(parent_ids);
let children = tx
let new_commit;
if args.insert {
// Instead of having the new commit as a child of the
// changes given on the command line, add it between
// the changes parents and the changes.
let grandparents = tx
.base_workspace_helper()
.evaluate_revset(&old_parents.children())?
.evaluate_revset(&RevsetExpression::commits(parent_ids.clone()).parents())?
.iter()
.commits(tx.base_repo().store())
.collect::<Result<Vec<_>, _>>()?;
num_rebased = children.len();
for child in children {
let commit_parents = RevsetExpression::commits(child.parent_ids().to_owned());
let new_parents = commit_parents.minus(&old_parents);
let mut new_parents = tx
let merged_tree = merge_commit_trees(tx.base_repo().as_repo_ref(), &grandparents);
let grandparent_ids = grandparents.iter().map(|c| c.id().clone()).collect();
new_commit = tx
.mut_repo()
.new_commit(
command.settings(),
grandparent_ids,
merged_tree.id().clone(),
)
.set_description(&args.message)
.write()?;
num_rebased = parent_ids.len();
for parent_id in parent_ids {
let parent_commit = tx
.base_workspace_helper()
.evaluate_revset(&new_parents)?
.resolve_single_rev(&parent_id.hex())?;
rebase_commit(
command.settings(),
tx.mut_repo(),
&parent_commit,
&[new_commit.clone()],
)?;
}
} else {
let merged_tree = merge_commit_trees(tx.base_repo().as_repo_ref(), &commits);
new_commit = tx
.mut_repo()
.new_commit(
command.settings(),
parent_ids.clone(),
merged_tree.id().clone(),
)
.set_description(&args.message)
.write()?;
if args.rebase_children {
// Replace parents in all children by the new commit
let old_parents = RevsetExpression::commits(parent_ids);
let children = tx
.base_workspace_helper()
.evaluate_revset(&old_parents.children())?
.iter()
.commits(tx.base_repo().store())
.collect::<Result<Vec<_>, _>>()?;
new_parents.push(new_commit.clone());
rebase_commit(command.settings(), tx.mut_repo(), &child, &new_parents)?;
num_rebased = children.len();
for child in children {
let commit_parents = RevsetExpression::commits(child.parent_ids().to_owned());
let new_parents = commit_parents.minus(&old_parents);
let mut new_parents = tx
.base_workspace_helper()
.evaluate_revset(&new_parents)?
.iter()
.commits(tx.base_repo().store())
.collect::<Result<Vec<_>, _>>()?;
new_parents.push(new_commit.clone());
rebase_commit(command.settings(), tx.mut_repo(), &child, &new_parents)?;
}
}
}
if num_rebased > 0 {
Expand Down
40 changes: 40 additions & 0 deletions tests/test_new_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,46 @@ fn test_new_rebase_children() {
"###);
}

#[test]
fn test_new_insert() {
let 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");
setup_before_insertion(&test_env, &repo_path);
insta::assert_snapshot!(get_short_log_output(&test_env, &repo_path), @r###"
@ F
|\
o | E
| o D
|/
| o C
| o B
| o A
|/
o root
"###);

let stdout = test_env.jj_cmd_success(&repo_path, &["new", "--insert", "-m", "G", "C", "F"]);
insta::assert_snapshot!(stdout, @r###"
Rebased 2 descendant commits
Working copy now at: ff6bbbc7b8df G
"###);
insta::assert_snapshot!(get_short_log_output(&test_env, &repo_path), @r###"
o F
| o C
|/
@-. G
|\ \
o | | E
| o | D
|/ /
| o B
| o A
|/
o root
"###);
}

fn setup_before_insertion(test_env: &TestEnvironment, repo_path: &Path) {
test_env.jj_cmd_success(repo_path, &["branch", "create", "A"]);
test_env.jj_cmd_success(repo_path, &["commit", "-m", "A"]);
Expand Down

0 comments on commit 7108cd8

Please sign in to comment.