Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/vykar-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ vykar-storage.workspace = true
clap.workspace = true
serde.workspace = true
serde_yaml.workspace = true
serde_json.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
comfy-table = "7"
Expand Down
4 changes: 4 additions & 0 deletions crates/vykar-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ pub(crate) enum Commands {
/// Show only the N most recent snapshots
#[arg(long)]
last: Option<usize>,

/// Output data as JSON
#[arg(long)]
json: bool,
},

/// Inspect snapshot contents and metadata
Expand Down
57 changes: 55 additions & 2 deletions crates/vykar-cli/src/cmd/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,49 @@ use crate::format::{format_bytes, format_count};
use crate::passphrase::with_repo_passphrase;
use crate::table::CliTableTheme;

// use serde_json::Value;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels out of place here. Where would you place SnapshotView?

use chrono::{DateTime, Utc};
use serde::Serialize;
use vykar_types::snapshot_id::SnapshotId;
use vykar_core::repo::manifest::SnapshotEntry;
use vykar_core::snapshot::SnapshotStats;

#[derive(Serialize)]
struct SnapshotView {
pub name: String,
pub id: SnapshotId,
pub time: DateTime<Utc>,
pub label: String,
pub source_paths: Vec<String>,
pub hostname: String,
pub nfiles: u64,
pub original_size: u64,
pub compressed_size: u64,
pub deduplicated_size: u64,
}

impl SnapshotView {
fn from_entry_stats_tuple(entry: SnapshotEntry, stats: SnapshotStats) -> SnapshotView {
Self {
name: entry.name,
id: entry.id,
time: entry.time,
label: entry.label,
source_paths: entry.source_paths,
hostname: entry.hostname,
nfiles: stats.nfiles,
original_size: stats.original_size,
compressed_size: stats.compressed_size,
deduplicated_size: stats.deduplicated_size,
}
}
}

pub(crate) fn run_list(
config: &VykarConfig,
label: Option<&str>,
source_filter: &[String],
json: &bool,
last: Option<usize>,
) -> Result<(), Box<dyn std::error::Error>> {
let mut snapshots = with_repo_passphrase(config, label, |passphrase| {
Expand All @@ -31,8 +70,13 @@ pub(crate) fn run_list(
snapshots.drain(..len - n);
}
}

if snapshots.is_empty() {
println!("No snapshots found.");
if *json {
println!("[]");
} else {
println!("No snapshots found.");
}
return Ok(());
}

Expand Down Expand Up @@ -106,7 +150,16 @@ pub(crate) fn run_list(
Cell::new(size_col),
]);
}
println!("{table}");

if *json {
let snapshot_views: Vec<SnapshotView> = snapshots
.into_iter()
.map(|(entry, stats)| SnapshotView::from_entry_stats_tuple(entry, stats.unwrap()))
.collect();
println!("{}", serde_json::to_string_pretty(&snapshot_views)?);
} else {
println!("{table}");
}

Ok(())
}
4 changes: 2 additions & 2 deletions crates/vykar-cli/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ pub(crate) fn dispatch_command(
shutdown,
verbose,
),
Commands::List { source, last, .. } => {
cmd::list::run_list(cfg, label, source, *last).map(|()| false)
Commands::List { source, last, json, .. } => {
cmd::list::run_list(cfg, label, source, json, *last).map(|()| false)
}
Commands::Snapshot { command, .. } => {
cmd::snapshot::run_snapshot_command(command, cfg, label, shutdown).map(|()| false)
Expand Down
26 changes: 26 additions & 0 deletions crates/vykar-cli/tests/cli_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,32 @@ fn cli_snapshot_list_latest_alias() {
);
}

#[test]
fn cli_snapshot_list_json() {
let fx = CliFixture::new();
write_plain_config(&fx.config_path, &fx.repo_dir);

let cfg = fx.config_path.to_string_lossy().to_string();
let source = fx.source_a.to_string_lossy().to_string();

fx.run_ok(&["--config", &cfg, "init"]);

// Snapshot 1: only old.txt
std::fs::write(fx.source_a.join("old.txt"), b"old\n").unwrap();
fx.run_ok(&["--config", &cfg, "backup", &source]);

let out = fx.run_ok(&["--config", &cfg, "list", "--json"]);
let out_json: serde_json::Value = serde_json::from_str(&out).unwrap();
assert!(
out_json[0]["nfiles"] == 1 &&
out_json[0]["source_paths"][0].to_string().contains("source-a") &&
out_json[0]["original_size"] == 4 &&
out_json[0]["compressed_size"] == 11 &&
out_json[0]["deduplicated_size"] == 11,
"expected list --json to show valid info, got:\n{out}"
);
}

#[test]
fn cli_snapshot_info_latest_alias() {
let fx = CliFixture::new();
Expand Down