impl ReadSource for stdin

This commit is contained in:
Alexander Weiss 2023-02-15 22:36:22 +01:00
parent 8ca3a99ab2
commit f4896e7e57
4 changed files with 83 additions and 50 deletions

View File

@ -1,4 +1,3 @@
use std::io::Read;
use std::path::{Path, PathBuf};
use anyhow::Result;
@ -7,11 +6,11 @@ use indicatif::ProgressBar;
use log::*;
use crate::backend::{DecryptWriteBackend, ReadSource, ReadSourceEntry};
use crate::blob::{BlobType, Node};
use crate::blob::BlobType;
use crate::index::{IndexedBackend, Indexer, SharedIndexer};
use crate::repofile::{ConfigFile, SnapshotFile};
use super::{FileArchiver, Parent, ParentResult, TreeArchiver, TreeIterator};
use super::{FileArchiver, Parent, TreeArchiver, TreeIterator};
pub struct Archiver<BE: DecryptWriteBackend, I: IndexedBackend> {
file_archiver: FileArchiver<BE, I>,
@ -53,6 +52,13 @@ impl<BE: DecryptWriteBackend, I: IndexedBackend> Archiver<BE, I> {
as_path: Option<&PathBuf>,
p: &ProgressBar,
) -> Result<SnapshotFile> {
if !p.is_hidden() {
if let Some(size) = src.size()? {
p.set_length(size);
}
};
p.set_prefix("backing up...");
// filter out errors and handle as_path
let iter = src.entries().filter_map(|item| match item {
Err(e) => {
@ -108,22 +114,10 @@ impl<BE: DecryptWriteBackend, I: IndexedBackend> Archiver<BE, I> {
}
let snap = self.finalize_snapshot()?;
p.finish_with_message("done");
Ok(snap)
}
pub fn backup_reader(
&mut self,
path: &Path,
r: impl Read + Send + 'static,
node: Node,
parent: ParentResult<()>,
p: ProgressBar,
) -> Result<()> {
let (node, filesize) = self.file_archiver.backup_reader(r, node, p)?;
self.tree_archiver.add_file(path, node, parent, filesize);
Ok(())
}
pub fn finalize_snapshot(mut self) -> Result<SnapshotFile> {
let stats = self.file_archiver.finalize()?;
let (id, mut summary) = self.tree_archiver.finalize()?;

View File

@ -17,6 +17,7 @@ pub mod local;
pub mod node;
pub mod rclone;
pub mod rest;
pub mod stdin;
pub use self::ignore::*;
pub use cache::*;
@ -28,6 +29,7 @@ pub use local::*;
use node::Node;
pub use rclone::*;
pub use rest::*;
pub use stdin::*;
/// All [`FileType`]s which are located in separated directories
pub const ALL_FILE_TYPES: [FileType; 4] = [

63
src/backend/stdin.rs Normal file
View File

@ -0,0 +1,63 @@
use std::io::{stdin, Stdin};
use std::path::Path;
use anyhow::Result;
use super::{node::Metadata, node::NodeType, Node, ReadSource};
use super::{ReadSourceEntry, ReadSourceOpen};
pub struct StdinSource {
finished: bool,
}
impl StdinSource {
pub fn new() -> Result<Self> {
Ok(Self { finished: false })
}
}
pub struct OpenStdin();
impl ReadSourceOpen for OpenStdin {
type Reader = Stdin;
fn open(self) -> Result<Self::Reader> {
Ok(stdin())
}
}
impl ReadSource for StdinSource {
type Open = OpenStdin;
type Iter = Self;
fn size(&self) -> Result<Option<u64>> {
Ok(None)
}
fn entries(self) -> Self::Iter {
self
}
}
impl Iterator for StdinSource {
type Item = Result<ReadSourceEntry<OpenStdin>>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
self.finished = true;
Some(Ok(ReadSourceEntry {
path: Path::new("stdin").to_path_buf(),
node: Node::new(
"stdin".to_string(),
NodeType::File,
Metadata::default(),
None,
None,
),
open: Some(OpenStdin()),
}))
}
}

View File

@ -11,9 +11,8 @@ use serde::Deserialize;
use toml::Value;
use super::{bytes, progress_bytes, progress_counter, RusticConfig};
use crate::archiver::{Archiver, Parent, ParentResult};
use crate::backend::{DryRunBackend, LocalSource, LocalSourceOptions, ReadSource};
use crate::blob::{Metadata, Node, NodeType};
use crate::archiver::{Archiver, Parent};
use crate::backend::{DryRunBackend, LocalSource, LocalSourceOptions, StdinSource};
use crate::index::IndexBackend;
use crate::repofile::{
PathList, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, SnapshotOptions,
@ -209,40 +208,15 @@ pub(super) fn execute(
let parent = Parent::new(&index, parent_tree, opts.ignore_ctime, opts.ignore_inode);
let snap = if backup_stdin {
let mut archiver = Archiver::new(be, index, &repo.config, parent, snap)?;
let p = progress_bytes("starting backup from stdin...");
archiver.backup_reader(
&PathBuf::new(),
std::io::stdin(),
Node::new(
opts.stdin_filename,
NodeType::File,
Metadata::default(),
None,
None,
),
ParentResult::NotFound,
p.clone(),
)?;
let archiver = Archiver::new(be, index, &repo.config, parent, snap)?;
let p = progress_bytes("determining size...");
let snap = archiver.finalize_snapshot()?;
p.finish_with_message("done");
snap
let snap = if backup_stdin {
let src = StdinSource::new()?;
archiver.archive(src, &backup_path[0], as_path.as_ref(), &p)?
} else {
let src = LocalSource::new(opts.ignore_opts.clone(), &backup_path)?;
let p = progress_bytes("determining size...");
if !p.is_hidden() {
if let Some(size) = src.size()? {
p.set_length(size);
}
};
p.set_prefix("backing up...");
let archiver = Archiver::new(be, index.clone(), &repo.config, parent, snap)?;
let snap = archiver.archive(src, &backup_path[0], as_path.as_ref(), &p)?;
p.finish_with_message("done");
snap
archiver.archive(src, &backup_path[0], as_path.as_ref(), &p)?
};
if opts.json {