use {
crate::{config::QuasarConfig, error::CliResult, style, utils},
std::{
path::PathBuf,
process::{Command, Stdio},
},
};
pub fn run(
program_keypair: Option<PathBuf>,
upgrade_authority: Option<PathBuf>,
keypair: Option<PathBuf>,
url: Option<String>,
skip_build: bool,
) -> CliResult {
let config = QuasarConfig::load()?;
let name = &config.project.name;
if !skip_build {
crate::build::run(false, false, None)?;
}
let so_path = utils::find_so(&config, false).unwrap_or_else(|| {
eprintln!(
"\n {}",
style::fail(&format!("no compiled binary found for \"{name}\""))
);
eprintln!();
eprintln!(" Run {} first.", style::bold("quasar build"));
eprintln!();
std::process::exit(1);
});
let keypair_path = program_keypair.unwrap_or_else(|| {
let default = PathBuf::from("target")
.join("deploy")
.join(format!("{}-keypair.json", name));
if !default.exists() {
let module = config.module_name();
let alt = PathBuf::from("target")
.join("deploy")
.join(format!("{module}-keypair.json"));
if alt.exists() {
return alt;
}
}
default
});
if !keypair_path.exists() {
eprintln!(
"\n {}",
style::fail(&format!(
"program keypair not found: {}",
keypair_path.display()
))
);
eprintln!();
eprintln!(
" Run {} to generate one, or pass {} explicitly.",
style::bold("quasar build"),
style::bold("--program-keypair")
);
eprintln!();
std::process::exit(1);
}
let sp = style::spinner("Deploying...");
let mut cmd = Command::new("solana");
cmd.args([
"program",
"deploy",
so_path.to_str().unwrap_or_default(),
"--program-id",
keypair_path.to_str().unwrap_or_default(),
]);
if let Some(authority) = &upgrade_authority {
cmd.args([
"--upgrade-authority",
authority.to_str().unwrap_or_default(),
]);
}
if let Some(payer) = &keypair {
cmd.args(["--keypair", payer.to_str().unwrap_or_default()]);
}
if let Some(cluster) = &url {
cmd.args(["--url", cluster]);
}
let output = cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).output();
sp.finish_and_clear();
match output {
Ok(o) if o.status.success() => {
let stdout = String::from_utf8_lossy(&o.stdout);
let program_id = stdout
.lines()
.find(|l| l.contains("Program Id:"))
.and_then(|l| l.split(':').nth(1))
.map(|s| s.trim())
.unwrap_or("(unknown)");
println!(
"\n {}",
style::success(&format!("Deployed to {}", style::bold(program_id)))
);
println!();
Ok(())
}
Ok(o) => {
let stderr = String::from_utf8_lossy(&o.stderr);
let stdout = String::from_utf8_lossy(&o.stdout);
if !stderr.is_empty() {
eprintln!();
for line in stderr.lines() {
eprintln!(" {line}");
}
}
if !stdout.is_empty() {
for line in stdout.lines() {
eprintln!(" {line}");
}
}
eprintln!();
eprintln!(" {}", style::fail("deploy failed"));
std::process::exit(o.status.code().unwrap_or(1));
}
Err(e) => {
eprintln!(
"\n {}",
style::fail(&format!("failed to run solana program deploy: {e}"))
);
eprintln!();
eprintln!(
" Make sure the {} CLI is installed and configured.",
style::bold("solana")
);
eprintln!();
std::process::exit(1);
}
}
}