radicle: add clean method
Add a `clean` method to remove the remotes of a repository that are not the local peer nor the delegates. Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
parent
53013f306f
commit
d23120ca8b
|
|
@ -348,6 +348,9 @@ pub trait WriteStorage: ReadStorage {
|
|||
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;
|
||||
/// Delete a repository.
|
||||
fn remove(&self, rid: Id) -> Result<(), Error>;
|
||||
/// Delete all remote namespaces apart from the local node's and
|
||||
/// delegates' namespace.
|
||||
fn clean(&self, rid: Id) -> Result<Vec<RemoteId>, RepositoryError>;
|
||||
}
|
||||
|
||||
/// Allows read-only access to a repository.
|
||||
|
|
@ -592,6 +595,10 @@ where
|
|||
fn remove(&self, rid: Id) -> Result<(), Error> {
|
||||
self.deref().remove(rid)
|
||||
}
|
||||
|
||||
fn clean(&self, rid: Id) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||
self.deref().clean(rid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
pub mod cob;
|
||||
pub mod transport;
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
|
@ -142,6 +142,11 @@ impl WriteStorage for Storage {
|
|||
fn remove(&self, rid: Id) -> Result<(), Error> {
|
||||
self.repository(rid)?.remove()
|
||||
}
|
||||
|
||||
fn clean(&self, rid: Id) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||
let repo = self.repository(rid)?;
|
||||
repo.clean(&self.info.key)
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
|
|
@ -357,6 +362,56 @@ impl Repository {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove all the remotes of a repository that are not the
|
||||
/// `local` remote or a delegate of the repository.
|
||||
///
|
||||
/// N.b. failure to delete remotes or references will not result
|
||||
/// in an early exit. Instead, this method continues to delete the
|
||||
/// next available remote or reference.
|
||||
pub fn clean(&self, local: &RemoteId) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||
let delegates = self
|
||||
.delegates()?
|
||||
.into_iter()
|
||||
.map(RemoteId::from)
|
||||
.collect::<BTreeSet<_>>();
|
||||
let mut deleted = Vec::new();
|
||||
for id in self.remote_ids()? {
|
||||
let id = match id {
|
||||
Ok(id) => id,
|
||||
Err(e) => {
|
||||
log::error!(target: "storage", "Failed to clean up remote: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// N.b. it is fatal to delete local or delegates
|
||||
if *local == id || delegates.contains(&id) {
|
||||
continue;
|
||||
}
|
||||
let glob = git::refname!("refs/namespaces")
|
||||
.join(git::Component::from(&id))
|
||||
.with_pattern(git::refspec::STAR);
|
||||
let refs = match self.references_glob(&glob) {
|
||||
Ok(refs) => refs,
|
||||
Err(e) => {
|
||||
log::error!(target: "storage", "Failed to clean up remote '{id}': {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
for (refname, _) in refs {
|
||||
if let Ok(mut r) = self.backend.find_reference(refname.as_str()) {
|
||||
if let Err(e) = r.delete() {
|
||||
log::error!(target: "storage", "Failed to clean up reference '{refname}': {e}");
|
||||
}
|
||||
} else {
|
||||
log::error!(target: "storage", "Failed to clean up reference '{refname}'");
|
||||
}
|
||||
}
|
||||
deleted.push(id);
|
||||
}
|
||||
|
||||
Ok(deleted)
|
||||
}
|
||||
|
||||
/// Create the repository's identity branch.
|
||||
pub fn init<G: Signer, S: WriteStorage>(
|
||||
doc: &Doc<Verified>,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ impl WriteStorage for MockStorage {
|
|||
fn remove(&self, _rid: Id) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn clean(&self, _rid: Id) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue