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

cli: add git remote rename subcommand

This commit is contained in:
Benjamin Saunders 2022-10-19 11:44:39 -07:00
parent bbdcd6faaf
commit b009019d8d
6 changed files with 87 additions and 0 deletions

View file

@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### New features
* The new `jj git remote rename` command allows git remotes to be renamed
in-place.
## [0.5.1] - 2022-10-17
No changes (just trying to get automated GitHub release to work).

View file

@ -754,6 +754,10 @@ impl MutableRepo {
self.view_mut().remove_remote_branch(name, remote_name);
}
pub fn rename_remote(&mut self, old: &str, new: &str) {
self.view_mut().rename_remote(old, new);
}
pub fn get_tag(&self, name: &str) -> Option<RefTarget> {
self.view.borrow().get_tag(name)
}

View file

@ -212,6 +212,14 @@ impl View {
}
}
pub fn rename_remote(&mut self, old: &str, new: &str) {
for branch in self.data.branches.values_mut() {
if let Some(target) = branch.remote_targets.remove(old) {
branch.remote_targets.insert(new.to_owned(), target);
}
}
}
pub fn get_tag(&self, name: &str) -> Option<RefTarget> {
self.data.tags.get(name).cloned()
}

View file

@ -612,3 +612,19 @@ fn test_rebase_descendants_conflicting_rewrite(use_git: bool) {
.unwrap()
.is_none());
}
#[test_case(false ; "local backend")]
#[test_case(true ; "git backend")]
fn test_rename_remote(use_git: bool) {
let settings = testutils::user_settings();
let test_repo = TestRepo::init(use_git);
let repo = &test_repo.repo;
let mut tx = repo.start_transaction("test");
let mut_repo = tx.mut_repo();
let commit = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo);
let target = RefTarget::Normal(commit.id().clone());
mut_repo.set_remote_branch("main".to_string(), "origin".to_string(), target.clone());
mut_repo.rename_remote("origin", "upstream");
assert_eq!(mut_repo.get_remote_branch("main", "upstream"), Some(target));
assert_eq!(mut_repo.get_remote_branch("main", "origin"), None);
}

View file

@ -843,6 +843,7 @@ enum GitCommands {
enum GitRemoteCommands {
Add(GitRemoteAddArgs),
Remove(GitRemoteRemoveArgs),
Rename(GitRemoteRenameArgs),
List(GitRemoteListArgs),
}
@ -862,6 +863,15 @@ struct GitRemoteRemoveArgs {
remote: String,
}
/// Rename a Git remote
#[derive(clap::Args, Clone, Debug)]
struct GitRemoteRenameArgs {
/// The name of an existing remote
old: String,
/// The desired name for `old`
new: String,
}
/// List Git remotes
#[derive(clap::Args, Clone, Debug)]
struct GitRemoteListArgs {}
@ -3967,6 +3977,29 @@ fn cmd_git_remote_remove(
Ok(())
}
fn cmd_git_remote_rename(
ui: &mut Ui,
command: &CommandHelper,
args: &GitRemoteRenameArgs,
) -> Result<(), CommandError> {
let mut workspace_command = command.workspace_helper(ui)?;
let repo = workspace_command.repo();
let git_repo = get_git_repo(repo.store())?;
if git_repo.find_remote(&args.old).is_err() {
return Err(CommandError::UserError("Remote doesn't exist".to_string()));
}
git_repo
.remote_rename(&args.old, &args.new)
.map_err(|err| CommandError::UserError(err.to_string()))?;
let mut tx = workspace_command
.start_transaction(&format!("rename git remote {} to {}", &args.old, &args.new));
tx.mut_repo().rename_remote(&args.old, &args.new);
if tx.mut_repo().has_changes() {
workspace_command.finish_transaction(ui, tx)?;
}
Ok(())
}
fn cmd_git_remote_list(
ui: &mut Ui,
command: &CommandHelper,
@ -4419,6 +4452,9 @@ fn cmd_git(
GitCommands::Remote(GitRemoteCommands::Remove(command_matches)) => {
cmd_git_remote_remove(ui, command, command_matches)
}
GitCommands::Remote(GitRemoteCommands::Rename(command_matches)) => {
cmd_git_remote_rename(ui, command, command_matches)
}
GitCommands::Remote(GitRemoteCommands::List(command_matches)) => {
cmd_git_remote_list(ui, command, command_matches)
}

View file

@ -49,3 +49,21 @@ fn test_git_remotes() {
insta::assert_snapshot!(stderr, @"Error: Remote doesn't exist
");
}
#[test]
fn test_git_remote_rename() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_success(test_env.env_root(), &["init", "--git", "repo"]);
let repo_path = test_env.env_root().join("repo");
test_env.jj_cmd_success(
&repo_path,
&["git", "remote", "add", "foo", "http://example.com/repo/foo"],
);
let stderr = test_env.jj_cmd_failure(&repo_path, &["git", "remote", "rename", "bar", "foo"]);
insta::assert_snapshot!(stderr, @"Error: Remote doesn't exist\n");
let stdout = test_env.jj_cmd_success(&repo_path, &["git", "remote", "rename", "foo", "bar"]);
insta::assert_snapshot!(stdout, @"");
let stdout = test_env.jj_cmd_success(&repo_path, &["git", "remote", "list"]);
insta::assert_snapshot!(stdout, @"bar http://example.com/repo/foo");
}