mirror of https://github.com/dswd/zvault
Using repository aliases
This commit is contained in:
parent
645022ce9c
commit
2fe62cbe27
|
@ -6,6 +6,7 @@ This project follows [semantic versioning](http://semver.org).
|
|||
### UNRELEASED
|
||||
* [added] Added `copy` subcommand
|
||||
* [modified] Also documenting common flags in subcommands
|
||||
* [modified] Using repository aliases (**conversion needed**)
|
||||
|
||||
|
||||
### v0.3.2 (2017-05-11)
|
||||
|
|
|
@ -76,8 +76,10 @@ location.
|
|||
### Path syntax
|
||||
|
||||
Most subcommands work with a repository that has to be specified as a parameter.
|
||||
If this repository is specified as `::`, the default repository in `~/.zvault`
|
||||
will be used instead.
|
||||
If the given repository path is absolute, this path will be used as is.
|
||||
If the given path is relative, the repository will be located in
|
||||
`~/.zvault/repos`. If the path is empty (specified as `::`), the default
|
||||
repository in `~/.zvault/repos/default` will be used.
|
||||
|
||||
Some subcommands need to reference a specific backup in the repository. This is
|
||||
done via the syntax `repository::backup_name` where `repository` is the path to
|
||||
|
|
109
src/cli/args.rs
109
src/cli/args.rs
|
@ -1,13 +1,13 @@
|
|||
use ::prelude::*;
|
||||
use super::*;
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use log::LogLevel;
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
|
||||
pub enum Arguments {
|
||||
Init {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
bundle_size: usize,
|
||||
chunker: ChunkerType,
|
||||
compression: Option<Compression>,
|
||||
|
@ -16,7 +16,7 @@ pub enum Arguments {
|
|||
remote_path: String
|
||||
},
|
||||
Backup {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: String,
|
||||
src_path: String,
|
||||
full: bool,
|
||||
|
@ -28,20 +28,20 @@ pub enum Arguments {
|
|||
tar: bool
|
||||
},
|
||||
Restore {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: String,
|
||||
inode: Option<String>,
|
||||
dst_path: String,
|
||||
tar: bool
|
||||
},
|
||||
Remove {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: String,
|
||||
inode: Option<String>,
|
||||
force: bool
|
||||
},
|
||||
Prune {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
prefix: String,
|
||||
daily: usize,
|
||||
weekly: usize,
|
||||
|
@ -50,13 +50,13 @@ pub enum Arguments {
|
|||
force: bool
|
||||
},
|
||||
Vacuum {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
ratio: f32,
|
||||
force: bool,
|
||||
combine: bool
|
||||
},
|
||||
Check {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: Option<String>,
|
||||
inode: Option<String>,
|
||||
bundles: bool,
|
||||
|
@ -65,56 +65,56 @@ pub enum Arguments {
|
|||
repair: bool
|
||||
},
|
||||
List {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: Option<String>,
|
||||
inode: Option<String>
|
||||
},
|
||||
Info {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: Option<String>,
|
||||
inode: Option<String>
|
||||
},
|
||||
Copy {
|
||||
repo_path_src: String,
|
||||
repo_path_src: PathBuf,
|
||||
backup_name_src: String,
|
||||
repo_path_dst: String,
|
||||
repo_path_dst: PathBuf,
|
||||
backup_name_dst: String,
|
||||
},
|
||||
Mount {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
backup_name: Option<String>,
|
||||
inode: Option<String>,
|
||||
mount_point: String
|
||||
},
|
||||
Versions {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
path: String
|
||||
},
|
||||
Diff {
|
||||
repo_path_old: String,
|
||||
repo_path_old: PathBuf,
|
||||
backup_name_old: String,
|
||||
inode_old: Option<String>,
|
||||
repo_path_new: String,
|
||||
repo_path_new: PathBuf,
|
||||
backup_name_new: String,
|
||||
inode_new: Option<String>
|
||||
},
|
||||
Analyze {
|
||||
repo_path: String
|
||||
repo_path: PathBuf
|
||||
},
|
||||
BundleList {
|
||||
repo_path: String
|
||||
repo_path: PathBuf
|
||||
},
|
||||
BundleInfo {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
bundle_id: BundleId
|
||||
},
|
||||
Import {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
remote_path: String,
|
||||
key_files: Vec<String>
|
||||
},
|
||||
Config {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
bundle_size: Option<usize>,
|
||||
chunker: Option<ChunkerType>,
|
||||
compression: Option<Option<Compression>>,
|
||||
|
@ -126,7 +126,7 @@ pub enum Arguments {
|
|||
password: Option<String>
|
||||
},
|
||||
AddKey {
|
||||
repo_path: String,
|
||||
repo_path: PathBuf,
|
||||
file: Option<String>,
|
||||
password: Option<String>,
|
||||
set_default: bool
|
||||
|
@ -142,16 +142,25 @@ pub enum Arguments {
|
|||
}
|
||||
|
||||
|
||||
fn parse_repo_path(repo_path: &str, existing: bool, backup_restr: Option<bool>, path_restr: Option<bool>) -> Result<(&str, Option<&str>, Option<&str>), String> {
|
||||
let mut parts = repo_path.splitn(3, "::");
|
||||
let mut repo = parts.next().unwrap_or(&DEFAULT_REPOSITORY);
|
||||
if repo.is_empty() {
|
||||
repo = &DEFAULT_REPOSITORY;
|
||||
fn convert_repo_path(mut path_str: &str) -> PathBuf {
|
||||
if path_str.is_empty() {
|
||||
path_str = "default";
|
||||
}
|
||||
if existing && !Path::new(repo).join("config.yaml").exists() {
|
||||
let path = Path::new(path_str);
|
||||
if path.is_absolute() {
|
||||
path.to_path_buf()
|
||||
} else {
|
||||
ZVAULT_FOLDER.join("repos").join(path)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_repo_path(repo_path: &str, existing: bool, backup_restr: Option<bool>, path_restr: Option<bool>) -> Result<(PathBuf, Option<&str>, Option<&str>), String> {
|
||||
let mut parts = repo_path.splitn(3, "::");
|
||||
let repo = convert_repo_path(parts.next().unwrap_or(""));
|
||||
if existing && !repo.join("config.yaml").exists() {
|
||||
return Err("The specified repository does not exist".to_string());
|
||||
}
|
||||
if !existing && Path::new(repo).exists() {
|
||||
if !existing && repo.exists() {
|
||||
return Err("The specified repository already exists".to_string());
|
||||
}
|
||||
let mut backup = parts.next();
|
||||
|
@ -462,14 +471,14 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
compression: parse_compression(args.value_of("compression").unwrap()).unwrap(),
|
||||
encryption: args.is_present("encrypt"),
|
||||
hash: parse_hash(args.value_of("hash").unwrap()).unwrap(),
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
remote_path: args.value_of("remote").unwrap().to_string()
|
||||
}
|
||||
},
|
||||
("backup", Some(args)) => {
|
||||
let (repository, backup, _inode) = parse_repo_path(args.value_of("BACKUP").unwrap(), true, Some(true), Some(false)).unwrap();
|
||||
Arguments::Backup {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.unwrap().to_string(),
|
||||
full: args.is_present("full"),
|
||||
same_device: !args.is_present("cross_device"),
|
||||
|
@ -484,7 +493,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("restore", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("BACKUP").unwrap(), true, Some(true), None).unwrap();
|
||||
Arguments::Restore {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.unwrap().to_string(),
|
||||
inode: inode.map(|v| v.to_string()),
|
||||
dst_path: args.value_of("DST").unwrap().to_string(),
|
||||
|
@ -494,7 +503,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("remove", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("BACKUP").unwrap(), true, Some(true), None).unwrap();
|
||||
Arguments::Remove {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.unwrap().to_string(),
|
||||
inode: inode.map(|v| v.to_string()),
|
||||
force: args.is_present("force")
|
||||
|
@ -503,7 +512,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("prune", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::Prune {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
prefix: args.value_of("prefix").unwrap_or("").to_string(),
|
||||
force: args.is_present("force"),
|
||||
daily: parse_num(args.value_of("daily").unwrap()).unwrap() as usize,
|
||||
|
@ -515,7 +524,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("vacuum", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::Vacuum {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
force: args.is_present("force"),
|
||||
combine: args.is_present("combine"),
|
||||
ratio: parse_num(args.value_of("ratio").unwrap()).unwrap() as f32 / 100.0
|
||||
|
@ -524,7 +533,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("check", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("PATH").unwrap(), true, None, None).unwrap();
|
||||
Arguments::Check {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.map(|v| v.to_string()),
|
||||
inode: inode.map(|v| v.to_string()),
|
||||
bundles: args.is_present("bundles"),
|
||||
|
@ -536,7 +545,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("list", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("PATH").unwrap(), true, None, None).unwrap();
|
||||
Arguments::List {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.map(|v| v.to_string()),
|
||||
inode: inode.map(|v| v.to_string())
|
||||
}
|
||||
|
@ -544,20 +553,20 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("bundlelist", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::BundleList {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
}
|
||||
},
|
||||
("bundleinfo", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::BundleInfo {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
bundle_id: try!(parse_bundle_id(args.value_of("BUNDLE").unwrap()))
|
||||
}
|
||||
},
|
||||
("info", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("PATH").unwrap(), true, None, None).unwrap();
|
||||
Arguments::Info {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.map(|v| v.to_string()),
|
||||
inode: inode.map(|v| v.to_string())
|
||||
}
|
||||
|
@ -566,16 +575,16 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
let (repository_src, backup_src, _inode) = parse_repo_path(args.value_of("SRC").unwrap(), true, Some(true), Some(false)).unwrap();
|
||||
let (repository_dst, backup_dst, _inode) = parse_repo_path(args.value_of("DST").unwrap(), true, Some(true), Some(false)).unwrap();
|
||||
Arguments::Copy {
|
||||
repo_path_src: repository_src.to_string(),
|
||||
repo_path_src: repository_src,
|
||||
backup_name_src: backup_src.unwrap().to_string(),
|
||||
repo_path_dst: repository_dst.to_string(),
|
||||
repo_path_dst: repository_dst,
|
||||
backup_name_dst: backup_dst.unwrap().to_string(),
|
||||
}
|
||||
},
|
||||
("mount", Some(args)) => {
|
||||
let (repository, backup, inode) = parse_repo_path(args.value_of("PATH").unwrap(), true, None, None).unwrap();
|
||||
Arguments::Mount {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
backup_name: backup.map(|v| v.to_string()),
|
||||
inode: inode.map(|v| v.to_string()),
|
||||
mount_point: args.value_of("MOUNTPOINT").unwrap().to_string()
|
||||
|
@ -584,7 +593,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("versions", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::Versions {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
path: args.value_of("PATH").unwrap().to_string()
|
||||
}
|
||||
},
|
||||
|
@ -592,10 +601,10 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
let (repository_old, backup_old, inode_old) = parse_repo_path(args.value_of("OLD").unwrap(), true, Some(true), None).unwrap();
|
||||
let (repository_new, backup_new, inode_new) = parse_repo_path(args.value_of("NEW").unwrap(), true, Some(true), None).unwrap();
|
||||
Arguments::Diff {
|
||||
repo_path_old: repository_old.to_string(),
|
||||
repo_path_old: repository_old,
|
||||
backup_name_old: backup_old.unwrap().to_string(),
|
||||
inode_old: inode_old.map(|v| v.to_string()),
|
||||
repo_path_new: repository_new.to_string(),
|
||||
repo_path_new: repository_new,
|
||||
backup_name_new: backup_new.unwrap().to_string(),
|
||||
inode_new: inode_new.map(|v| v.to_string()),
|
||||
}
|
||||
|
@ -603,13 +612,13 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("analyze", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::Analyze {
|
||||
repo_path: repository.to_string()
|
||||
repo_path: repository
|
||||
}
|
||||
},
|
||||
("import", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), false, Some(false), Some(false)).unwrap();
|
||||
Arguments::Import {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
remote_path: args.value_of("REMOTE").unwrap().to_string(),
|
||||
key_files: args.values_of("key").map(|v| v.map(|k| k.to_string()).collect()).unwrap_or_else(|| vec![])
|
||||
}
|
||||
|
@ -622,7 +631,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
compression: args.value_of("compression").map(|v| parse_compression(v).unwrap()),
|
||||
encryption: args.value_of("encryption").map(|v| parse_public_key(v).unwrap()),
|
||||
hash: args.value_of("hash").map(|v| parse_hash(v).unwrap()),
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
}
|
||||
},
|
||||
("genkey", Some(args)) => {
|
||||
|
@ -634,7 +643,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
("addkey", Some(args)) => {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
|
||||
Arguments::AddKey {
|
||||
repo_path: repository.to_string(),
|
||||
repo_path: repository,
|
||||
set_default: args.is_present("set_default"),
|
||||
password: args.value_of("password").map(|v| v.to_string()),
|
||||
file: args.value_of("FILE").map(|v| v.to_string())
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::io::{BufReader, BufRead};
|
|||
use std::fs::File;
|
||||
use std::env;
|
||||
use std::str;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use self::args::Arguments;
|
||||
|
||||
|
@ -76,8 +76,8 @@ pub const DEFAULT_COMPRESSION: &'static str = "brotli/3";
|
|||
pub const DEFAULT_BUNDLE_SIZE_STR: &'static str = "25";
|
||||
pub const DEFAULT_VACUUM_RATIO_STR: &'static str = "0";
|
||||
lazy_static! {
|
||||
pub static ref DEFAULT_REPOSITORY: String = {
|
||||
env::home_dir().unwrap().join(".zvault").to_string_lossy().to_string()
|
||||
pub static ref ZVAULT_FOLDER: PathBuf = {
|
||||
env::home_dir().unwrap().join(".zvault")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ macro_rules! checked {
|
|||
};
|
||||
}
|
||||
|
||||
fn open_repository(path: &str) -> Result<Repository, ErrorCode> {
|
||||
fn open_repository(path: &Path) -> Result<Repository, ErrorCode> {
|
||||
Ok(checked!(Repository::open(path), "load repository", ErrorCode::LoadRepository))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue