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 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);
|
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_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(
|
git::push(
|
||||||
repo,
|
repo,
|
||||||
&REMOTE_NAME,
|
&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_identity_head()?;
|
||||||
let _head = project.set_head()?;
|
let _head = project.set_head()?;
|
||||||
|
|
||||||
Ok((project.id, doc, signed))
|
Ok(signed)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -371,9 +371,6 @@ pub trait WriteStorage: ReadStorage {
|
||||||
/// Create a read-write repository.
|
/// Create a read-write repository.
|
||||||
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;
|
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`.
|
/// Clean the repository found at `rid`.
|
||||||
///
|
///
|
||||||
/// If the local peer has initialised `rad/sigrefs` by forking or
|
/// If the local peer has initialised `rad/sigrefs` by forking or
|
||||||
|
|
|
||||||
|
|
@ -422,12 +422,12 @@ impl Repository {
|
||||||
/// Create the repository's identity branch.
|
/// Create the repository's identity branch.
|
||||||
pub fn init<G: Signer, S: WriteStorage>(
|
pub fn init<G: Signer, S: WriteStorage>(
|
||||||
doc: &Doc<Verified>,
|
doc: &Doc<Verified>,
|
||||||
storage: S,
|
storage: &S,
|
||||||
signer: &G,
|
signer: &G,
|
||||||
) -> Result<(Self, git::Oid), RepositoryError> {
|
) -> Result<(Self, git::Oid), RepositoryError> {
|
||||||
let (doc_oid, _) = doc.encode()?;
|
let (doc_oid, _) = doc.encode()?;
|
||||||
let id = Id::from(doc_oid);
|
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)?;
|
let commit = doc.init(&repo, signer)?;
|
||||||
|
|
||||||
Ok((repo, commit))
|
Ok((repo, commit))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue