mirror of https://github.com/dswd/zvault
Allow stdin/stdout for --tar (closes #12)
This commit is contained in:
parent
12b00b13ec
commit
d06149979a
|
@ -4,6 +4,8 @@ This project follows [semantic versioning](http://semver.org).
|
|||
|
||||
|
||||
### UNRELEASED
|
||||
* [added] Ability to read/write tar file from/to stdin/stdout
|
||||
* [modified] Logging to stderr
|
||||
* [fixed] Only print "repairing bundles" if actually repairing bundles
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ The patterns can be given directly via `--exclude` or be read from a file via
|
|||
exclude pattern is read from the file `excludes` in the repository folder.
|
||||
All exclude pattern given via any of these ways will be combined.
|
||||
|
||||
If `--tar` is specified and `SRC` is `-`, the input is read from stdin.
|
||||
|
||||
Unless `--xdev` is set, zVault will not traverse into subfolders that are on a
|
||||
different filesystem, i.e. mount points will not be included.
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ The backup or backup subtree given by `BACKUP` must be in the format
|
|||
If `repository` is omitted, the default repository location is used instead.
|
||||
|
||||
If `--tar` is set, the data is written to a tar file named `DST`. In this case
|
||||
`DST` must not exist.
|
||||
`DST` must not exist. If `DST` is `-`, the data will be written to stdout.
|
||||
|
||||
If `--tar` is not set, the data will be written into the existing folder `DST`.
|
||||
|
||||
|
|
|
@ -2,8 +2,16 @@ use log::{self, LogRecord, LogLevel, LogMetadata};
|
|||
pub use log::SetLoggerError;
|
||||
|
||||
use ansi_term::{Color, Style};
|
||||
use std::io::Write;
|
||||
|
||||
|
||||
macro_rules! println_stderr(
|
||||
($($arg:tt)*) => { {
|
||||
let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
|
||||
r.expect("failed printing to stderr");
|
||||
} }
|
||||
);
|
||||
|
||||
struct Logger(LogLevel);
|
||||
|
||||
impl log::Log for Logger {
|
||||
|
@ -14,11 +22,11 @@ impl log::Log for Logger {
|
|||
fn log(&self, record: &LogRecord) {
|
||||
if self.enabled(record.metadata()) {
|
||||
match record.level() {
|
||||
LogLevel::Error => println!("{}: {}", Color::Red.bold().paint("error"), record.args()),
|
||||
LogLevel::Warn => println!("{}: {}", Color::Yellow.bold().paint("warning"), record.args()),
|
||||
LogLevel::Info => println!("{}: {}", Color::Green.bold().paint("info"), record.args()),
|
||||
LogLevel::Debug => println!("{}: {}", Style::new().bold().paint("debug"), record.args()),
|
||||
LogLevel::Trace => println!("{}: {}", "trace", record.args())
|
||||
LogLevel::Error => println_stderr!("{}: {}", Color::Red.bold().paint("error"), record.args()),
|
||||
LogLevel::Warn => println_stderr!("{}: {}", Color::Yellow.bold().paint("warning"), record.args()),
|
||||
LogLevel::Info => println_stderr!("{}: {}", Color::Green.bold().paint("info"), record.args()),
|
||||
LogLevel::Debug => println_stderr!("{}: {}", Style::new().bold().paint("debug"), record.args()),
|
||||
LogLevel::Trace => println_stderr!("{}: {}", "trace", record.args())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use ::prelude::*;
|
|||
|
||||
use std::collections::{HashMap, HashSet, BTreeMap};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::{Read, Cursor};
|
||||
use std::io::{self, Read, Write, Cursor};
|
||||
use std::fs::File;
|
||||
use std::str;
|
||||
|
||||
|
@ -71,8 +71,8 @@ impl Repository {
|
|||
Ok(inode)
|
||||
}
|
||||
|
||||
fn import_tarfile_as_inode<P: AsRef<Path>>(&mut self, backup: &mut Backup, tarfile: P, failed_paths: &mut Vec<PathBuf>) -> Result<(Inode, ChunkList), RepositoryError> {
|
||||
let mut tarfile = tar::Archive::new(try!(File::open(tarfile)));
|
||||
fn import_tarfile_as_inode<R: Read>(&mut self, backup: &mut Backup, input: R, failed_paths: &mut Vec<PathBuf>) -> Result<(Inode, ChunkList), RepositoryError> {
|
||||
let mut tarfile = tar::Archive::new(input);
|
||||
// Step 1: create inodes for all entries
|
||||
let mut inodes = HashMap::<PathBuf, (Inode, HashSet<String>)>::new();
|
||||
for entry in try!(tarfile.entries()) {
|
||||
|
@ -185,7 +185,12 @@ impl Repository {
|
|||
let info_before = self.info();
|
||||
let start = Local::now();
|
||||
let mut failed_paths = vec![];
|
||||
let (root_inode, chunks) = try!(self.import_tarfile_as_inode(&mut backup, tarfile, &mut failed_paths));
|
||||
let tarfile = tarfile.as_ref();
|
||||
let (root_inode, chunks) = if tarfile == Path::new("-") {
|
||||
try!(self.import_tarfile_as_inode(&mut backup, try!(File::open(tarfile)), &mut failed_paths))
|
||||
} else {
|
||||
try!(self.import_tarfile_as_inode(&mut backup, io::stdin(), &mut failed_paths))
|
||||
};
|
||||
backup.root = chunks;
|
||||
try!(self.flush());
|
||||
let elapsed = Local::now().signed_duration_since(start);
|
||||
|
@ -208,7 +213,7 @@ impl Repository {
|
|||
}
|
||||
}
|
||||
|
||||
fn export_xattrs(&mut self, inode: &Inode, tarfile: &mut tar::Builder<File>) -> Result<(), RepositoryError> {
|
||||
fn export_xattrs<W: Write>(&mut self, inode: &Inode, tarfile: &mut tar::Builder<W>) -> Result<(), RepositoryError> {
|
||||
let mut data = Vec::new();
|
||||
for (key, value) in &inode.xattrs {
|
||||
let mut len_len = 1;
|
||||
|
@ -231,7 +236,7 @@ impl Repository {
|
|||
Ok(try!(tarfile.append(&header, Cursor::new(&data))))
|
||||
}
|
||||
|
||||
fn export_tarfile_recurse(&mut self, backup: &Backup, path: &Path, inode: Inode, tarfile: &mut tar::Builder<File>) -> Result<(), RepositoryError> {
|
||||
fn export_tarfile_recurse<W: Write>(&mut self, backup: &Backup, path: &Path, inode: Inode, tarfile: &mut tar::Builder<W>) -> Result<(), RepositoryError> {
|
||||
if !inode.xattrs.is_empty() {
|
||||
try!(self.export_xattrs(&inode, tarfile));
|
||||
}
|
||||
|
@ -277,9 +282,16 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn export_tarfile<P: AsRef<Path>>(&mut self, backup: &Backup, inode: Inode, tarfile: P) -> Result<(), RepositoryError> {
|
||||
let tarfile = tarfile.as_ref();
|
||||
if tarfile == Path::new("-") {
|
||||
let mut tarfile = tar::Builder::new(io::stdout());
|
||||
try!(self.export_tarfile_recurse(backup, Path::new(""), inode, &mut tarfile));
|
||||
try!(tarfile.finish());
|
||||
} else {
|
||||
let mut tarfile = tar::Builder::new(try!(File::create(tarfile)));
|
||||
try!(self.export_tarfile_recurse(backup, Path::new(""), inode, &mut tarfile));
|
||||
try!(tarfile.finish());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue