archival 0.14.0

The simplest CMS in existence
Documentation
use super::BinaryCommand;
use crate::{
    archival_proto,
    binary::{
        command::{add_args, command_root, CommandConfig},
        ExitStatus,
    },
    file_system_stdlib::{self, NativeFileSystem},
    Archival,
};
use clap::{arg, value_parser, ArgMatches};
use prost::Message;
use std::{
    error::Error,
    fs,
    path::PathBuf,
    sync::{atomic::AtomicBool, Arc},
};

pub struct Command {}
impl BinaryCommand for Command {
    fn name(&self) -> &str {
        "proto"
    }
    fn cli(&self, cmd: clap::Command) -> clap::Command {
        cmd.about("dumps test protos").subcommand(
            clap::Command::new("dump")
                .about("dump proto data")
                .subcommand(add_args(
                    clap::Command::new("object")
                        .about("dump an object proto")
                        .arg(
                            arg!(-o --out <file> "file to dump to")
                                .required(false)
                                .value_parser(value_parser!(PathBuf)),
                        )
                        .arg(arg!([type] "object type").required(true))
                        .arg(arg!([name] "object name").required(false)),
                    CommandConfig::no_build(),
                )),
        )
    }
    fn handler(
        &self,
        args: &ArgMatches,
        _quit: Arc<AtomicBool>,
    ) -> Result<crate::binary::ExitStatus, Box<dyn std::error::Error>> {
        if let Some((name, sub_m)) = args.subcommand() {
            if name == "dump" {
                if let Some((sub_name, m)) = sub_m.subcommand() {
                    if sub_name == "object" {
                        let archival = self.get_archival(m)?;
                        let name = m.get_one::<String>("type").map(|s| s.as_str()).unwrap();
                        let filename = m.get_one::<String>("name").map(|s| s.as_str());
                        let object = archival.get_object(name, filename).unwrap();
                        let obj_proto = archival_proto::Object::from(object);
                        let buffer = obj_proto.encode_to_vec();
                        if let Some(out) = m.get_one::<PathBuf>("out") {
                            println!("Writing to {}", out.display());
                            fs::write(out, buffer)?;
                        } else {
                            println!(
                                "{}",
                                String::from_utf8(buffer).expect("failed encoding to string")
                            );
                        }
                        return Ok(ExitStatus::Ok);
                    }
                }
            }
        }

        Ok(ExitStatus::Ok)
    }
}

impl Command {
    fn get_archival(
        &self,
        args: &ArgMatches,
    ) -> Result<Archival<NativeFileSystem>, Box<dyn Error>> {
        let root_dir = command_root(args);
        let fs = file_system_stdlib::NativeFileSystem::new(&root_dir);
        Archival::new_with_upload_prefix(fs, "")
    }
}