mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
Implement a rename
subcommand for the branch
command.
This is really a simple change that does the following in a transaction: * Set the new branch name to point to the same commit as the old branch name. * Set the old branch name to point to no commit (hence deleting the old name). Before it starts, it confirms that the new branch name is not already in use.
This commit is contained in:
parent
d39843bd82
commit
35b8dad890
3 changed files with 75 additions and 0 deletions
|
@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### New features
|
||||
|
||||
* Information about new and resolved conflicts is now printed by every command.
|
||||
* `jj branch` has gained a new `rename` subcommand that allows changing a branch
|
||||
name atomically. `jj branch help rename` for details.
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ pub enum BranchSubcommand {
|
|||
Forget(BranchForgetArgs),
|
||||
#[command(visible_alias("l"))]
|
||||
List(BranchListArgs),
|
||||
#[command(visible_alias("r"))]
|
||||
Rename(BranchRenameArgs),
|
||||
#[command(visible_alias("s"))]
|
||||
Set(BranchSetArgs),
|
||||
Track(BranchTrackArgs),
|
||||
|
@ -122,6 +124,19 @@ pub struct BranchForgetArgs {
|
|||
pub glob: Vec<StringPattern>,
|
||||
}
|
||||
|
||||
/// Rename `old` branch name to `new` branch name.
|
||||
///
|
||||
/// The new branch name points at the same commit as the old
|
||||
/// branch name.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchRenameArgs {
|
||||
/// The old name of the branch.
|
||||
pub old: String,
|
||||
|
||||
/// The new name of the branch.
|
||||
pub new: String,
|
||||
}
|
||||
|
||||
/// Update an existing branch to point to a certain commit.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct BranchSetArgs {
|
||||
|
@ -248,6 +263,7 @@ pub fn cmd_branch(
|
|||
) -> Result<(), CommandError> {
|
||||
match subcommand {
|
||||
BranchSubcommand::Create(sub_args) => cmd_branch_create(ui, command, sub_args),
|
||||
BranchSubcommand::Rename(sub_args) => cmd_branch_rename(ui, command, sub_args),
|
||||
BranchSubcommand::Set(sub_args) => cmd_branch_set(ui, command, sub_args),
|
||||
BranchSubcommand::Delete(sub_args) => cmd_branch_delete(ui, command, sub_args),
|
||||
BranchSubcommand::Forget(sub_args) => cmd_branch_forget(ui, command, sub_args),
|
||||
|
@ -301,6 +317,40 @@ fn cmd_branch_create(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_branch_rename(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &BranchRenameArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let view = workspace_command.repo().view();
|
||||
let old_branch = &args.old;
|
||||
let ref_target = view.get_local_branch(old_branch).clone();
|
||||
if ref_target.is_absent() {
|
||||
return Err(user_error(format!("No such branch: {old_branch}")));
|
||||
}
|
||||
|
||||
let new_branch = &args.new;
|
||||
if view.get_local_branch(new_branch).is_present() {
|
||||
return Err(user_error(format!("Branch already exists: {new_branch}")));
|
||||
}
|
||||
|
||||
let mut tx = workspace_command.start_transaction();
|
||||
tx.mut_repo()
|
||||
.set_local_branch_target(new_branch, ref_target);
|
||||
tx.mut_repo()
|
||||
.set_local_branch_target(old_branch, RefTarget::absent());
|
||||
tx.finish(
|
||||
ui,
|
||||
format!(
|
||||
"rename {} to {}",
|
||||
make_branch_term(&[old_branch]),
|
||||
make_branch_term(&[new_branch]),
|
||||
),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_branch_set(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
|
|
|
@ -189,6 +189,29 @@ fn test_branch_move_conflicting() {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_branch_rename() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
||||
let repo_path = test_env.env_root().join("repo");
|
||||
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["branch", "rename", "foo", "bar"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: No such branch: foo
|
||||
"###);
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
|
||||
let (_stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["branch", "rename", "foo", "bar"]);
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
|
||||
test_env.jj_cmd_ok(&repo_path, &["new"]);
|
||||
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "conflictfoo"]);
|
||||
let stderr = test_env.jj_cmd_failure(&repo_path, &["branch", "rename", "bar", "conflictfoo"]);
|
||||
insta::assert_snapshot!(stderr, @r###"
|
||||
Error: Branch already exists: conflictfoo
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_branch_forget_glob() {
|
||||
let test_env = TestEnvironment::default();
|
||||
|
|
Loading…
Reference in a new issue