mirror of
https://github.com/rustic-rs/rustic.git
synced 2025-10-26 11:18:51 +00:00
cat/ls/restore: Add filtering for latest snapshot
This commit is contained in:
parent
bce9a13924
commit
3d73e2014d
@ -5,11 +5,12 @@ use clap::{Parser, Subcommand};
|
||||
use indicatif::ProgressBar;
|
||||
|
||||
use super::progress_counter;
|
||||
use super::rustic_config::RusticConfig;
|
||||
use crate::backend::{DecryptReadBackend, FileType};
|
||||
use crate::blob::{BlobType, Tree};
|
||||
use crate::id::Id;
|
||||
use crate::index::{IndexBackend, IndexedBackend};
|
||||
use crate::repo::SnapshotFile;
|
||||
use crate::repo::{SnapshotFile, SnapshotFilter};
|
||||
|
||||
#[derive(Parser)]
|
||||
pub(super) struct Opts {
|
||||
@ -41,12 +42,19 @@ struct IdOpt {
|
||||
|
||||
#[derive(Parser)]
|
||||
struct TreeOpts {
|
||||
#[clap(flatten, help_heading = "SNAPSHOT FILTER OPTIONS (when using latest)")]
|
||||
filter: SnapshotFilter,
|
||||
|
||||
/// Snapshot/path of the tree to display
|
||||
#[clap(value_name = "SNAPSHOT[:PATH]")]
|
||||
snap: String,
|
||||
}
|
||||
|
||||
pub(super) fn execute(be: &impl DecryptReadBackend, opts: Opts) -> Result<()> {
|
||||
pub(super) fn execute(
|
||||
be: &impl DecryptReadBackend,
|
||||
opts: Opts,
|
||||
config_file: RusticConfig,
|
||||
) -> Result<()> {
|
||||
match opts.command {
|
||||
Command::Config => cat_file(be, FileType::Config, IdOpt::default()),
|
||||
Command::Index(opt) => cat_file(be, FileType::Index, opt),
|
||||
@ -55,7 +63,7 @@ pub(super) fn execute(be: &impl DecryptReadBackend, opts: Opts) -> Result<()> {
|
||||
Command::TreeBlob(opt) => cat_blob(be, BlobType::Tree, opt),
|
||||
Command::DataBlob(opt) => cat_blob(be, BlobType::Data, opt),
|
||||
// special treatment for cating a tree within a snapshot
|
||||
Command::Tree(opts) => cat_tree(be, opts),
|
||||
Command::Tree(opts) => cat_tree(be, opts, config_file),
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,9 +83,15 @@ fn cat_blob(be: &impl DecryptReadBackend, tpe: BlobType, opt: IdOpt) -> Result<(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cat_tree(be: &impl DecryptReadBackend, opts: TreeOpts) -> Result<()> {
|
||||
fn cat_tree(
|
||||
be: &impl DecryptReadBackend,
|
||||
mut opts: TreeOpts,
|
||||
config_file: RusticConfig,
|
||||
) -> Result<()> {
|
||||
config_file.merge_into("snapshot-filter", &mut opts.filter)?;
|
||||
|
||||
let (id, path) = opts.snap.split_once(':').unwrap_or((&opts.snap, ""));
|
||||
let snap = SnapshotFile::from_str(be, id, |_| true, progress_counter(""))?;
|
||||
let snap = SnapshotFile::from_str(be, id, |sn| sn.matches(&opts.filter), progress_counter(""))?;
|
||||
let index = IndexBackend::new(be, progress_counter(""))?;
|
||||
let id = Tree::subtree_id(&index, snap.tree, Path::new(path))?;
|
||||
let data = index.blob_from_backend(&BlobType::Tree, &id)?;
|
||||
|
||||
@ -3,21 +3,31 @@ use clap::Parser;
|
||||
use std::path::Path;
|
||||
|
||||
use super::progress_counter;
|
||||
use super::rustic_config::RusticConfig;
|
||||
use crate::backend::DecryptReadBackend;
|
||||
use crate::blob::{NodeStreamer, Tree};
|
||||
use crate::index::IndexBackend;
|
||||
use crate::repo::SnapshotFile;
|
||||
use crate::repo::{SnapshotFile, SnapshotFilter};
|
||||
|
||||
#[derive(Parser)]
|
||||
pub(super) struct Opts {
|
||||
#[clap(flatten, help_heading = "SNAPSHOT FILTER OPTIONS (when using latest)")]
|
||||
filter: SnapshotFilter,
|
||||
|
||||
/// Snapshot/path to list
|
||||
#[clap(value_name = "SNAPSHOT[:PATH]")]
|
||||
snap: String,
|
||||
}
|
||||
|
||||
pub(super) fn execute(be: &(impl DecryptReadBackend + Unpin), opts: Opts) -> Result<()> {
|
||||
pub(super) fn execute(
|
||||
be: &impl DecryptReadBackend,
|
||||
mut opts: Opts,
|
||||
config_file: RusticConfig,
|
||||
) -> Result<()> {
|
||||
config_file.merge_into("snapshot-filter", &mut opts.filter)?;
|
||||
|
||||
let (id, path) = opts.snap.split_once(':').unwrap_or((&opts.snap, ""));
|
||||
let snap = SnapshotFile::from_str(be, id, |_| true, progress_counter(""))?;
|
||||
let snap = SnapshotFile::from_str(be, id, |sn| sn.matches(&opts.filter), progress_counter(""))?;
|
||||
let index = IndexBackend::new(be, progress_counter(""))?;
|
||||
let tree = Tree::subtree_id(&index, snap.tree, Path::new(path))?;
|
||||
|
||||
|
||||
@ -309,7 +309,7 @@ pub fn execute() -> Result<()> {
|
||||
match cmd {
|
||||
Command::Backup(opts) => backup::execute(&dbe, opts, config, config_file, command)?,
|
||||
Command::Config(opts) => config::execute(&dbe, &be_hot, opts, config)?,
|
||||
Command::Cat(opts) => cat::execute(&dbe, opts)?,
|
||||
Command::Cat(opts) => cat::execute(&dbe, opts, config_file)?,
|
||||
Command::Check(opts) => check::execute(&dbe, &cache, &be_hot, &be, opts)?,
|
||||
Command::Completions(_) => {} // already handled above
|
||||
Command::Diff(opts) => diff::execute(&dbe, opts)?,
|
||||
@ -317,11 +317,11 @@ pub fn execute() -> Result<()> {
|
||||
Command::Init(_) => {} // already handled above
|
||||
Command::Key(opts) => key::execute(&dbe, key, opts)?,
|
||||
Command::List(opts) => list::execute(&dbe, opts)?,
|
||||
Command::Ls(opts) => ls::execute(&dbe, opts)?,
|
||||
Command::Ls(opts) => ls::execute(&dbe, opts, config_file)?,
|
||||
Command::SelfUpdate(_) => {} // already handled above
|
||||
Command::Snapshots(opts) => snapshots::execute(&dbe, opts, config_file)?,
|
||||
Command::Prune(opts) => prune::execute(&dbe, cache, opts, config, vec![])?,
|
||||
Command::Restore(opts) => restore::execute(&dbe, opts)?,
|
||||
Command::Restore(opts) => restore::execute(&dbe, opts, config_file)?,
|
||||
Command::Repair(opts) => repair::execute(&dbe, opts, config_file, &config)?,
|
||||
Command::Repoinfo(opts) => repoinfo::execute(&dbe, &be_hot, opts)?,
|
||||
Command::Tag(opts) => tag::execute(&dbe, opts, config_file)?,
|
||||
|
||||
@ -11,6 +11,7 @@ use ignore::{DirEntry, WalkBuilder};
|
||||
use log::*;
|
||||
use rayon::ThreadPoolBuilder;
|
||||
|
||||
use super::rustic_config::RusticConfig;
|
||||
use super::{bytes, progress_bytes, progress_counter, wait, warm_up, warm_up_command};
|
||||
use crate::backend::{DecryptReadBackend, FileType, LocalBackend};
|
||||
use crate::blob::{Node, NodeStreamer, NodeType, Tree};
|
||||
@ -18,11 +19,14 @@ use crate::commands::helpers::progress_spinner;
|
||||
use crate::crypto::hash;
|
||||
use crate::id::Id;
|
||||
use crate::index::{IndexBackend, IndexedBackend};
|
||||
use crate::repo::SnapshotFile;
|
||||
use crate::repo::{SnapshotFile, SnapshotFilter};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(global_setting(AppSettings::DeriveDisplayOrder))]
|
||||
pub(super) struct Opts {
|
||||
#[clap(flatten, help_heading = "SNAPSHOT FILTER OPTIONS (when using latest)")]
|
||||
filter: SnapshotFilter,
|
||||
|
||||
/// Dry-run: don't restore, only show what would be done
|
||||
#[clap(long, short = 'n')]
|
||||
dry_run: bool,
|
||||
@ -57,7 +61,13 @@ pub(super) struct Opts {
|
||||
dest: String,
|
||||
}
|
||||
|
||||
pub(super) fn execute(be: &(impl DecryptReadBackend + Unpin), opts: Opts) -> Result<()> {
|
||||
pub(super) fn execute(
|
||||
be: &(impl DecryptReadBackend + Unpin),
|
||||
mut opts: Opts,
|
||||
config_file: RusticConfig,
|
||||
) -> Result<()> {
|
||||
config_file.merge_into("snapshot-filter", &mut opts.filter)?;
|
||||
|
||||
if let Some(command) = &opts.warm_up_command {
|
||||
if !command.contains("%id") {
|
||||
bail!("warm-up command must contain %id!")
|
||||
@ -66,7 +76,7 @@ pub(super) fn execute(be: &(impl DecryptReadBackend + Unpin), opts: Opts) -> Res
|
||||
}
|
||||
|
||||
let (id, path) = opts.snap.split_once(':').unwrap_or((&opts.snap, ""));
|
||||
let snap = SnapshotFile::from_str(be, id, |_| true, progress_counter(""))?;
|
||||
let snap = SnapshotFile::from_str(be, id, |sn| sn.matches(&opts.filter), progress_counter(""))?;
|
||||
|
||||
let index = IndexBackend::new(be, progress_counter(""))?;
|
||||
let tree = Tree::subtree_id(&index, snap.tree, Path::new(path))?;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user