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 progress_arc = MultiProgress::new_arc();
46 let progress = Arc::clone(&progress_arc);
47
48 let build_dependencies = rockspec.build_dependencies().current_platform();
51
52 let build_dependencies_to_install = build_dependencies
53 .iter()
54 .filter(|dep| {
55 tree.match_rocks(dep.package_req())
56 .is_ok_and(|rock_match| rock_match.is_found())
57 })
58 .map(|dep| {
59 PackageInstallSpec::new(dep.package_req().clone(), tree::EntryType::Entrypoint)
60 .build_behaviour(BuildBehaviour::NoForce)
61 .pin(pin)
62 .opt(OptState::Required)
63 .maybe_source(dep.source().clone())
64 .build()
65 })
66 .collect();
67
68 Install::new(&config)
69 .packages(build_dependencies_to_install)
70 .tree(tree.build_tree(&config)?)
71 .progress(progress_arc.clone())
72 .install()
73 .await?;
74
75 let dependencies = rockspec.dependencies().current_platform();
76
77 let dependencies_to_install = dependencies
78 .iter()
79 .filter(|dep| {
80 tree.match_rocks(dep.package_req())
81 .is_ok_and(|rock_match| rock_match.is_found())
82 })
83 .map(|dep| {
84 PackageInstallSpec::new(dep.package_req().clone(), tree::EntryType::DependencyOnly)
85 .build_behaviour(BuildBehaviour::NoForce)
86 .pin(pin)
87 .opt(OptState::Required)
88 .maybe_source(dep.source().clone())
89 .build()
90 })
91 .collect();
92
93 Install::new(&config)
94 .packages(dependencies_to_install)
95 .tree(tree.clone())
96 .progress(progress_arc.clone())
97 .install()
98 .await?;
99
100 if let Some(BuildBackendSpec::LuaRock(_)) = &rockspec.build().current_platform().build_backend {
101 let build_tree = tree.build_tree(&config)?;
102 let luarocks = LuaRocksInstallation::new(&config, build_tree)?;
103 let bar = progress.map(|p| p.new_bar());
104 luarocks.ensure_installed(&bar).await?;
105 }
106
107 build::Build::new(
108 &rockspec,
109 &tree,
110 tree::EntryType::Entrypoint,
111 &config,
112 &progress.map(|p| p.new_bar()),
113 )
114 .pin(pin)
115 .behaviour(BuildBehaviour::Force)
116 .build()
117 .await?;
118
119 Ok(())
120}