(WIP) new: implement status subcommand

- Error while getting mount path of Storages
- Need to redesign the API of LocalInfo or something
This commit is contained in:
qwjyh 2024-08-07 11:39:58 +02:00
parent 0abf9c0693
commit 37782c934c
4 changed files with 99 additions and 1 deletions

View file

@ -44,6 +44,18 @@ pub(crate) enum Commands {
#[command(subcommand)]
Backup(BackupSubCommands),
/// Print status for the given path.
Status {
/// Target path. Default is the current directory.
path: Option<PathBuf>,
/// Show storage which the path belongs to.
#[arg(short)]
storage: bool,
/// Show backup config covering the path.
#[arg(short)]
backup: bool,
},
/// Print config dir.
Path {},

81
src/cmd_status.rs Normal file
View file

@ -0,0 +1,81 @@
use anyhow::{Context, Result};
use console::Style;
use std::{
env,
path::{self, Path, PathBuf},
};
use crate::{
backups::Backups,
devices::{self, Device},
storages::{self, StorageExt, Storages},
util,
};
// TODO: fine styling like `backup list`, or should I just use the same style?
pub(crate) fn cmd_status(
path: Option<PathBuf>,
show_storage: bool,
show_backup: bool,
config_dir: &Path,
) -> Result<()> {
let path = path.unwrap_or(env::current_dir().context("Failed to get current directory.")?);
let device = devices::get_device(config_dir)?;
if show_storage {
let storages = storages::Storages::read(config_dir)?;
let storage = util::min_parent_storage(&path, &storages, &device);
match storage {
Some(storage) => {
println!("Storage: {}", storage.0.name())
}
None => {
println!("Storage: None");
}
}
}
if show_backup {
let devices = devices::get_devices(config_dir)?;
let storages = storages::Storages::read(config_dir)?;
let backups = Backups::read(config_dir, &device)?;
let covering_backup = devices
.iter()
.map(|device| (device, parent_backups(&path, &backups, &storages, device)));
for (backup_device, covering_backups) in covering_backup {
println!("Device: {}", backup_device.name());
for backup in covering_backups {
println!(" {}", console::style(backup.0).bold());
}
}
}
todo!()
}
fn parent_backups<'a>(
target_path: &'a PathBuf,
backups: &'a Backups,
storages: &'a Storages,
device: &'a Device,
) -> Vec<(&'a String, PathBuf)> {
backups
.list
.iter()
.filter_map(|(k, v)| {
let backup_path = match v.source().path(storages, device) {
Ok(path) => path,
Err(e) => {
error!("Error while getting backup source path: {}", e);
return None;
}
};
let diff = pathdiff::diff_paths(target_path, backup_path)?;
if diff.components().any(|c| c == path::Component::ParentDir) {
None
} else {
Some((k, diff))
}
})
.collect()
}

View file

@ -31,6 +31,7 @@ mod cmd_backup;
mod cmd_check;
mod cmd_completion;
mod cmd_init;
mod cmd_status;
mod cmd_storage;
mod cmd_sync;
mod devices;
@ -91,6 +92,11 @@ fn main() -> Result<()> {
println!("{}", &config_dir.display());
}
Commands::Sync { remote_name } => cmd_sync::cmd_sync(&config_dir, remote_name)?,
Commands::Status {
path,
storage,
backup,
} => cmd_status::cmd_status(path, storage, backup, &config_dir)?,
Commands::Check {} => cmd_check::cmd_check(&config_dir)?,
Commands::Backup(backup) => {
trace!("backup subcommand with args: {:?}", backup);

View file

@ -144,7 +144,6 @@ pub trait StorageExt {
fn local_info(&self, device: &devices::Device) -> Option<&local_info::LocalInfo>;
/// Get mount path of `self` on `device`.
/// `storages` is a `BTreeMap` with key of storage name and value of the storage.
fn mount_path(&self, device: &devices::Device) -> Result<path::PathBuf>;
/// Add local info of `device` to `self`.