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