lux_lib/operations/
install_project.rs1use crate::{
2 build::{Build, BuildBehaviour, BuildError},
3 config::Config,
4 lockfile::LocalPackage,
5 lua_installation::{LuaInstallation, LuaInstallationError},
6 luarocks::luarocks_installation::{LuaRocksError, LuaRocksInstallError, LuaRocksInstallation},
7 operations::{install_dependencies::prepare_dependencies_for_build, InstallDependencies},
8 progress::{MultiProgress, Progress},
9 project::{project_toml::LocalProjectTomlValidationError, Project, ProjectError},
10 tree::{self, InstallTree, TreeError},
11};
12use bon::Builder;
13use itertools::Itertools;
14use miette::Diagnostic;
15use std::sync::Arc;
16use thiserror::Error;
17
18use super::InstallError;
19
20#[derive(Debug, Error, Diagnostic)]
21pub enum InstallProjectError {
22 #[error(transparent)]
23 #[diagnostic(transparent)]
24 LocalProjectTomlValidation(#[from] LocalProjectTomlValidationError),
25 #[error(transparent)]
26 #[diagnostic(transparent)]
27 Project(#[from] ProjectError),
28 #[error(transparent)]
29 #[diagnostic(transparent)]
30 LuaInstallation(#[from] LuaInstallationError),
31 #[error(transparent)]
32 #[diagnostic(transparent)]
33 Tree(#[from] TreeError),
34 #[error(transparent)]
35 #[diagnostic(transparent)]
36 LuaRocks(#[from] LuaRocksError),
37 #[error(transparent)]
38 #[diagnostic(transparent)]
39 LuaRocksInstall(#[from] LuaRocksInstallError),
40 #[error("error installind dependencies:\n{0}")]
41 #[diagnostic(forward(0))]
42 InstallDependencies(InstallError),
43 #[error("error installind build dependencies:\n{0}")]
44 #[diagnostic(forward(0))]
45 InstallBuildDependencies(InstallError),
46 #[error("error building project:\n{0}")]
47 #[diagnostic(forward(0))]
48 Build(#[from] BuildError),
49}
50
51#[derive(Builder)]
55#[builder(start_fn = new, finish_fn(name = _build, vis = ""))]
56pub struct InstallProject<'a, T>
57where
58 T: InstallTree,
59{
60 project: &'a Project,
61
62 config: &'a Config,
63
64 tree: &'a T,
65
66 progress: Option<Arc<Progress<MultiProgress>>>,
67}
68
69impl<
70 T: InstallTree + Sync + Send + Clone + 'static,
71 State: install_project_builder::State + install_project_builder::IsComplete,
72 > InstallProjectBuilder<'_, T, State>
73{
74 pub async fn build(self) -> Result<LocalPackage, InstallProjectError> {
76 let args = self._build();
77 let config = args.config;
78 let project = args.project;
79 let tree = args.tree;
80 let build_tree = tree.build_tree(config)?;
81 let progress_arc = args
82 .progress
83 .clone()
84 .unwrap_or_else(|| MultiProgress::new_arc(args.config));
85 let lua = LuaInstallation::new_from_config(
86 config,
87 &progress_arc.map(|progress| progress.new_bar()),
88 )
89 .await?;
90 let luarocks = LuaRocksInstallation::new(config, build_tree.clone())?;
91 let mut dependencies_to_install = Vec::new();
92 let mut build_dependencies_to_install = Vec::new();
93 let project_toml = project.toml().into_local()?;
94 prepare_dependencies_for_build(
95 &project_toml,
96 tree,
97 &mut dependencies_to_install,
98 &mut build_dependencies_to_install,
99 );
100
101 InstallDependencies::new()
102 .dependencies(dependencies_to_install.into_iter().unique().collect_vec())
103 .build_dependencies(
104 build_dependencies_to_install
105 .into_iter()
106 .unique()
107 .collect_vec(),
108 )
109 .tree(tree)
110 .lua(&lua)
111 .luarocks(&luarocks)
112 .config(config)
113 .progress(progress_arc.clone())
114 .build()
115 .await
116 .map_err(InstallProjectError::InstallBuildDependencies)?;
117
118 let package = Build::new()
119 .rockspec(&project_toml)
120 .lua(&lua)
121 .tree(tree)
122 .entry_type(tree::EntryType::Entrypoint)
123 .config(config)
124 .progress(&progress_arc.map(|p| p.new_bar()))
125 .behaviour(BuildBehaviour::Force)
126 .build()
127 .await?;
128
129 let lockfile = tree.lockfile()?;
130 let dependencies = lockfile
131 .rocks()
132 .iter()
133 .filter_map(|(pkg_id, value)| {
134 if lockfile.is_entrypoint(pkg_id) {
135 Some(value)
136 } else {
137 None
138 }
139 })
140 .cloned()
141 .collect_vec();
142 let mut lockfile = lockfile.write_guard();
143 lockfile.add_entrypoint(&package);
144 for dep in dependencies {
145 lockfile.add_dependency(&package, &dep);
146 lockfile.remove_entrypoint(&dep);
147 }
148 Ok(package)
149 }
150}