use crate::output::emit;
use crate::output::record::Record;
use crate::upgrade::MachineStep;
pub const USAGE: &str = "\
Usage: wsb upgrade [--ref <branch|tag>] [--dry-run]
Fetch wsb's repository at the ref (default main) into one checkout this
machine keeps for it, build wsb and wsb-daemon with QuickRust, start both,
and replace the installed pair in $QRUST_HOME/bin (else ~/.qrust/bin): both,
or neither. The new wsb then stops the daemon, migrates the machine's state
(`wsb migrate`), and a service installed with `wsb daemon install` is
reinstalled by it and restarted onto the new daemon.
--dry-run build and start both, say what would be replaced, and
replace nothing
Speaks --jsonl.";
pub fn dispatch(args: &[String]) -> u8 {
let mut reference = crate::upgrade::DEFAULT_REF.to_string();
let mut dry_run = false;
let mut arguments = args.iter();
while let Some(argument) = arguments.next() {
match argument.as_str() {
"--ref" => match arguments.next() {
Some(value) => reference = value.clone(),
None => {
crate::errln!("wsb upgrade: --ref needs a value\n\n{USAGE}");
return 2;
}
},
"--dry-run" => dry_run = true,
"help" | "--help" | "-h" => {
crate::outln!("{USAGE}");
return 0;
}
other => {
crate::errln!("wsb upgrade: unknown argument '{other}'\n\n{USAGE}");
return 2;
}
}
}
match upgrade(&reference, dry_run) {
Ok(()) => 0,
Err(message) => {
crate::errln!("wsb upgrade: {message}");
1
}
}
}
fn upgrade(reference: &str, dry_run: bool) -> Result<(), String> {
let report = crate::upgrade::run(reference, dry_run)?;
emit(Record::Upgrade {
from_version: report.from_version.clone(),
to_version: report.to_version.clone(),
reference: report.reference.clone(),
commit: report.commit.clone(),
replaced: report.replaced.iter().map(|p| p.display().to_string()).collect(),
dry_run: report.dry_run,
});
let from = report.from_version.as_deref().unwrap_or("a wsb that did not report its version");
let at = &report.commit[..report.commit.len().min(12)];
if report.dry_run {
crate::outln!("upgrade: would replace {from} with {} ({} at {at})", report.to_version, report.reference);
for path in &report.replaced {
crate::outln!(" {}", path.display());
}
crate::outln!("Nothing was replaced: --dry-run.");
return Ok(());
}
crate::outln!("upgrade: {from} \u{2192} {} ({} at {at})", report.to_version, report.reference);
for path in &report.replaced {
crate::outln!(" replaced {}", path.display());
}
let here = std::env::current_dir().map_err(|e| format!("cannot determine the current directory: {e}"))?;
match crate::upgrade::bring_the_machine_over(&report.install_dir, &here)? {
MachineStep::Restarted { worktree } => crate::outln!(
"the machine's state was migrated, and the service was reinstalled by the new wsb and \
restarted onto the new daemon (worktree {})",
worktree.display()
),
MachineStep::Stopped => crate::outln!(
"No service is installed: the daemon was stopped and the machine's state migrated; the \
next command starts the new daemon."
),
}
Ok(())
}