use std::fs;
use anyhow::{Context, Result, bail};
use slave_gateway::Config;
use crate::{apps, project, runtime};
pub fn separate(name: &str) -> Result<()> {
set(name, true)?;
println!(
"App {name} now runs on its own; `slave build` then `slave serve` start it next to the runtime."
);
Ok(())
}
pub fn embed(name: &str) -> Result<()> {
set(name, false)?;
println!("App {name} is served by the runtime again; rebuild with `slave build`.");
Ok(())
}
fn set(name: &str, separate: bool) -> Result<()> {
let root = project::find_root()?;
runtime::require(&root)?;
if !root.join("apps").join(name).join("Cargo.toml").is_file() {
bail!("apps/{name} not found");
}
let path = root.join(apps::CONFIG);
let text =
fs::read_to_string(&path).with_context(|| format!("failed to read {}", apps::CONFIG))?;
let config = Config::parse(&text).with_context(|| format!("invalid {}", apps::CONFIG))?;
let entries: Vec<_> = config.domains.iter().filter(|d| d.app == name).collect();
if entries.is_empty() {
bail!("app `{name}` is not listed in {}", apps::CONFIG);
}
if let Some(entry) = entries.iter().find(|d| d.upstream.is_some()) {
bail!(
"`{}` sends {name} to upstream {}; edit {} by hand",
entry.label(),
entry.upstream.as_deref().unwrap_or_default(),
apps::CONFIG
);
}
let updated = apps::set_separate(&text, name, separate);
Config::parse(&updated).with_context(|| format!("cannot update {}", apps::CONFIG))?;
fs::write(&path, updated).with_context(|| format!("failed to update {}", apps::CONFIG))?;
println!(" updated {}", apps::CONFIG);
match (separate, runtime::has_app(&root, name)) {
(true, true) => runtime::remove_app(&root, name)?,
(false, false) => runtime::add_app(&root, name, &name.replace('-', "_"))?,
_ => {}
}
Ok(())
}