Skip to main content

lux_cli/
vendor.rs

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    /// The directory in which to vendor the dependencies.
14    /// Must be set if `--vendor-dir` is not set.
15    vendor_dir: Option<PathBuf>,
16
17    /// RockSpec to vendor the packages for.{n}
18    /// If not set, Lux will vendor dependencies of the current project.
19    #[arg(long)]
20    rockspec: Option<PathBuf>,
21
22    /// Ignore the project's lockfile, if present.
23    #[arg(long)]
24    no_lock: bool,
25
26    /// Don't delete the <vendor-dir> when vendoring,{n}
27    /// but rather keep all existing contents of the vendor directory.
28    #[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}