lux_lib/operations/
install_rockspec.rs1use bon::Builder;
2use miette::Diagnostic;
3use thiserror::Error;
4
5use crate::{
6 build::{BuildBehaviour, BuildError},
7 config::Config,
8 drivers::install_packages::{InstallPackages, InstallPackagesError},
9 lockfile::{LockedPackage, OptState, PinnedState},
10 lua_installation::LuaInstallationError,
11 lua_rockspec::{LuaVersionError, RemoteLuaRockspec},
12 luarocks::luarocks_installation::{LuaRocksError, LuaRocksInstallError},
13 operations::PackageInstallSpec,
14 package::{PackageName, PackageReq},
15 package_db::{PackageDB, PackageDBError},
16 pipeline::discover::FoundPackage,
17 rockspec::{LuaVersionCompatibility, Rockspec},
18 tree::{self, InstallTree, TreeError},
19};
20
21#[derive(Debug, Error, Diagnostic)]
22#[error(transparent)]
23#[non_exhaustive]
24pub enum InstallRockspecError {
25 #[diagnostic(transparent)]
26 LuaInstallation(#[from] LuaInstallationError),
27 #[diagnostic(transparent)]
28 LuaVersion(#[from] LuaVersionError),
29 #[diagnostic(transparent)]
30 PackageDB(#[from] PackageDBError),
31 #[diagnostic(transparent)]
32 Tree(#[from] TreeError),
33 #[diagnostic(transparent)]
34 Install(#[from] Box<InstallPackagesError>),
35 #[diagnostic(transparent)]
36 LuaRocks(#[from] LuaRocksError),
37 #[diagnostic(transparent)]
38 LuaRocksInstall(#[from] Box<LuaRocksInstallError>),
39 #[diagnostic(transparent)]
40 Build(#[from] Box<BuildError>),
41 #[error("package '{0}' was not installed")]
42 PackageNotInstalled(PackageName),
43}
44
45impl From<InstallPackagesError> for InstallRockspecError {
46 fn from(source: InstallPackagesError) -> Self {
47 Self::Install(Box::new(source))
48 }
49}
50
51impl From<LuaRocksInstallError> for InstallRockspecError {
52 fn from(source: LuaRocksInstallError) -> Self {
53 Self::LuaRocksInstall(Box::new(source))
54 }
55}
56
57impl From<BuildError> for InstallRockspecError {
58 fn from(source: BuildError) -> Self {
59 Self::Build(Box::new(source))
60 }
61}
62
63#[derive(Builder)]
65#[builder(start_fn = new, finish_fn(name = _build, vis = ""))]
66pub struct InstallRockspec<'a, T>
67where
68 T: InstallTree,
69{
70 rockspec: RemoteLuaRockspec,
71
72 pin: PinnedState,
73
74 config: &'a Config,
75
76 tree: &'a T,
77}
78
79impl<
80 T: InstallTree + Sync + Send + Clone + 'static,
81 State: install_rockspec_builder::State + install_rockspec_builder::IsComplete,
82 > InstallRockspecBuilder<'_, T, State>
83{
84 pub async fn install(self) -> Result<LockedPackage, InstallRockspecError> {
85 let args = self._build();
86 let rockspec = args.rockspec;
87 let pin = args.pin;
88 let config = args.config;
89 let tree = args.tree;
90
91 rockspec.lua_version_matches(config)?;
92
93 let name = rockspec.package().clone();
94 let root = FoundPackage::from_rockspec(rockspec);
95 let package_db = PackageDB::from_config(config).await?.with_local(vec![root]);
96
97 let install_spec =
98 PackageInstallSpec::new(PackageReq::from(name.clone()), tree::EntryType::Entrypoint)
99 .build_behaviour(BuildBehaviour::Force)
100 .pin(pin)
101 .opt(OptState::Required)
102 .build();
103
104 InstallPackages::new(config, tree)
105 .package_db(package_db)
106 .package(install_spec)
107 .install()
108 .await?
109 .0
110 .into_iter()
111 .find(|package| package.name() == &name)
112 .ok_or(InstallRockspecError::PackageNotInstalled(name))
113 }
114}