Skip to main content

asimov_cli/commands/source/snap/
save.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{BoxError, StandardOptions, SysexitsError::*};
4use asimov_env::paths::asimov_root;
5use asimov_module::normalization::normalize_url;
6use clientele::crates::clap::Args;
7use color_print::ceprintln;
8use miette::Result;
9
10#[derive(Args, Clone, Debug, Default)]
11pub struct SnapSaveArgs {
12    /// URL(s) to snapshot
13    urls: Vec<String>,
14}
15
16pub async fn save(args: &SnapSaveArgs, flags: &StandardOptions) -> Result<(), BoxError> {
17    let registry = asimov_registry::Registry::default();
18
19    let _enabled_modules = registry
20        .enabled_modules()
21        .await
22        .map_err(|e| {
23            ceprintln!("<s,r>error:</> unable to access enabled modules: {e}");
24            match e {
25                asimov_registry::error::EnabledModulesError::DirIo(_, err)
26                    if err.kind() == std::io::ErrorKind::NotFound => {
27                        ceprintln!("<s,dim>hint:</> There appears to be no installed modules.");
28                        ceprintln!("<s,dim>hint:</> Modules may be discovered either on the site <u>https://asimov.directory/modules</>");
29                        ceprintln!("<s,dim>hint:</> or on the GitHub organization <u>https://github.com/asimov-modules</>");
30                        ceprintln!("<s,dim>hint:</> and installed with <s>asimov module install <<module>></>");
31                    },
32                _ => (),
33            };
34            EX_UNAVAILABLE
35        })?;
36
37    let storage =
38        asimov_snapshot::storage::Fs::for_dir(asimov_root().join("snapshots")).map_err(|e| {
39            ceprintln!("<s,r>error:</> failed to create snapshot storage: {e}");
40            EX_UNAVAILABLE
41        })?;
42
43    let mut snapshotter = asimov_snapshot::Snapshotter::new(registry, storage, Default::default());
44
45    for input_url in &args.urls {
46        let input_url = normalize_url(&input_url).unwrap_or_else(|e| {
47            if flags.verbose > 1 {
48                ceprintln!(
49                    "<s,y>warning:</> using given unmodified URL, normalization failed: {e}"
50                );
51            }
52            input_url.clone()
53        });
54        snapshotter.snapshot(&input_url).await.map_err(|e| {
55            ceprintln!("<s,r>error:</> failed to create snapshot URL <s>{input_url}</>: {e}");
56            EX_UNAVAILABLE
57        })?;
58    }
59
60    Ok(())
61}