cli: remove the 'rad' remote during `rad rm`

If the 'rad' remote is still in the git config, then some of the CLI
tooling will think the project exists -- even after running `rad rm`.

For example, in the current state, if `rad rm` is followed by `rad
init` then the operation will fail.

During `rad rm`, attempt to delete the 'rad' remote.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny 2023-04-28 13:31:33 +01:00 committed by Alexis Sellier
parent c49412a73f
commit 2ff6bf2fc4
No known key found for this signature in database
4 changed files with 58 additions and 1 deletions

View File

@ -11,6 +11,7 @@ Now let's delete the `heartwood` project:
```
$ rad rm rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
✓ Untracked rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✓ Successfully removed 'rad' remote
✓ Successfully removed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from storage
```

View File

@ -6,8 +6,10 @@ use anyhow::anyhow;
use radicle::identity::Id;
use radicle::node;
use radicle::node::Handle as _;
use radicle::storage;
use radicle::Profile;
use crate::git;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
@ -71,7 +73,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?;
let storage = &profile.storage;
let rid = options.rid;
let path = radicle::storage::git::paths::repository(storage, &rid);
let path = storage::git::paths::repository(storage, &rid);
if !path.exists() {
anyhow::bail!("repository {rid} was not found");
@ -79,6 +81,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
if !options.confirm || term::confirm(format!("Remove {rid}?")) {
untrack(&rid, &profile)?;
remove_remote(&rid)?;
fs::remove_dir_all(path)?;
term::success!("Successfully removed {rid} from storage");
}
@ -106,3 +109,20 @@ fn untrack(rid: &Id, profile: &Profile) -> anyhow::Result<()> {
Ok(())
}
fn remove_remote(rid: &Id) -> anyhow::Result<()> {
let cwd = std::env::current_dir()?;
if let Err(e) = git::Repository::open(cwd)
.map_err(|err| err.into())
.and_then(|repo| git::remove_remote(&repo, rid))
{
term::warning(&format!(
"Attempted to remove 'rad' remote from working copy: {e}"
));
term::warning("In case a working copy exists, make sure to `git remote remove rad`");
} else {
term::success!("Successfully removed 'rad' remote");
}
Ok(())
}

View File

@ -251,6 +251,28 @@ pub fn rad_remote(repo: &Repository) -> anyhow::Result<(git2::Remote, Id)> {
}
}
pub fn remove_remote(repo: &Repository, rid: &Id) -> anyhow::Result<()> {
// N.b. ensure that we are removing the remote for the correct RID
match radicle::rad::remote(repo) {
Ok((_, rid_)) => {
if rid_ != *rid {
return Err(radicle::rad::RemoteError::RidMismatch {
found: rid_,
expected: *rid,
}
.into());
}
}
Err(radicle::rad::RemoteError::NotFound(_)) => return Ok(()),
Err(err) => return Err(err).context("could not read git remote configuration"),
};
match radicle::rad::remove_remote(repo) {
Ok(()) => Ok(()),
Err(err) => Err(err).context("could not read git remote configuration"),
}
}
pub fn add_remote<'a>(
repo: &'a Repository,
name: &'a str,

View File

@ -265,6 +265,8 @@ pub enum RemoteError {
InvalidUtf8,
#[error("remote `{0}` not found")]
NotFound(String),
#[error("expected remote for {expected} but found {found}")]
RidMismatch { found: Id, expected: Id },
}
/// Get the radicle ("rad") remote of a repository, and return the associated project id.
@ -282,6 +284,18 @@ pub fn remote(repo: &git2::Repository) -> Result<(git2::Remote<'_>, Id), RemoteE
Ok((remote, url.repo))
}
/// Delete the radicle ("rad") remote of a repository.
pub fn remove_remote(repo: &git2::Repository) -> Result<(), RemoteError> {
repo.remote_delete(&REMOTE_NAME).map_err(|e| {
if e.code() == git2::ErrorCode::NotFound {
RemoteError::NotFound(REMOTE_NAME.to_string())
} else {
RemoteError::from(e)
}
})?;
Ok(())
}
/// Get the Id of project in current working directory
pub fn cwd() -> Result<(git2::Repository, Id), RemoteError> {
let repo = git2::Repository::open(Path::new("."))?;