lux_cli/
install_rockspec.rs1use eyre::eyre;
2use std::{path::PathBuf, sync::Arc};
3
4use clap::Args;
5use eyre::Result;
6use lux_lib::{
7 build::{self, BuildBehaviour},
8 config::Config,
9 lockfile::{OptState, PinnedState},
10 lua_rockspec::{BuildBackendSpec, RemoteLuaRockspec},
11 luarocks::luarocks_installation::LuaRocksInstallation,
12 operations::{Install, PackageInstallSpec},
13 progress::MultiProgress,
14 rockspec::{LuaVersionCompatibility, Rockspec},
15 tree,
16};
17
18#[derive(Args, Default)]
19pub struct InstallRockspec {
20 rockspec_path: PathBuf,
22
23 #[arg(long)]
25 pin: bool,
26}
27
28pub async fn install_rockspec(data: InstallRockspec, config: Config) -> Result<()> {
30 let pin = PinnedState::from(data.pin);
31 let path = data.rockspec_path;
32
33 if path
34 .extension()
35 .map(|ext| ext != "rockspec")
36 .unwrap_or(true)
37 {
38 return Err(eyre!("Provided path is not a valid rockspec!"));
39 }
40 let content = std::fs::read_to_string(path)?;
41 let rockspec = RemoteLuaRockspec::new(&content)?;
42 let lua_version = rockspec.lua_version_matches(&config)?;
43 let tree = config.user_tree(lua_version)?;
44
45 let dependencies = rockspec.dependencies().current_platform();
47
48 let progress_arc = MultiProgress::new_arc();
49 let progress = Arc::clone(&progress_arc);
50
51 let dependencies_to_install = dependencies
52 .iter()
53 .filter(|dep| {
54 tree.match_rocks(dep.package_req())
55 .is_ok_and(|rock_match| rock_match.is_found())
56 })
57 .map(|dep| {
58 PackageInstallSpec::new(dep.package_req().clone(), tree::EntryType::DependencyOnly)
59 .build_behaviour(BuildBehaviour::NoForce)
60 .pin(pin)
61 .opt(OptState::Required)
62 .maybe_source(dep.source().clone())
63 .build()
64 })
65 .collect();
66
67 Install::new(&config)
68 .packages(dependencies_to_install)
69 .tree(tree.clone())
70 .progress(progress_arc.clone())
71 .install()
72 .await?;
73
74 if let Some(BuildBackendSpec::LuaRock(build_backend)) =
75 &rockspec.build().current_platform().build_backend
76 {
77 let build_tree = tree.build_tree(&config)?;
78 let luarocks = LuaRocksInstallation::new(&config, build_tree)?;
79 let bar = progress.map(|p| p.new_bar());
80 luarocks.ensure_installed(&bar).await?;
81 luarocks
82 .install_build_dependencies(build_backend, &rockspec, progress_arc.clone())
83 .await?;
84 }
85
86 build::Build::new(
87 &rockspec,
88 &tree,
89 tree::EntryType::Entrypoint,
90 &config,
91 &progress.map(|p| p.new_bar()),
92 )
93 .pin(pin)
94 .behaviour(BuildBehaviour::Force)
95 .build()
96 .await?;
97
98 Ok(())
99}