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>;
|
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;
|
||||||
/// Delete a repository.
|
/// Delete a repository.
|
||||||
fn remove(&self, rid: Id) -> Result<(), Error>;
|
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.
|
/// Allows read-only access to a repository.
|
||||||
|
|
@ -592,6 +595,10 @@ where
|
||||||
fn remove(&self, rid: Id) -> Result<(), Error> {
|
fn remove(&self, rid: Id) -> Result<(), Error> {
|
||||||
self.deref().remove(rid)
|
self.deref().remove(rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean(&self, rid: Id) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||||
|
self.deref().clean(rid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
pub mod cob;
|
pub mod cob;
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
@ -142,6 +142,11 @@ impl WriteStorage for Storage {
|
||||||
fn remove(&self, rid: Id) -> Result<(), Error> {
|
fn remove(&self, rid: Id) -> Result<(), Error> {
|
||||||
self.repository(rid)?.remove()
|
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 {
|
impl Storage {
|
||||||
|
|
@ -357,6 +362,56 @@ impl Repository {
|
||||||
Ok(())
|
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.
|
/// 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>,
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ impl WriteStorage for MockStorage {
|
||||||
fn remove(&self, _rid: Id) -> Result<(), Error> {
|
fn remove(&self, _rid: Id) -> Result<(), Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean(&self, _rid: Id) -> Result<Vec<RemoteId>, RepositoryError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue