radicle: ensure clean up on rad::init error
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 <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
parent
f03c734e85
commit
5dbd9bb2a3
|
|
@ -70,17 +70,44 @@ 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(),
|
||||
)],
|
||||
)?;
|
||||
|
||||
|
|
@ -88,7 +115,7 @@ pub fn init<G: Signer, S: WriteStorage>(
|
|||
let _head = project.set_identity_head()?;
|
||||
let _head = project.set_head()?;
|
||||
|
||||
Ok((project.id, doc, signed))
|
||||
Ok(signed)
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Reference in New Issue