Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/package/typst-gather/src/main.rs
6460 views
1
use std::collections::HashSet;
2
use std::path::PathBuf;
3
use std::process::ExitCode;
4
5
use clap::Parser;
6
use typst_gather::{gather_packages, Config};
7
8
#[derive(Parser)]
9
#[command(version, about = "Gather Typst packages to a local directory")]
10
struct Args {
11
/// TOML file specifying packages to gather
12
spec_file: PathBuf,
13
}
14
15
fn main() -> ExitCode {
16
let args = Args::parse();
17
18
let content = match std::fs::read_to_string(&args.spec_file) {
19
Ok(c) => c,
20
Err(e) => {
21
eprintln!("Error reading spec file: {e}");
22
return ExitCode::FAILURE;
23
}
24
};
25
26
let config = match Config::parse(&content) {
27
Ok(c) => c,
28
Err(e) => {
29
eprintln!("Error parsing spec file: {e}");
30
return ExitCode::FAILURE;
31
}
32
};
33
34
let dest = match &config.destination {
35
Some(d) => d.clone(),
36
None => {
37
eprintln!("Error: 'destination' field is required in spec file");
38
return ExitCode::FAILURE;
39
}
40
};
41
42
// Resolve paths relative to rootdir if specified
43
let rootdir = config.rootdir.clone();
44
let dest = match &rootdir {
45
Some(root) => root.join(&dest),
46
None => dest,
47
};
48
let discover: Vec<PathBuf> = config
49
.discover
50
.iter()
51
.map(|p| match &rootdir {
52
Some(root) => root.join(p),
53
None => p.clone(),
54
})
55
.collect();
56
57
// Build set of configured local packages
58
let configured_local: HashSet<String> = config.local.keys().cloned().collect();
59
60
let entries = config.into_entries();
61
let result = gather_packages(&dest, entries, &discover, &configured_local);
62
63
// Check for unconfigured @local imports FIRST (this is an error)
64
if !result.unconfigured_local.is_empty() {
65
eprintln!("\nError: Found @local imports not configured in [local] section:");
66
for (name, source_file) in &result.unconfigured_local {
67
eprintln!(" - {name} (in {source_file})");
68
}
69
eprintln!("\nAdd them to your config file:");
70
eprintln!(" [local]");
71
for (name, _) in &result.unconfigured_local {
72
eprintln!(" {name} = \"/path/to/{name}\"");
73
}
74
return ExitCode::FAILURE;
75
}
76
77
println!(
78
"\nDone: {} downloaded, {} copied, {} skipped, {} failed",
79
result.stats.downloaded, result.stats.copied, result.stats.skipped, result.stats.failed
80
);
81
82
if result.stats.failed > 0 {
83
ExitCode::FAILURE
84
} else {
85
ExitCode::SUCCESS
86
}
87
}
88
89