forked from mirrors/jj
cli: add git remote rename subcommand
This commit is contained in:
parent
bbdcd6faaf
commit
b009019d8d
6 changed files with 87 additions and 0 deletions
|
@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
* The new `jj git remote rename` command allows git remotes to be renamed
|
||||||
|
in-place.
|
||||||
|
|
||||||
## [0.5.1] - 2022-10-17
|
## [0.5.1] - 2022-10-17
|
||||||
|
|
||||||
No changes (just trying to get automated GitHub release to work).
|
No changes (just trying to get automated GitHub release to work).
|
||||||
|
|
|
@ -754,6 +754,10 @@ impl MutableRepo {
|
||||||
self.view_mut().remove_remote_branch(name, remote_name);
|
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> {
|
pub fn get_tag(&self, name: &str) -> Option<RefTarget> {
|
||||||
self.view.borrow().get_tag(name)
|
self.view.borrow().get_tag(name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
pub fn get_tag(&self, name: &str) -> Option<RefTarget> {
|
||||||
self.data.tags.get(name).cloned()
|
self.data.tags.get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
|
@ -612,3 +612,19 @@ fn test_rebase_descendants_conflicting_rewrite(use_git: bool) {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.is_none());
|
.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);
|
||||||
|
}
|
||||||
|
|
|
@ -843,6 +843,7 @@ enum GitCommands {
|
||||||
enum GitRemoteCommands {
|
enum GitRemoteCommands {
|
||||||
Add(GitRemoteAddArgs),
|
Add(GitRemoteAddArgs),
|
||||||
Remove(GitRemoteRemoveArgs),
|
Remove(GitRemoteRemoveArgs),
|
||||||
|
Rename(GitRemoteRenameArgs),
|
||||||
List(GitRemoteListArgs),
|
List(GitRemoteListArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,6 +863,15 @@ struct GitRemoteRemoveArgs {
|
||||||
remote: String,
|
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
|
/// List Git remotes
|
||||||
#[derive(clap::Args, Clone, Debug)]
|
#[derive(clap::Args, Clone, Debug)]
|
||||||
struct GitRemoteListArgs {}
|
struct GitRemoteListArgs {}
|
||||||
|
@ -3967,6 +3977,29 @@ fn cmd_git_remote_remove(
|
||||||
Ok(())
|
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(
|
fn cmd_git_remote_list(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
command: &CommandHelper,
|
command: &CommandHelper,
|
||||||
|
@ -4419,6 +4452,9 @@ fn cmd_git(
|
||||||
GitCommands::Remote(GitRemoteCommands::Remove(command_matches)) => {
|
GitCommands::Remote(GitRemoteCommands::Remove(command_matches)) => {
|
||||||
cmd_git_remote_remove(ui, command, 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)) => {
|
GitCommands::Remote(GitRemoteCommands::List(command_matches)) => {
|
||||||
cmd_git_remote_list(ui, command, command_matches)
|
cmd_git_remote_list(ui, command, command_matches)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,3 +49,21 @@ fn test_git_remotes() {
|
||||||
insta::assert_snapshot!(stderr, @"Error: Remote doesn't exist
|
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");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue