linkmarks_cli/cmd/
init.rs1use anyhow::Result;
14use clap::Args;
15use linkmarks_core::config as core_config;
16use linkmarks_core::paths;
17use linkmarks_core::store;
18
19#[derive(Args, Debug)]
20pub struct InitArgs {
21 #[arg(long)]
23 pub data_dir: Option<std::path::PathBuf>,
24
25 #[arg(long)]
27 pub config_dir: Option<std::path::PathBuf>,
28
29 #[arg(long)]
33 pub force: bool,
34}
35
36pub fn run(args: InitArgs, _format: crate::Format, paths: crate::Paths) -> Result<i32> {
37 let store_path = paths.store.clone();
41 let cfg_path = paths.config.clone();
42
43 let data_dir = args.data_dir.clone().unwrap_or_else(|| {
44 store_path
45 .parent()
46 .map(|p| p.to_path_buf())
47 .unwrap_or_else(paths::linkmarks_data_dir)
48 });
49 let config_dir = args.config_dir.clone().unwrap_or_else(|| {
50 cfg_path
51 .parent()
52 .map(|p| p.to_path_buf())
53 .unwrap_or_else(paths::linkmarks_config_dir)
54 });
55
56 std::fs::create_dir_all(&data_dir)
58 .map_err(|e| anyhow::anyhow!("create data dir {}: {e}", data_dir.display()))?;
59 std::fs::create_dir_all(&config_dir)
60 .map_err(|e| anyhow::anyhow!("create config dir {}: {e}", config_dir.display()))?;
61
62 let wrote_config = if args.force || !cfg_path.exists() {
64 if args.force && cfg_path.exists() {
65 let backup = cfg_path.with_extension("toml.bak");
67 let _ = std::fs::rename(&cfg_path, &backup);
68 }
69 std::fs::write(&cfg_path, core_config::DEFAULT_CONFIG_BODY)
70 .map_err(|e| anyhow::anyhow!("write default config: {e}"))?;
71 true
72 } else {
73 false
74 };
75
76 let _store = store::open(&store_path)
78 .map_err(|e| anyhow::anyhow!("open store {}: {e}", store_path.display()))?;
79 let _cfg = core_config::load_from(&cfg_path)
80 .map_err(|e| anyhow::anyhow!("parse config {}: {e}", cfg_path.display()))?;
81
82 println!(
83 "data_dir={}\nconfig_dir={}\nstore={}\nconfig_file={}\nconfig_written={}",
84 data_dir.display(),
85 config_dir.display(),
86 store_path.display(),
87 cfg_path.display(),
88 wrote_config,
89 );
90 Ok(crate::exit_codes::OK)
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use tempfile::tempdir;
97
98 #[test]
99 fn default_args_parse() {
100 let _ = InitArgs {
101 data_dir: None,
102 config_dir: None,
103 force: false,
104 };
105 }
106
107 #[test]
108 fn store_opens_against_arbitrary_data_dir() {
109 let dir = tempdir().unwrap();
111 let s = store::open(&dir.path().join("store.db")).unwrap();
112 assert_eq!(s.count().unwrap(), 0);
113 }
114}