diff --git a/crates/core/src/index.rs b/crates/core/src/index.rs index c73f95ac1..a0c0bc543 100644 --- a/crates/core/src/index.rs +++ b/crates/core/src/index.rs @@ -317,6 +317,12 @@ impl GlobalIndex { } } } + + pub(crate) fn drop_data(self) -> Self { + Self { + index: Arc::new(self.into_index().drop_data()), + } + } } impl ReadGlobalIndex for GlobalIndex {} diff --git a/crates/core/src/index/binarysorted.rs b/crates/core/src/index/binarysorted.rs index feb02d527..9acef4744 100644 --- a/crates/core/src/index/binarysorted.rs +++ b/crates/core/src/index/binarysorted.rs @@ -75,6 +75,23 @@ pub(crate) struct TypeIndex { #[derive(Debug)] pub struct Index(BlobTypeMap); +impl Index { + /// drop all index entries related to data blobs + pub(crate) fn drop_data(self) -> Self { + Self(self.0.map(|blob_type, i| { + if blob_type == BlobType::Data { + TypeIndex { + packs: Vec::new(), + entries: EntriesVariants::None, + total_size: 0, + } + } else { + i + } + })) + } +} + impl IndexCollector { #[must_use] pub fn new(tpe: IndexType) -> Self { diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 5df9ccff2..19627949e 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -148,5 +148,7 @@ pub use crate::{ repofile::snapshotfile::{ PathList, SnapshotGroup, SnapshotGroupCriterion, SnapshotOptions, StringList, }, - repository::{IndexedFull, OpenStatus, Repository, RepositoryOptions}, + repository::{ + IndexedFull, IndexedIds, IndexedTree, Open, OpenStatus, Repository, RepositoryOptions, + }, }; diff --git a/crates/core/src/repository.rs b/crates/core/src/repository.rs index dbf71528f..0d53c41e6 100644 --- a/crates/core/src/repository.rs +++ b/crates/core/src/repository.rs @@ -1264,11 +1264,14 @@ pub trait IndexedTree: Open { type I: ReadGlobalIndex; fn index(&self) -> &Self::I; + fn into_open(self) -> impl Open; } /// A repository which is indexed such that all tree blobs are contained in the index /// and additionally the `Id`s of data blobs are also contained in the index. -pub trait IndexedIds: IndexedTree {} +pub trait IndexedIds: IndexedTree { + fn into_indexed_tree(self) -> impl IndexedTree; +} impl IndexedTree for Repository { type I = S::I; @@ -1276,6 +1279,10 @@ impl IndexedTree for Repository { fn index(&self) -> &Self::I { self.status.index() } + + fn into_open(self) -> impl Open { + self.status.into_open() + } } #[derive(Clone, Copy, Debug)] @@ -1330,6 +1337,12 @@ pub struct IndexedStatus { open: S, } +#[derive(Debug, Clone, Copy)] +/// A type of an index, that only contains [`Id`]s. +/// +/// Used for the [`IndexedTrees`] state of a repository in [`IndexedStatus`]. +pub struct TreeIndex; + #[derive(Debug, Clone, Copy)] /// A type of an index, that only contains [`Id`]s. /// @@ -1351,13 +1364,35 @@ impl IndexedTree for IndexedStatus { fn index(&self) -> &Self::I { &self.index } + + fn into_open(self) -> impl Open { + self.open + } } -impl IndexedIds for IndexedStatus {} +impl IndexedIds for IndexedStatus { + fn into_indexed_tree(self) -> impl IndexedTree { + Self { + index: self.index.drop_data(), + ..self + } + } +} -impl IndexedIds for IndexedStatus {} +impl IndexedIds for IndexedStatus { + fn into_indexed_tree(self) -> impl IndexedTree { + Self { + index: self.index.drop_data(), + ..self + } + } +} -impl IndexedIds for Repository {} +impl IndexedIds for Repository { + fn into_indexed_tree(self) -> impl IndexedTree { + self.status.into_indexed_tree() + } +} impl IndexedFull for IndexedStatus { fn get_blob_or_insert_with( @@ -1533,6 +1568,18 @@ impl Repository { ) -> RusticResult { Tree::find_matching_nodes(self.dbe(), self.index(), ids, matches) } + + /// drop the `Repository` index leaving an `Open` `Repository` + pub fn drop_index(self) -> Repository { + Repository { + name: self.name, + be: self.be, + be_hot: self.be_hot, + opts: self.opts, + pb: self.pb, + status: self.status.into_open(), + } + } } impl Repository { @@ -1758,6 +1805,18 @@ impl Repository { pub fn get_blob_cached(&self, id: &Id, tpe: BlobType) -> RusticResult { self.get_blob_or_insert_with(id, || self.index().blob_from_backend(self.dbe(), tpe, id)) } + + /// drop the data pack information from the `Repository` index leaving an `IndexedTree` `Repository` + pub fn drop_data_from_index(self) -> Repository { + Repository { + name: self.name, + be: self.be, + be_hot: self.be_hot, + opts: self.opts, + pb: self.pb, + status: self.status.into_indexed_tree(), + } + } } impl Repository { diff --git a/crates/core/tests/integration.rs b/crates/core/tests/integration.rs index 15e9242b9..9a7924bfb 100644 --- a/crates/core/tests/integration.rs +++ b/crates/core/tests/integration.rs @@ -439,6 +439,8 @@ fn test_prune( let paths = PathList::from_iter(Some(source.0.path().join("0/0/9/3"))); let _ = repo.backup(&opts, &paths, SnapshotFile::default())?; + // drop index + let repo = repo.drop_index(); repo.delete_snapshots(&[snapshot1.id])?; // get prune plan