lux_cli/
exec.rs

1use std::env;
2
3use clap::Args;
4use eyre::Result;
5use lux_lib::{
6    config::{Config, LuaVersion},
7    operations::{self, install_command},
8    path::Paths,
9    project::Project,
10};
11use which::which;
12
13use crate::build::Build;
14
15#[derive(Args)]
16pub struct Exec {
17    /// The command to run.
18    command: String,
19
20    /// Arguments to pass to the program.
21    args: Option<Vec<String>>,
22
23    /// Do not add `require('lux').loader()` to `LUA_INIT`.
24    /// If a rock has conflicting transitive dependencies,
25    /// disabling the Lux loader may result in the wrong modules being loaded.
26    #[clap(default_value_t = false)]
27    #[arg(long)]
28    no_loader: bool,
29}
30
31pub async fn exec(run: Exec, config: Config) -> Result<()> {
32    let project = Project::current()?;
33    let tree = match &project {
34        Some(project) => project.tree(&config)?,
35        None => {
36            let lua_version = LuaVersion::from(&config)?.clone();
37            config.user_tree(lua_version)?
38        }
39    };
40
41    let paths = Paths::new(&tree)?;
42    unsafe {
43        // safe as long as this is single-threaded
44        env::set_var("PATH", paths.path_prepended().joined());
45    }
46    if which(&run.command).is_err() {
47        match project {
48            Some(_) => {
49                super::build::build(Build::default(), config.clone()).await?;
50            }
51            None => install_command(&run.command, &config).await?,
52        }
53    };
54    operations::Exec::new(&run.command, project.as_ref(), &config)
55        .args(run.args.unwrap_or_default())
56        .disable_loader(run.no_loader)
57        .exec()
58        .await?;
59    Ok(())
60}