1use crate::{CliError, Session};
5use btctax_store::Passphrase;
6use std::path::Path;
7
8pub fn run(vault_path: &Path, pp: &Passphrase, key_backup_path: &Path) -> Result<(), CliError> {
11 run_with_repair(vault_path, pp, key_backup_path, false)
12}
13
14pub fn run_with_repair(
17 vault_path: &Path,
18 pp: &Passphrase,
19 key_backup_path: &Path,
20 repair: bool,
21) -> Result<(), CliError> {
22 let session = if repair {
23 Session::repair(vault_path, pp)?
24 } else {
25 Session::create(vault_path, pp)?
26 };
27 session.vault().backup_key(key_backup_path)?;
29 Ok(())
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35 use btctax_store::Passphrase;
36
37 #[test]
38 fn init_creates_vault_key_and_forced_backup() {
39 let dir = tempfile::tempdir().unwrap();
40 let vault = dir.path().join("vault.pgp");
41 let backup = dir.path().join("backup/key.asc");
42 run(&vault, &Passphrase::new("pw".into()), &backup).unwrap();
43 assert!(vault.exists(), "vault.pgp written");
44 assert!(dir.path().join("vault.key").exists(), "sidecar key written");
45 assert!(backup.exists(), "forced key backup written");
46 }
47
48 #[test]
49 fn init_refuses_to_clobber_an_existing_vault() {
50 let dir = tempfile::tempdir().unwrap();
51 let vault = dir.path().join("vault.pgp");
52 let backup = dir.path().join("k.asc");
53 run(&vault, &Passphrase::new("pw".into()), &backup).unwrap();
54 let err = run(&vault, &Passphrase::new("pw".into()), &backup).unwrap_err();
55 assert!(matches!(
56 err,
57 CliError::Store(btctax_store::StoreError::AlreadyExists)
58 ));
59 }
60
61 #[test]
64 fn init_repair_recovers_a_half_created_vault() {
65 let dir = tempfile::tempdir().unwrap();
66 let vault = dir.path().join("vault.pgp");
67 let backup = dir.path().join("k.asc");
68 let pp = Passphrase::new("pw".into());
69 run(&vault, &pp, &backup).unwrap();
71 std::fs::remove_file(&vault).unwrap();
72 let bak = btctax_store::paths::bak_of(&vault);
73 if bak.exists() {
74 std::fs::remove_file(&bak).unwrap();
75 }
76 let backup2 = dir.path().join("k2.asc");
78 run_with_repair(&vault, &pp, &backup2, true).unwrap();
79 crate::Session::open(&vault, &pp).unwrap();
81 }
82
83 #[test]
86 fn init_without_repair_on_half_created_errors() {
87 let dir = tempfile::tempdir().unwrap();
88 let vault = dir.path().join("vault.pgp");
89 let backup = dir.path().join("k.asc");
90 let pp = Passphrase::new("pw".into());
91 run(&vault, &pp, &backup).unwrap();
92 std::fs::remove_file(&vault).unwrap();
93 let bak = btctax_store::paths::bak_of(&vault);
94 if bak.exists() {
95 std::fs::remove_file(&bak).unwrap();
96 }
97 let err = run(&vault, &pp, &backup).unwrap_err();
99 assert!(
100 matches!(
101 err,
102 CliError::Store(btctax_store::StoreError::HalfCreatedVault(_))
103 ),
104 "expected HalfCreatedVault, got: {err:?}"
105 );
106 }
107}