Skip to main content

asimov_cli/commands/
fetch.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{
4    StandardOptions,
5    SysexitsError::{self, *},
6    shared,
7};
8use asimov_module::{normalization::normalize_url, resolve::Resolver};
9use asimov_runner::{FetcherOptions, GraphOutput};
10use color_print::ceprintln;
11use miette::Result;
12
13pub async fn fetch(
14    input_urls: Vec<String>,
15    module: Option<String>,
16    output: Option<String>,
17    flags: &StandardOptions,
18) -> Result<(), SysexitsError> {
19    let registry = asimov_registry::Registry::default();
20
21    let installed_modules = shared::installed_modules(&registry, Some("fetcher")).await?;
22
23    let resolver = Resolver::try_from_iter(installed_modules.iter()).map_err(|e| {
24        ceprintln!("<s,r>error:</> failed to build resolver: {e}");
25        EX_UNAVAILABLE
26    })?;
27
28    for input_url in input_urls {
29        if flags.verbose > 1 {
30            ceprintln!("<s,c>»</> Fetching <s>{}</>...", input_url);
31        }
32
33        let input_url = normalize_url(&input_url).unwrap_or_else(|e| {
34            if flags.verbose > 1 {
35                ceprintln!(
36                    "<s,y>warning:</> using given unmodified URL, normalization failed: {e}"
37                );
38            }
39            input_url.clone()
40        });
41
42        let modules = resolver.resolve(&input_url).map_err(|e| {
43            ceprintln!("<s,r>error:</> unable to handle URL <s>{input_url}</>: {e}");
44            EX_USAGE
45        })?;
46
47        let module =
48            shared::pick_module(&registry, &input_url, modules.as_slice(), module.as_deref())
49                .await?;
50
51        let mut fetcher = asimov_runner::Fetcher::new(
52            format!("asimov-{}-fetcher", module.name),
53            &input_url,
54            GraphOutput::Inherited,
55            FetcherOptions::builder()
56                .maybe_output(output.as_deref())
57                .maybe_other(flags.debug.then_some("--debug"))
58                .build(),
59        );
60
61        let _ = fetcher.execute().await.map_err(|e| {
62            ceprintln!("<s,r>error:</> fetcher execution failed: {e}");
63            EX_UNAVAILABLE
64        })?;
65
66        if flags.verbose > 0 {
67            ceprintln!("<s,g>✓</> Fetched <s>{}</>.", input_url);
68        }
69    }
70
71    Ok(())
72}