use clap::Args;
use microsandbox::sandbox::Sandbox;
use super::common::{SandboxOpts, apply_sandbox_opts, apply_sandbox_opts_after_config};
use crate::{sandbox_config, ui};
#[derive(Debug, Args)]
pub struct CreateArgs {
pub image: Option<String>,
#[command(flatten)]
pub sandbox: SandboxOpts,
}
pub async fn run(
mut args: CreateArgs,
log_level: Option<microsandbox::LogLevel>,
) -> anyhow::Result<()> {
let is_named = args.sandbox.name.is_some();
let name = args.sandbox.name.clone().unwrap_or_else(ui::generate_name);
if args.sandbox.log_level.is_none()
&& let Some(log_level) = log_level
{
args.sandbox.log_level = Some(log_level.to_string());
}
let resolved = sandbox_config::resolve(&args.sandbox.config)?;
let image = resolved.image(args.image.as_deref(), None)?;
let builder = resolved.apply(Sandbox::builder(&name))?;
let builder = image.apply(builder)?;
let builder = if resolved.loaded() {
apply_sandbox_opts_after_config(builder, &args.sandbox)?
} else {
apply_sandbox_opts(builder, &args.sandbox)?
};
let (mut progress, task) = builder
.detached(true)
.create_detached_with_pull_progress()?;
let mut display = if args.sandbox.quiet {
ui::PullProgressDisplay::quiet(&image.display())
} else {
ui::PullProgressDisplay::new(&image.display())
};
while let Some(event) = progress.recv().await {
display.handle_event(event);
}
match task.await {
Ok(Ok(sandbox)) => {
display.finish();
sandbox.detach().await;
if !is_named {
println!("{name}");
}
}
Ok(Err(e)) => {
display.finish();
return Err(e.into());
}
Err(e) => {
display.finish();
return Err(anyhow::anyhow!("create task panicked: {e}"));
}
}
Ok(())
}