mirror of https://github.com/dswd/zvault
Refactor layout
This commit is contained in:
parent
0b5a485a26
commit
ca1916145f
|
@ -4,29 +4,37 @@ use ::prelude::*;
|
|||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
pub struct BackupRepository {
|
||||
layout: Arc<RepositoryLayout>,
|
||||
repo: Repository
|
||||
}
|
||||
|
||||
impl BackupRepository {
|
||||
pub fn create<P: AsRef<Path>, R: AsRef<Path>>(path: P, config: &Config, remote: R) -> Result<Self, RepositoryError> {
|
||||
let layout = Arc::new(RepositoryLayout::new(path.as_ref()));
|
||||
Ok(BackupRepository {
|
||||
repo: try!(Repository::create(path, config, remote))
|
||||
layout: layout.clone(),
|
||||
repo: try!(Repository::create(layout, config, remote))
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unknown_lints, useless_let_if_seq)]
|
||||
pub fn open<P: AsRef<Path>>(path: P, online: bool) -> Result<Self, RepositoryError> {
|
||||
let layout = Arc::new(RepositoryLayout::new(path.as_ref()));
|
||||
Ok(BackupRepository {
|
||||
repo: try!(Repository::open(path, online))
|
||||
layout: layout.clone(),
|
||||
repo: try!(Repository::open(layout, online))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn import<P: AsRef<Path>, R: AsRef<Path>>(path: P, remote: R, key_files: Vec<String>) -> Result<Self, RepositoryError> {
|
||||
let layout = Arc::new(RepositoryLayout::new(path.as_ref()));
|
||||
Ok(BackupRepository {
|
||||
repo: try!(Repository::import(path, remote, key_files))
|
||||
layout: layout.clone(),
|
||||
repo: try!(Repository::import(layout, remote, key_files))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,7 +85,7 @@ impl BackupRepository {
|
|||
}
|
||||
|
||||
pub fn get_layout(&self) -> &RepositoryLayout {
|
||||
&self.repo.layout
|
||||
&self.layout
|
||||
}
|
||||
|
||||
pub fn create_backup_recursively<P: AsRef<Path>>(&mut self, path: P, reference: Option<&Backup>, options: &BackupOptions) -> Result<Backup, RepositoryError> {
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use repository::chunking::{ChunkerType, Chunker, ChunkerStatus, ChunkerError
|
|||
pub use repository::{Repository, Backup, Config, RepositoryError, RepositoryInfo, Inode, FileType,
|
||||
IntegrityError, BackupFileError, BackupError, BackupOptions, BundleAnalysis,
|
||||
FileData, DiffType, InodeError, RepositoryLayout, Location,
|
||||
RepositoryStatistics};
|
||||
RepositoryStatistics, ChunkRepositoryLayout};
|
||||
pub use repository::index::{Index, IndexError, IndexStatistics};
|
||||
pub use backups::mount::FuseFilesystem;
|
||||
pub use translation::CowStr;
|
||||
|
|
|
@ -117,7 +117,7 @@ fn load_bundles(
|
|||
|
||||
|
||||
pub struct BundleDb {
|
||||
pub layout: RepositoryLayout,
|
||||
pub layout: Arc<ChunkRepositoryLayout>,
|
||||
uploader: Option<Arc<BundleUploader>>,
|
||||
crypto: Arc<Mutex<Crypto>>,
|
||||
local_bundles: HashMap<BundleId, StoredBundle>,
|
||||
|
@ -127,7 +127,7 @@ pub struct BundleDb {
|
|||
|
||||
|
||||
impl BundleDb {
|
||||
fn new(layout: RepositoryLayout, crypto: Arc<Mutex<Crypto>>) -> Self {
|
||||
fn new(layout: Arc<ChunkRepositoryLayout>, crypto: Arc<Mutex<Crypto>>) -> Self {
|
||||
BundleDb {
|
||||
layout,
|
||||
crypto,
|
||||
|
@ -239,7 +239,7 @@ impl BundleDb {
|
|||
}
|
||||
|
||||
pub fn open(
|
||||
layout: RepositoryLayout,
|
||||
layout: Arc<ChunkRepositoryLayout>,
|
||||
crypto: Arc<Mutex<Crypto>>,
|
||||
online: bool
|
||||
) -> Result<(Self, Vec<BundleInfo>, Vec<BundleInfo>), BundleDbError> {
|
||||
|
@ -251,7 +251,7 @@ impl BundleDb {
|
|||
Ok((self_, new, gone))
|
||||
}
|
||||
|
||||
pub fn create(layout: &RepositoryLayout) -> Result<(), BundleDbError> {
|
||||
pub fn create(layout: Arc<ChunkRepositoryLayout>) -> Result<(), BundleDbError> {
|
||||
try!(fs::create_dir_all(layout.remote_bundles_path()).context(
|
||||
&layout.remote_bundles_path() as
|
||||
&Path
|
||||
|
@ -332,11 +332,14 @@ impl BundleDb {
|
|||
|
||||
fn copy_remote_bundle_to_cache(&mut self, bundle: &StoredBundle) -> Result<(), BundleDbError> {
|
||||
let id = bundle.id();
|
||||
let (folder, filename) = self.layout.local_bundle_path(&id, self.local_bundles.len());
|
||||
try!(fs::create_dir_all(&folder).context(&folder as &Path));
|
||||
let dst_path = self.layout.local_bundle_path(&id, self.local_bundles.len());
|
||||
{
|
||||
let folder = dst_path.parent().unwrap();
|
||||
try!(fs::create_dir_all(folder).context(folder as &Path));
|
||||
}
|
||||
let bundle = try!(bundle.copy_to(
|
||||
self.layout.base_path(),
|
||||
folder.join(filename)
|
||||
dst_path
|
||||
));
|
||||
self.local_bundles.insert(id, bundle);
|
||||
Ok(())
|
||||
|
@ -347,8 +350,7 @@ impl BundleDb {
|
|||
if bundle.info.mode == BundleMode::Meta {
|
||||
try!(self.copy_remote_bundle_to_cache(&bundle))
|
||||
}
|
||||
let (folder, filename) = self.layout.remote_bundle_path(self.remote_bundles.len());
|
||||
let dst_path = folder.join(filename);
|
||||
let dst_path = self.layout.remote_bundle_path(&bundle.id(),self.remote_bundles.len());
|
||||
let src_path = self.layout.base_path().join(bundle.path);
|
||||
bundle.path = dst_path
|
||||
.strip_prefix(self.layout.base_path())
|
||||
|
|
|
@ -2,6 +2,35 @@ use prelude::*;
|
|||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub trait ChunkRepositoryLayout {
|
||||
fn base_path(&self) -> &Path;
|
||||
|
||||
fn index_path(&self) -> PathBuf;
|
||||
fn bundle_map_path(&self) -> PathBuf;
|
||||
fn local_locks_path(&self) -> PathBuf;
|
||||
fn remote_path(&self) -> PathBuf;
|
||||
fn remote_exists(&self) -> bool;
|
||||
fn remote_locks_path(&self) -> PathBuf;
|
||||
fn remote_bundles_path(&self) -> PathBuf;
|
||||
fn local_bundles_path(&self) -> PathBuf;
|
||||
fn remote_bundle_path(&self, bundle: &BundleId, count: usize) -> PathBuf;
|
||||
fn local_bundle_path(&self, bundle: &BundleId, count: usize) -> PathBuf;
|
||||
fn temp_bundles_path(&self) -> PathBuf;
|
||||
fn temp_bundle_path(&self) -> PathBuf;
|
||||
fn local_bundle_cache_path(&self) -> PathBuf;
|
||||
fn remote_bundle_cache_path(&self) -> PathBuf;
|
||||
fn dirtyfile_path(&self) -> PathBuf;
|
||||
|
||||
|
||||
fn config_path(&self) -> PathBuf;
|
||||
fn keys_path(&self) -> PathBuf;
|
||||
fn excludes_path(&self) -> PathBuf;
|
||||
fn backups_path(&self) -> PathBuf;
|
||||
fn backup_path(&self, name: &str) -> PathBuf;
|
||||
fn remote_readme_path(&self) -> PathBuf;
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RepositoryLayout(PathBuf);
|
||||
|
||||
|
@ -10,39 +39,19 @@ impl RepositoryLayout {
|
|||
RepositoryLayout(path.as_ref().to_path_buf())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn base_path(&self) -> &Path {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn config_path(&self) -> PathBuf {
|
||||
self.0.join("config.yaml")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn excludes_path(&self) -> PathBuf {
|
||||
self.0.join("excludes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn index_path(&self) -> PathBuf {
|
||||
self.0.join("index")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn keys_path(&self) -> PathBuf {
|
||||
self.0.join("keys")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bundle_map_path(&self) -> PathBuf {
|
||||
self.0.join("bundles.map")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_locks_path(&self) -> PathBuf {
|
||||
self.0.join("locks")
|
||||
pub fn excludes_path(&self) -> PathBuf {
|
||||
self.0.join("excludes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -55,11 +64,6 @@ impl RepositoryLayout {
|
|||
self.backups_path().join(format!("{}.backup", name))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_path(&self) -> PathBuf {
|
||||
self.0.join("remote")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_exists(&self) -> bool {
|
||||
self.remote_bundles_path().exists() && self.backups_path().exists() &&
|
||||
|
@ -71,27 +75,7 @@ impl RepositoryLayout {
|
|||
self.0.join("remote/README.md")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_locks_path(&self) -> PathBuf {
|
||||
self.0.join("remote/locks")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_bundles_path(&self) -> PathBuf {
|
||||
self.0.join("remote/bundles")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_bundles_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/cached")
|
||||
}
|
||||
|
||||
fn bundle_path(
|
||||
&self,
|
||||
bundle: &BundleId,
|
||||
mut folder: PathBuf,
|
||||
mut count: usize,
|
||||
) -> (PathBuf, PathBuf) {
|
||||
fn bundle_path(&self, bundle: &BundleId, mut folder: PathBuf, mut count: usize) -> PathBuf {
|
||||
let file = bundle.to_string().to_owned() + ".bundle";
|
||||
{
|
||||
let mut rest = &file as &str;
|
||||
|
@ -104,44 +88,123 @@ impl RepositoryLayout {
|
|||
count /= 250;
|
||||
}
|
||||
}
|
||||
(folder, file.into())
|
||||
folder.join(Path::new(&file))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl ChunkRepositoryLayout for RepositoryLayout {
|
||||
#[inline]
|
||||
fn base_path(&self) -> &Path {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_bundle_path(&self, count: usize) -> (PathBuf, PathBuf) {
|
||||
fn remote_exists(&self) -> bool {
|
||||
self.remote_bundles_path().exists() && self.remote_locks_path().exists()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_path(&self) -> PathBuf {
|
||||
self.0.join("index")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bundle_map_path(&self) -> PathBuf {
|
||||
self.0.join("bundles.map")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn local_locks_path(&self) -> PathBuf {
|
||||
self.0.join("locks")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_path(&self) -> PathBuf {
|
||||
self.0.join("remote")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_locks_path(&self) -> PathBuf {
|
||||
self.0.join("remote/locks")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_bundles_path(&self) -> PathBuf {
|
||||
self.0.join("remote/bundles")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn local_bundles_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/cached")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_bundle_path(&self, _bundle: &BundleId, count: usize) -> PathBuf {
|
||||
self.bundle_path(&BundleId::random(), self.remote_bundles_path(), count)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_bundle_path(&self, bundle: &BundleId, count: usize) -> (PathBuf, PathBuf) {
|
||||
fn local_bundle_path(&self, bundle: &BundleId, count: usize) -> PathBuf {
|
||||
self.bundle_path(bundle, self.local_bundles_path(), count)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn temp_bundles_path(&self) -> PathBuf {
|
||||
fn temp_bundles_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/temp")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn temp_bundle_path(&self) -> PathBuf {
|
||||
self.temp_bundles_path().join(
|
||||
BundleId::random().to_string().to_owned() +
|
||||
".bundle"
|
||||
)
|
||||
fn temp_bundle_path(&self) -> PathBuf {
|
||||
self.temp_bundles_path().join(BundleId::random().to_string().to_owned() + ".bundle")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_bundle_cache_path(&self) -> PathBuf {
|
||||
fn local_bundle_cache_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/local.cache")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remote_bundle_cache_path(&self) -> PathBuf {
|
||||
fn remote_bundle_cache_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/remote.cache")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dirtyfile_path(&self) -> PathBuf {
|
||||
fn dirtyfile_path(&self) -> PathBuf {
|
||||
self.0.join("dirty")
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[inline]
|
||||
fn config_path(&self) -> PathBuf {
|
||||
self.0.join("config.yaml")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn keys_path(&self) -> PathBuf {
|
||||
self.0.join("keys")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn excludes_path(&self) -> PathBuf {
|
||||
self.0.join("excludes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backups_path(&self) -> PathBuf {
|
||||
self.0.join("remote/backups")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backup_path(&self, name: &str) -> PathBuf {
|
||||
self.backups_path().join(format!("{}.backup", name))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_readme_path(&self) -> PathBuf {
|
||||
self.0.join("remote/README.md")
|
||||
}
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@ pub use self::backup::{BackupError, BackupOptions, DiffType};
|
|||
pub use self::backup_file::{Backup, BackupFileError};
|
||||
pub use self::integrity::IntegrityError;
|
||||
pub use self::info::{RepositoryInfo, BundleAnalysis, RepositoryStatistics};
|
||||
pub use self::layout::RepositoryLayout;
|
||||
pub use self::layout::{RepositoryLayout, ChunkRepositoryLayout};
|
||||
use self::bundle_map::BundleMap;
|
||||
|
||||
|
||||
|
@ -74,7 +74,7 @@ impl index::Key for Hash {
|
|||
}
|
||||
|
||||
pub struct Repository {
|
||||
pub layout: RepositoryLayout,
|
||||
pub layout: Arc<ChunkRepositoryLayout>,
|
||||
pub config: Config,
|
||||
index: Index<Hash, Location>,
|
||||
crypto: Arc<Mutex<Crypto>>,
|
||||
|
@ -93,12 +93,11 @@ pub struct Repository {
|
|||
|
||||
|
||||
impl Repository {
|
||||
pub fn create<P: AsRef<Path>, R: AsRef<Path>>(
|
||||
path: P,
|
||||
pub fn create<R: AsRef<Path>>(
|
||||
layout: Arc<ChunkRepositoryLayout>,
|
||||
config: &Config,
|
||||
remote: R,
|
||||
) -> Result<Self, RepositoryError> {
|
||||
let layout = RepositoryLayout::new(path.as_ref().to_path_buf());
|
||||
try!(fs::create_dir(layout.base_path()));
|
||||
try!(File::create(layout.excludes_path()).and_then(|mut f| {
|
||||
f.write_all(DEFAULT_EXCLUDES)
|
||||
|
@ -113,7 +112,7 @@ impl Repository {
|
|||
));
|
||||
try!(fs::create_dir_all(layout.remote_locks_path()));
|
||||
try!(config.save(layout.config_path()));
|
||||
try!(BundleDb::create(&layout));
|
||||
try!(BundleDb::create(layout.clone()));
|
||||
try!(Index::<Hash, Location>::create(
|
||||
layout.index_path(),
|
||||
&INDEX_MAGIC,
|
||||
|
@ -121,12 +120,11 @@ impl Repository {
|
|||
));
|
||||
try!(BundleMap::create().save(layout.bundle_map_path()));
|
||||
try!(fs::create_dir_all(layout.backups_path()));
|
||||
Self::open(path, true)
|
||||
Self::open(layout, true)
|
||||
}
|
||||
|
||||
#[allow(unknown_lints, useless_let_if_seq)]
|
||||
pub fn open<P: AsRef<Path>>(path: P, online: bool) -> Result<Self, RepositoryError> {
|
||||
let layout = RepositoryLayout::new(path.as_ref().to_path_buf());
|
||||
pub fn open(layout: Arc<ChunkRepositoryLayout>, online: bool) -> Result<Self, RepositoryError> {
|
||||
if !layout.remote_exists() {
|
||||
return Err(RepositoryError::NoRemote);
|
||||
}
|
||||
|
@ -220,17 +218,16 @@ impl Repository {
|
|||
Ok(repo)
|
||||
}
|
||||
|
||||
pub fn import<P: AsRef<Path>, R: AsRef<Path>>(
|
||||
path: P,
|
||||
pub fn import<R: AsRef<Path>>(
|
||||
layout: Arc<ChunkRepositoryLayout>,
|
||||
remote: R,
|
||||
key_files: Vec<String>,
|
||||
) -> Result<Self, RepositoryError> {
|
||||
let path = path.as_ref();
|
||||
let mut repo = try!(Repository::create(path, &Config::default(), remote));
|
||||
let mut repo = try!(Repository::create(layout.clone(), &Config::default(), remote));
|
||||
for file in key_files {
|
||||
try!(repo.crypto.lock().unwrap().register_keyfile(file));
|
||||
}
|
||||
repo = try!(Repository::open(path, true));
|
||||
repo = try!(Repository::open(layout, true));
|
||||
let mut backups: Vec<(String, Backup)> = try!(repo.get_all_backups()).into_iter().collect();
|
||||
backups.sort_by_key(|&(_, ref b)| b.timestamp);
|
||||
if let Some((name, backup)) = backups.pop() {
|
||||
|
|
Loading…
Reference in New Issue