Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
radicle: ensure clean up on rad::init error
Browse files Browse the repository at this point in the history
It is possible that there can be errors while configuring a Radicle
`Repository` during `rad::init`, for example:
- configuring working copy remote fails
- signing references fails
- setting the identity head fails
- setting the project head fails

If any of these occur, a best effort is made to remove the
`Repository` and the working copy remote, so that the caller may fix
any issues and retry.

Signed-off-by: Fintan Halpenny <[email protected]>
X-Clacks-Overhead: GNU Terry Pratchett
  • Loading branch information
FintanH authored and cloudhead committed Jan 19, 2024
1 parent f03c734 commit 5dbd9bb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
37 changes: 32 additions & 5 deletions radicle/src/rad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,25 +70,52 @@ pub fn init<G: Signer, S: WriteStorage>(
)
})?;
let doc = identity::Doc::initial(proj, delegate, visibility).verified()?;
let (project, _) = Repository::init(&doc, storage, signer)?;
let (project, _) = Repository::init(&doc, &storage, signer)?;
let url = git::Url::from(project.id);

match init_configure(repo, &project, pk, &default_branch, &url, signer) {
Ok(signed) => Ok((project.id, doc, signed)),
Err(err) => {
if let Err(e) = project.remove() {
log::warn!(target: "radicle", "Failed to remove project during `rad::init` cleanup: {e}");
}
if repo.find_remote(&REMOTE_NAME).is_ok() {
if let Err(e) = repo.remote_delete(&REMOTE_NAME) {
log::warn!(target: "radicle", "Failed to remove remote during `rad::init` cleanup: {e}");
}
}
Err(err)
}
}
}

fn init_configure<G>(
repo: &git2::Repository,
project: &Repository,
pk: &crypto::PublicKey,
default_branch: &BranchName,
url: &git::Url,
signer: &G,
) -> Result<SignedRefs<Verified>, InitError>
where
G: crypto::Signer,
{
git::configure_repository(repo)?;
git::configure_remote(repo, &REMOTE_NAME, &url, &url.clone().with_namespace(*pk))?;
git::configure_remote(repo, &REMOTE_NAME, url, &url.clone().with_namespace(*pk))?;
git::push(
repo,
&REMOTE_NAME,
[(
&git::fmt::lit::refs_heads(&default_branch).into(),
&git::fmt::lit::refs_heads(&default_branch).into(),
&git::fmt::lit::refs_heads(default_branch).into(),
&git::fmt::lit::refs_heads(default_branch).into(),
)],
)?;

let signed = project.sign_refs(signer)?;
let _head = project.set_identity_head()?;
let _head = project.set_head()?;

Ok((project.id, doc, signed))
Ok(signed)
}

#[derive(Error, Debug)]
Expand Down
3 changes: 0 additions & 3 deletions radicle/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,6 @@ pub trait WriteStorage: ReadStorage {
/// Create a read-write repository.
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;

/// Delete all remote namespaces apart from the local node's and
/// delegates' namespace.
/// Clean the repository found at `rid`.
///
/// If the local peer has initialised `rad/sigrefs` by forking or
Expand Down
4 changes: 2 additions & 2 deletions radicle/src/storage/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,12 +422,12 @@ impl Repository {
/// Create the repository's identity branch.
pub fn init<G: Signer, S: WriteStorage>(
doc: &Doc<Verified>,
storage: S,
storage: &S,
signer: &G,
) -> Result<(Self, git::Oid), RepositoryError> {
let (doc_oid, _) = doc.encode()?;
let id = Id::from(doc_oid);
let repo = Self::create(paths::repository(&storage, &id), id, storage.info())?;
let repo = Self::create(paths::repository(storage, &id), id, storage.info())?;
let commit = doc.init(&repo, signer)?;

Ok((repo, commit))
Expand Down

0 comments on commit 5dbd9bb

Please sign in to comment.