diff --git a/cli/src/commands/git/remote/mod.rs b/cli/src/commands/git/remote/mod.rs index 3026803ddc..ff634656f1 100644 --- a/cli/src/commands/git/remote/mod.rs +++ b/cli/src/commands/git/remote/mod.rs @@ -16,6 +16,7 @@ pub mod add; pub mod list; pub mod remove; pub mod rename; +pub mod set_url; use clap::Subcommand; @@ -23,6 +24,7 @@ use self::add::{cmd_remote_add, AddArgs}; use self::list::{cmd_remote_list, ListArgs}; use self::remove::{cmd_remote_remove, RemoveArgs}; use self::rename::{cmd_remote_rename, RenameArgs}; +use self::set_url::{cmd_remote_set_url, SetUrlArgs}; use crate::cli_util::CommandHelper; use crate::command_error::CommandError; use crate::ui::Ui; @@ -36,6 +38,7 @@ pub enum RemoteCommand { List(ListArgs), Remove(RemoveArgs), Rename(RenameArgs), + SetUrl(SetUrlArgs), } pub fn cmd_git_remote( @@ -48,5 +51,6 @@ pub fn cmd_git_remote( RemoteCommand::List(args) => cmd_remote_list(ui, command, args), RemoteCommand::Remove(args) => cmd_remote_remove(ui, command, args), RemoteCommand::Rename(args) => cmd_remote_rename(ui, command, args), + RemoteCommand::SetUrl(args) => cmd_remote_set_url(ui, command, args), } } diff --git a/cli/src/commands/git/remote/set_url.rs b/cli/src/commands/git/remote/set_url.rs new file mode 100644 index 0000000000..86363fdb2e --- /dev/null +++ b/cli/src/commands/git/remote/set_url.rs @@ -0,0 +1,50 @@ +// Copyright 2024 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 jj_lib::git; +use jj_lib::repo::Repo; + +use crate::cli_util::CommandHelper; +use crate::command_error::CommandError; +use crate::git_util::get_git_repo; +use crate::ui::Ui; + +/// Set the URL of a Git remote +#[derive(clap::Args, Clone, Debug)] +pub struct SetUrlArgs { + /// The remote's name + remote: String, + /// The desired url for `remote` + url: String, +} + +pub fn cmd_remote_set_url( + ui: &mut Ui, + command: &CommandHelper, + args: &SetUrlArgs, +) -> Result<(), CommandError> { + let mut workspace_command = command.workspace_helper(ui)?; + let repo = workspace_command.repo(); + let git_repo = get_git_repo(repo.store())?; + let mut tx = workspace_command.start_transaction(); + git::remote_set_url(&git_repo, &args.remote, &args.url)?; + if tx.mut_repo().has_changes() { + tx.finish( + ui, + format!("set url of git remote {} to {}", &args.remote, &args.url), + ) + } else { + Ok(()) // Do not print "Nothing changed." + } +} diff --git a/lib/src/git.rs b/lib/src/git.rs index fb3b709166..66032dfc00 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -1144,6 +1144,26 @@ pub fn rename_remote( Ok(()) } +pub fn remote_set_url( + git_repo: &git2::Repository, + remote_name: &str, + new_remote_url: &str, +) -> Result<(), GitRemoteManagementError> { + if remote_name == REMOTE_NAME_FOR_LOCAL_GIT_REPO { + return Err(GitRemoteManagementError::RemoteReservedForLocalGitRepo); + } + git_repo + .remote_set_url(remote_name, new_remote_url) + .map_err(|err| { + if is_remote_not_found_err(&err) { + GitRemoteManagementError::NoSuchRemote(remote_name.to_owned()) + } else { + GitRemoteManagementError::InternalGitError(err) + } + })?; + Ok(()) +} + fn rename_remote_refs(mut_repo: &mut MutableRepo, old_remote_name: &str, new_remote_name: &str) { mut_repo.rename_remote(old_remote_name, new_remote_name); let prefix = format!("refs/remotes/{old_remote_name}/");