sbak/sub/init/
bank.rs

1use std::process::exit;
2
3use clap::{App, Arg, ArgMatches, SubCommand};
4use failure::Fail;
5
6use super::super::SubCmd;
7
8use crate::config::Config;
9use crate::core::repo::{self, Repository};
10
11pub fn new() -> Box<dyn SubCmd> {
12    Box::new(Bank::new())
13}
14
15pub struct Bank();
16
17impl Bank {
18    pub fn new() -> Bank {
19        Bank()
20    }
21
22    fn wrapped_exec(&self, matches: &ArgMatches, config: Config) -> Result<()> {
23        let repo_path = matches
24            .value_of("repo")
25            .map(|s| s.parse().unwrap())
26            .or_else(|| config.repository_path().map(|p| p.to_owned()))
27            .ok_or_else(|| Error::Arg("no repository path"))?;
28
29        let repository = Repository::open(&repo_path)?;
30        let name = matches.value_of("name").unwrap();
31        let path = matches.value_of("path").unwrap();
32
33        if repository.bank_exists(name)? {
34            println!("bank '{}' already exists.", name);
35            return Ok(());
36        }
37
38        repository.create_bank(name, path)?;
39
40        Ok(())
41    }
42}
43
44impl SubCmd for Bank {
45    fn name(&self) -> &'static str {
46        "bank"
47    }
48
49    fn command_args(&self) -> App {
50        SubCommand::with_name(self.name())
51            .about("create or initialize bank")
52            .arg(
53                Arg::with_name("repo")
54                    .long("repo")
55                    .takes_value(true)
56                    .help("Overwrite repository path"),
57            )
58            .arg(
59                Arg::with_name("name")
60                    .short("n")
61                    .long("name")
62                    .takes_value(true)
63                    .required(true)
64                    .help("Bank name"),
65            )
66            .arg(
67                Arg::with_name("path")
68                    .short("p")
69                    .long("path")
70                    .takes_value(true)
71                    .required(true)
72                    .help("Target path"),
73            )
74    }
75
76    fn exec(&self, matches: &ArgMatches, config: Config) -> ! {
77        match self.wrapped_exec(matches, config) {
78            Ok(()) => exit(0),
79            Err(e) => {
80                eprintln!("{}", e);
81                if cfg!(debug_assertions) {
82                    eprintln!("{:#?}", e);
83                }
84                exit(1)
85            }
86        }
87    }
88}
89
90type Result<T> = std::result::Result<T, Error>;
91
92#[derive(Debug, Fail)]
93pub enum Error {
94    #[fail(display = "repository operation error: {}", _0)]
95    Repo(#[fail(cause)] repo::Error),
96
97    #[fail(display = "{}", _0)]
98    Arg(&'static str),
99}
100
101impl From<repo::Error> for Error {
102    fn from(e: repo::Error) -> Error {
103        Error::Repo(e)
104    }
105}