diff --git a/Cargo.toml b/Cargo.toml index e3d9556..79353d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,5 @@ boomphf = "0.5" walkdir = "2" # commands clap = { version = "3", features = ["derive"] } +prettytable-rs = "0.8" diff --git a/src/commands/mod.rs b/src/commands/mod.rs index e84f933..8cc8341 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -6,6 +6,7 @@ use crate::repo; mod cat; mod list; +mod snapshots; #[derive(Parser)] #[clap(about, version)] @@ -29,6 +30,9 @@ enum Command { /// cat files Cat(cat::Opts), + + /// cat files + Snapshots(snapshots::Opts), } pub fn execute() -> Result<()> { @@ -41,5 +45,6 @@ pub fn execute() -> Result<()> { match args.command { Command::List(opts) => list::execute(&be, opts), Command::Cat(opts) => cat::execute(&be, &dbe, opts), + Command::Snapshots(opts) => snapshots::execute(&dbe, opts), } } diff --git a/src/commands/snapshots.rs b/src/commands/snapshots.rs new file mode 100644 index 0000000..fffec28 --- /dev/null +++ b/src/commands/snapshots.rs @@ -0,0 +1,28 @@ +use anyhow::Result; +use clap::Parser; +use prettytable::{cell, format, row, Table}; + +use crate::backend::{FileType, ReadBackend}; +use crate::repo::SnapshotFile; + +#[derive(Parser)] +pub(super) struct Opts {} + +pub(super) fn execute(be: &impl ReadBackend, _opts: Opts) -> Result<()> { + let mut table = Table::new(); + table.set_titles(row!["ID", "Time", "Host", "Tags", "Paths"]); + table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + + for id in be.list(FileType::Snapshot)? { + let sn = SnapshotFile::from_backend(be, id)?; + let paths = sn + .paths + .iter() + .map(|p| p.to_string_lossy() + "\n") + .collect::(); + table.add_row(row![id, sn.time, sn.hostname, "", paths,]); + } + table.printstd(); + + Ok(()) +} diff --git a/src/repo/snapshot.rs b/src/repo/snapshot.rs index c434082..0e05df0 100644 --- a/src/repo/snapshot.rs +++ b/src/repo/snapshot.rs @@ -1,28 +1,38 @@ +use anyhow::Result; +use chrono::{DateTime, Local}; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; use super::Id; -use chrono::{DateTime, Local}; -use serde::{Deserialize, Serialize}; +use crate::backend::{FileType, ReadBackend}; #[derive(Debug, Serialize, Deserialize)] pub struct SnapshotFile { - time: DateTime, - tree: Id, - paths: Vec, + pub time: DateTime, + pub tree: Id, + pub paths: Vec, #[serde(default)] - hostname: String, + pub hostname: String, #[serde(default)] - username: String, + pub username: String, #[serde(default)] - uid: u32, + pub uid: u32, #[serde(default)] - gid: u32, + pub gid: u32, #[serde(default)] - tags: TagList, + pub tags: TagList, +} + +impl SnapshotFile { + /// Get an IndexFile from the backend + pub fn from_backend(be: &B, id: Id) -> Result { + let data = be.read_full(FileType::Snapshot, id)?; + Ok(serde_json::from_slice(&data)?) + } } #[derive(Default, Debug, Serialize, Deserialize)] -struct TagList(Vec); +pub struct TagList(Vec); #[derive(Default, Debug, Serialize, Deserialize)] pub struct Tag(String);