92 lines
2.7 KiB
Rust
92 lines
2.7 KiB
Rust
mod config;
|
|
mod detect;
|
|
mod launcher;
|
|
mod tui;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use anyhow::{Context, Error, Result, bail};
|
|
use clap::{Parser, Subcommand};
|
|
use config::{Config, LauncherEntry, load_config};
|
|
use detect::detect_beamline;
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "aarel")]
|
|
struct Cli {
|
|
/// Path to the launcher config file.
|
|
#[arg(long, default_value = "data/defaults.json")]
|
|
config: PathBuf,
|
|
|
|
#[command(subcommand)]
|
|
command: Command,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
enum Command {
|
|
/// Enter the TUI to choose what to launch
|
|
#[command(alias = "p")]
|
|
Pick,
|
|
/// Launch the AareGUI with default settings
|
|
#[command(alias = "g")]
|
|
Gui {
|
|
/// Config entry (beamline) to launch. Defaults to the detected beamline.
|
|
#[arg(long)]
|
|
entry: Option<String>,
|
|
},
|
|
/// Launch the AareDAQ server with default settings
|
|
#[command(alias = "s")]
|
|
Server {
|
|
/// Config entry (beamline) to launch. Defaults to the detected beamline.
|
|
#[arg(long)]
|
|
entry: Option<String>,
|
|
},
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let cli = Cli::parse();
|
|
|
|
let json = std::fs::read_to_string(&cli.config)
|
|
.with_context(|| format!("failed to read config file {}", cli.config.display()))?;
|
|
let config = load_config(&json)?;
|
|
|
|
check_base_exists("deployments_base", &config.deployments_base, &cli.config)?;
|
|
check_base_exists("venvs_base", &config.deployments_base, &cli.config)?;
|
|
|
|
match cli.command {
|
|
Command::Pick => {
|
|
if let Some((python, entrypoint)) = tui::run(&config)? {
|
|
launcher::launch(&python, &entrypoint)?;
|
|
}
|
|
}
|
|
Command::Gui { entry } => launcher::launch_gui(lookup_entry(&config, entry)?)?,
|
|
Command::Server { entry } => launcher::launch_server(lookup_entry(&config, entry)?)?,
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Fail with a helpful message if a configured base directory is missing.
|
|
fn check_base_exists(field: &str, base: &Path, config_file: &Path) -> Result<()> {
|
|
if !base.is_dir() {
|
|
bail!(
|
|
"{field} '{}' does not exist — edit '{field}' in {} to point at a valid directory",
|
|
base.display(),
|
|
config_file.display(),
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Look up the launcher entry to use: the explicitly requested `entry`, or the
|
|
/// detected beamline when none was given.
|
|
fn lookup_entry(config: &Config, entry: Option<String>) -> Result<&LauncherEntry> {
|
|
let beamline = match entry {
|
|
Some(entry) => entry,
|
|
None => detect_beamline().map_err(Error::msg)?,
|
|
};
|
|
config
|
|
.entries
|
|
.get(&beamline)
|
|
.with_context(|| format!("no config entry for beamline '{beamline}'"))
|
|
}
|