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

commands: move next code to next.rs

This commit is contained in:
Antoine Cezar 2023-10-29 22:42:56 +01:00 committed by Antoine Cezar
parent 23a0baba14
commit d1135917b0
2 changed files with 134 additions and 108 deletions

View file

@ -36,6 +36,7 @@ mod log;
mod merge;
mod r#move;
mod new;
mod next;
mod operation;
mod rebase;
mod resolve;
@ -119,7 +120,7 @@ enum Commands {
Merge(new::NewArgs),
Move(r#move::MoveArgs),
New(new::NewArgs),
Next(NextArgs),
Next(next::NextArgs),
Obslog(ObslogArgs),
#[command(subcommand)]
#[command(visible_alias = "op")]
@ -214,46 +215,6 @@ struct ObslogArgs {
diff_format: DiffFormatArgs,
}
/// Move the current working copy commit to the next child revision in the
/// repository.
///
///
/// The command moves you to the next child in a linear fashion.
///
///
/// D D @
/// | |/
/// C @ => C
/// |/ |
/// B B
///
///
/// If `--edit` is passed, it will move you directly to the child
/// revision.
///
///
/// D D
/// | |
/// C C
/// | |
/// B => @
/// | |
/// @ A
// TODO(#2126): Handle multiple child revisions properly.
#[derive(clap::Args, Clone, Debug)]
#[command(verbatim_doc_comment)]
struct NextArgs {
/// How many revisions to move forward. By default advances to the next
/// child.
#[arg(default_value = "1")]
amount: u64,
/// Instead of creating a new working-copy commit on top of the target
/// commit (like `jj new`), edit the target commit directly (like `jj
/// edit`).
#[arg(long)]
edit: bool,
}
/// Move the working copy commit to the parent of the current revision.
///
///
@ -1018,72 +979,6 @@ fn edit_sparse(
.try_collect()
}
fn cmd_next(ui: &mut Ui, command: &CommandHelper, args: &NextArgs) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let edit = args.edit;
let amount = args.amount;
let current_wc_id = workspace_command
.get_wc_commit_id()
.ok_or_else(|| user_error("This command requires a working copy"))?;
let current_wc = workspace_command.repo().store().get_commit(current_wc_id)?;
let current_short = short_commit_hash(current_wc.id());
// If we're editing, start at the working-copy commit.
// Otherwise start from our direct parent.
let start_id = if edit {
current_wc_id
} else {
match current_wc.parent_ids() {
[parent_id] => parent_id,
_ => return Err(user_error("Cannot run `jj next` on a merge commit")),
}
};
let descendant_expression = RevsetExpression::commit(start_id.clone()).descendants_at(amount);
let target_expression = if edit {
descendant_expression
} else {
descendant_expression.minus(&RevsetExpression::commit(current_wc_id.clone()).descendants())
};
let targets: Vec<Commit> = target_expression
.resolve(workspace_command.repo().as_ref())?
.evaluate(workspace_command.repo().as_ref())?
.iter()
.commits(workspace_command.repo().store())
.take(2)
.try_collect()?;
let target = match targets.as_slice() {
[target] => target,
[] => {
// We found no descendant.
return Err(user_error(format!(
"No descendant found {amount} commit{} forward",
if amount > 1 { "s" } else { "" }
)));
}
_ => {
// TODO(#2126) We currently cannot deal with multiple children, which result
// from branches. Prompt the user for resolution.
return Err(user_error("Ambiguous target commit"));
}
};
let target_short = short_commit_hash(target.id());
// We're editing, just move to the target commit.
if edit {
// We're editing, the target must be rewritable.
workspace_command.check_rewritable([target])?;
let mut tx = workspace_command
.start_transaction(&format!("next: {current_short} -> editing {target_short}"));
tx.edit(target)?;
tx.finish(ui)?;
return Ok(());
}
let mut tx =
workspace_command.start_transaction(&format!("next: {current_short} -> {target_short}"));
// Move the working-copy commit to the new parent.
tx.check_out(target)?;
tx.finish(ui)?;
Ok(())
}
fn cmd_prev(ui: &mut Ui, command: &CommandHelper, args: &PrevArgs) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let edit = args.edit;
@ -1979,8 +1874,8 @@ pub fn run_command(ui: &mut Ui, command_helper: &CommandHelper) -> Result<(), Co
Commands::Duplicate(sub_args) => duplicate::cmd_duplicate(ui, command_helper, sub_args),
Commands::Abandon(sub_args) => abandon::cmd_abandon(ui, command_helper, sub_args),
Commands::Edit(sub_args) => edit::cmd_edit(ui, command_helper, sub_args),
Commands::Next(sub_args) => cmd_next(ui, command_helper, sub_args),
Commands::Prev(sub_args) => cmd_prev(ui, command_helper, sub_args),
Commands::Next(sub_args) => next::cmd_next(ui, command_helper, sub_args),
Commands::New(sub_args) => new::cmd_new(ui, command_helper, sub_args),
Commands::Move(sub_args) => r#move::cmd_move(ui, command_helper, sub_args),
Commands::Squash(sub_args) => cmd_squash(ui, command_helper, sub_args),

131
cli/src/commands/next.rs Normal file
View file

@ -0,0 +1,131 @@
// Copyright 2020 The Jujutsu Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use itertools::Itertools;
use jj_lib::commit::Commit;
use jj_lib::repo::Repo;
use jj_lib::revset::{RevsetExpression, RevsetIteratorExt};
use crate::cli_util::{short_commit_hash, user_error, CommandError, CommandHelper};
use crate::ui::Ui;
/// Move the current working copy commit to the next child revision in the
/// repository.
///
///
/// The command moves you to the next child in a linear fashion.
///
///
/// D D @
/// | |/
/// C @ => C
/// |/ |
/// B B
///
///
/// If `--edit` is passed, it will move you directly to the child
/// revision.
///
///
/// D D
/// | |
/// C C
/// | |
/// B => @
/// | |
/// @ A
// TODO(#2126): Handle multiple child revisions properly.
#[derive(clap::Args, Clone, Debug)]
#[command(verbatim_doc_comment)]
pub(crate) struct NextArgs {
/// How many revisions to move forward. By default advances to the next
/// child.
#[arg(default_value = "1")]
amount: u64,
/// Instead of creating a new working-copy commit on top of the target
/// commit (like `jj new`), edit the target commit directly (like `jj
/// edit`).
#[arg(long)]
edit: bool,
}
pub(crate) fn cmd_next(
ui: &mut Ui,
command: &CommandHelper,
args: &NextArgs,
) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let edit = args.edit;
let amount = args.amount;
let current_wc_id = workspace_command
.get_wc_commit_id()
.ok_or_else(|| user_error("This command requires a working copy"))?;
let current_wc = workspace_command.repo().store().get_commit(current_wc_id)?;
let current_short = short_commit_hash(current_wc.id());
// If we're editing, start at the working-copy commit.
// Otherwise start from our direct parent.
let start_id = if edit {
current_wc_id
} else {
match current_wc.parent_ids() {
[parent_id] => parent_id,
_ => return Err(user_error("Cannot run `jj next` on a merge commit")),
}
};
let descendant_expression = RevsetExpression::commit(start_id.clone()).descendants_at(amount);
let target_expression = if edit {
descendant_expression
} else {
descendant_expression.minus(&RevsetExpression::commit(current_wc_id.clone()).descendants())
};
let targets: Vec<Commit> = target_expression
.resolve(workspace_command.repo().as_ref())?
.evaluate(workspace_command.repo().as_ref())?
.iter()
.commits(workspace_command.repo().store())
.take(2)
.try_collect()?;
let target = match targets.as_slice() {
[target] => target,
[] => {
// We found no descendant.
return Err(user_error(format!(
"No descendant found {amount} commit{} forward",
if amount > 1 { "s" } else { "" }
)));
}
_ => {
// TODO(#2126) We currently cannot deal with multiple children, which result
// from branches. Prompt the user for resolution.
return Err(user_error("Ambiguous target commit"));
}
};
let target_short = short_commit_hash(target.id());
// We're editing, just move to the target commit.
if edit {
// We're editing, the target must be rewritable.
workspace_command.check_rewritable([target])?;
let mut tx = workspace_command
.start_transaction(&format!("next: {current_short} -> editing {target_short}"));
tx.edit(target)?;
tx.finish(ui)?;
return Ok(());
}
let mut tx =
workspace_command.start_transaction(&format!("next: {current_short} -> {target_short}"));
// Move the working-copy commit to the new parent.
tx.check_out(target)?;
tx.finish(ui)?;
Ok(())
}