rustic_rs/commands/
init.rs1use abscissa_core::{Command, Runnable, Shutdown, status_err};
4use anyhow::{Result, bail};
5use dialoguer::Password;
6
7use crate::{
8 Application, RUSTIC_APP,
9 repository::{OpenRepo, Repo},
10};
11
12use rustic_core::{ConfigOptions, CredentialOptions, Credentials, KeyOptions};
13
14#[derive(clap::Parser, Command, Debug)]
16pub(crate) struct InitCmd {
17 #[clap(long)]
19 hot_only: bool,
20
21 #[clap(flatten, next_help_heading = "Key options")]
23 key_opts: KeyOptions,
24
25 #[clap(flatten, next_help_heading = "Config options")]
27 config_opts: ConfigOptions,
28}
29
30impl Runnable for InitCmd {
31 fn run(&self) {
32 if let Err(err) = RUSTIC_APP
33 .config()
34 .repository
35 .run(|repo| self.inner_run(repo))
36 {
37 status_err!("{}", err);
38 RUSTIC_APP.shutdown(Shutdown::Crash);
39 };
40 }
41}
42
43impl InitCmd {
44 fn inner_run(&self, repo: Repo) -> Result<()> {
45 let config = RUSTIC_APP.config();
46
47 if config.global.dry_run {
49 bail!(
50 "cannot initialize repository {} in dry-run mode!",
51 repo.name
52 );
53 }
54
55 if self.hot_only {
56 if config.repository.be.repo_hot.is_none() {
57 bail!("please specify a hot repository");
58 }
59 let repo = repo
60 .open_with(&config.repository.credential_opts, |repo, credentials| {
61 repo.open_only_cold(credentials)
62 })?;
63 repo.init_hot()?;
64 repo.repair_hotcold_except_packs(config.global.dry_run)?;
65 repo.repair_hotcold_packs(config.global.dry_run)?;
66
67 return Ok(());
68 }
69
70 if repo.config_id()?.is_some() {
73 bail!("Config file already exists. Aborting.");
74 }
75
76 let _ = init(
77 repo,
78 &config.repository.credential_opts,
79 &self.key_opts,
80 &self.config_opts,
81 )?;
82 Ok(())
83 }
84}
85
86pub(crate) fn init(
103 repo: Repo,
104 credential_opts: &CredentialOptions,
105 key_opts: &KeyOptions,
106 config_opts: &ConfigOptions,
107) -> Result<OpenRepo> {
108 let pass = init_credentials(credential_opts)?;
109 Ok(repo.0.init(&pass, key_opts, config_opts)?)
110}
111
112pub(crate) fn init_credentials(credential_opts: &CredentialOptions) -> Result<Credentials> {
113 let credentials = credential_opts.credentials()?.unwrap_or_else(|| {
114 match Password::new()
115 .with_prompt("enter password for new key")
116 .allow_empty_password(true)
117 .with_confirmation("confirm password", "passwords do not match")
118 .interact()
119 {
120 Ok(pass) => Credentials::Password(pass),
121 Err(err) => {
122 status_err!("{}", err);
123 RUSTIC_APP.shutdown(Shutdown::Crash);
124 }
125 }
126 });
127
128 Ok(credentials)
129}