1use clap::Args;
2use eyre::{eyre, Context, OptionExt, Result};
3use lux_lib::{
4 config::Config,
5 lua_rockspec::RemoteLuaRockspec,
6 operations::{self, VendorTarget},
7 project::Project,
8};
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 =
34 match data.rockspec {
35 Some(rockspec_path) => {
36 let content = tokio::fs::read_to_string(&rockspec_path).await?;
37 let rockspec = match rockspec_path
38 .extension()
39 .map(|ext| ext.to_string_lossy().to_string())
40 .unwrap_or("".into())
41 .as_str()
42 {
43 "rockspec" => Ok(RemoteLuaRockspec::new(&content)?),
44 _ => Err(eyre!(
45 "expected a path to a .rockspec file, but got:\n{}",
46 rockspec_path.display()
47 )),
48 }?;
49 VendorTarget::Rockspec(rockspec)
50 }
51 None => VendorTarget::Project(Project::current_or_err().context(
52 "`lx vendor` must be run in a project root or with a rockspec argument.",
53 )?),
54 };
55
56 let vendor_dir = data
57 .vendor_dir
58 .or_else(|| config.vendor_dir().cloned())
59 .ok_or_eyre(
60 r#"<vendor-dir> not set.
61 It must either be specified via `--vendor-dir` or passed to this command.
62 "#,
63 )?;
64
65 operations::Vendor::new()
66 .vendor_dir(vendor_dir)
67 .no_lock(data.no_lock)
68 .no_delete(data.no_delete)
69 .config(&config)
70 .target(target)
71 .vendor_dependencies()
72 .await?;
73
74 Ok(())
75}