1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
pub mod archive;
pub mod destination;
pub mod driver;
pub use self::archive::{ActiveArchive, StoredArchive};
use crate::repository::backend::Manifest as BackendManifest;
use crate::repository::backend::Result;
use crate::repository::{Backend, BackendClone, ChunkSettings, Repository};
use chrono::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Manifest<T: Backend> {
internal_manifest: T::Manifest,
}
impl<T: BackendClone> Manifest<T> {
pub fn load(repo: &Repository<T>) -> Manifest<T>
where
T: Backend,
{
let internal_manifest = repo.backend_manifest();
Manifest { internal_manifest }
}
pub async fn set_chunk_settings(&mut self, settings: ChunkSettings) -> Result<()> {
self.internal_manifest.write_chunk_settings(settings).await
}
pub async fn chunk_settings(&mut self) -> ChunkSettings {
self.internal_manifest.chunk_settings().await
}
pub async fn commit_archive(
&mut self,
repo: &mut Repository<impl BackendClone>,
archive: ActiveArchive,
) -> Result<()> {
let stored_archive = archive.store(repo).await;
self.internal_manifest.write_archive(stored_archive).await?;
repo.commit_index().await;
Ok(())
}
pub async fn archives(&mut self) -> Vec<StoredArchive> {
self.internal_manifest.archive_iterator().await.collect()
}
pub async fn timestamp(&mut self) -> Result<DateTime<FixedOffset>> {
self.internal_manifest.last_modification().await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::repository::*;
#[test]
fn chunk_settings_sanity() {
smol::block_on(async {
let settings = ChunkSettings {
encryption: Encryption::NoEncryption,
compression: Compression::NoCompression,
hmac: HMAC::Blake2b,
};
let key = Key::random(32);
let backend = crate::repository::backend::mem::Mem::new(settings, key.clone(), 4);
let repo = Repository::with(backend, settings, key, 2);
let mut manifest = Manifest::load(&repo);
manifest.set_chunk_settings(settings).await.unwrap();
let new_settings = manifest.chunk_settings().await;
assert_eq!(settings, new_settings);
});
}
#[test]
fn new_archive_updates_time() {
smol::block_on(async {
let settings = ChunkSettings::lightweight();
let key = Key::random(32);
let backend = crate::repository::backend::mem::Mem::new(settings, key.clone(), 4);
let repo = Repository::with(backend.clone(), settings, key, 2);
let mut manifest = Manifest::load(&repo);
let dummy1 = StoredArchive::dummy_archive();
backend.get_manifest().write_archive(dummy1).await.unwrap();
let time1 = manifest.timestamp().await.unwrap();
std::thread::sleep(std::time::Duration::from_millis(10));
let dummy2 = StoredArchive::dummy_archive();
backend.get_manifest().write_archive(dummy2).await.unwrap();
let time2 = manifest.timestamp().await.unwrap();
assert!(time2 > time1);
});
}
}