1use clap::Args;
2use lux_lib::{
3 config::Config,
4 lua_rockspec::RemoteLuaRockspec,
5 operations::{self, VendorTarget},
6 workspace::Workspace,
7};
8use miette::{miette, IntoDiagnostic, Result};
9use std::path::PathBuf;
10
11#[derive(Args)]
12pub struct Vendor {
13 vendor_dir: Option<PathBuf>,
16
17 #[arg(long)]
20 rockspec: Option<PathBuf>,
21
22 #[arg(long)]
24 no_lock: bool,
25
26 #[arg(long)]
29 no_delete: bool,
30}
31
32pub async fn vendor(data: Vendor, config: Config) -> Result<()> {
33 let target = match data.rockspec {
34 Some(rockspec_path) => {
35 let content = tokio::fs::read_to_string(&rockspec_path)
36 .await
37 .into_diagnostic()?;
38 let rockspec = match rockspec_path
39 .extension()
40 .map(|ext| ext.to_string_lossy().to_string())
41 .unwrap_or("".into())
42 .as_str()
43 {
44 "rockspec" => Ok(RemoteLuaRockspec::new(&content)?),
45 _ => Err(miette!(
46 "expected a path to a .rockspec file, but got:\n{}",
47 rockspec_path.display()
48 )),
49 }?;
50 VendorTarget::Rockspec(rockspec)
51 }
52 None => match Workspace::current_or_err() {
53 Ok(ws) => VendorTarget::Workspace(ws),
54 Err(_) => {
55 return Err(miette!(
56 "`lx vendor` must be run in a workspace root or with a rockspec argument."
57 ));
58 }
59 },
60 };
61
62 let vendor_dir = data
63 .vendor_dir
64 .or_else(|| config.vendor_dir().cloned())
65 .ok_or_else(|| {
66 miette!(
67 r#"<vendor-dir> not set.
68 It must either be specified via `--vendor-dir` or passed to this command.
69 "#
70 )
71 })?;
72
73 operations::Vendor::new()
74 .vendor_dir(vendor_dir)
75 .no_lock(data.no_lock)
76 .no_delete(data.no_delete)
77 .config(&config)
78 .target(target)
79 .vendor_dependencies()
80 .await?;
81
82 Ok(())
83}