use std::path::Path;
use std::time::Duration;
use weave_cli::land::{self, Resolver};
use weave_core::host::Host;
type R<T> = Result<T, Box<dyn std::error::Error>>;
pub(crate) struct Args<'a> {
pub base: Option<&'a str>,
pub ours: Option<&'a str>,
pub theirs: Option<&'a str>,
pub resolver: Option<&'a str>,
pub resolver_timeout: u64,
pub json: bool,
pub certificate: Option<&'a str>,
pub dry_run: bool,
pub result: Option<&'a str>,
}
pub(crate) fn run(args: Args<'_>, host: &Host) -> R<()> {
match land(args, host) {
Ok(refused) => std::process::exit(if refused { 1 } else { 0 }),
Err(e) => {
eprintln!("weave land: {e}. The run did not finish; no label from it stands.");
std::process::exit(2);
}
}
}
pub(crate) struct OntoArgs<'a> {
pub target: &'a str,
pub resolver: Option<&'a str>,
pub resolver_timeout: u64,
pub verify_cmd: Option<&'a str>,
pub verify_timeout: u64,
pub check: Option<&'a str>,
pub checkers: Option<&'a str>,
pub attempts: usize,
pub certificate_dir: Option<&'a str>,
}
pub(crate) fn run_onto(args: OntoArgs<'_>, host: &Host) -> R<()> {
let run = || -> R<weave_cli::onto::Outcome> {
let (remote, branch) = weave_cli::onto::split_target(args.target)?;
let opts = weave_cli::onto::Options {
remote,
branch,
resolver: args.resolver.map(|command| Resolver {
command: command.to_string(),
timeout: Duration::from_secs(args.resolver_timeout),
}),
verify_cmd: args.verify_cmd.map(str::to_string),
verify_timeout: Duration::from_secs(args.verify_timeout),
check: weave_cli::semcheck::resolve(args.check, args.checkers, Path::new("."))?,
attempts: args.attempts,
certificate_dir: args.certificate_dir.map(std::path::PathBuf::from),
};
let mut out = std::io::stdout();
weave_cli::onto::land_onto(Path::new("."), &opts, host, &mut out)
};
match run() {
Ok(weave_cli::onto::Outcome::Landed(_)) => std::process::exit(0),
Ok(weave_cli::onto::Outcome::Refused(_)) => std::process::exit(1),
Err(e) => {
eprintln!("weave land: {e}. Nothing was published.");
std::process::exit(2);
}
}
}
pub(crate) fn run_queue(
args: OntoArgs<'_>,
lease_ttl: u64,
queue_timeout: u64,
host: &Host,
) -> R<()> {
let run = || -> R<weave_cli::queue::QueueOutcome> {
let (remote, branch) = weave_cli::onto::split_target(args.target)?;
let q = weave_cli::queue::QueueOptions {
onto: weave_cli::onto::Options {
remote,
branch,
resolver: args.resolver.map(|command| Resolver {
command: command.to_string(),
timeout: Duration::from_secs(args.resolver_timeout),
}),
verify_cmd: args.verify_cmd.map(str::to_string),
verify_timeout: Duration::from_secs(args.verify_timeout),
check: weave_cli::semcheck::resolve(args.check, args.checkers, Path::new("."))?,
attempts: args.attempts,
certificate_dir: args.certificate_dir.map(std::path::PathBuf::from),
},
lease_ttl: Duration::from_secs(lease_ttl.max(1)),
wait_timeout: Duration::from_secs(queue_timeout),
poll: Duration::from_millis(400),
};
let mut out = std::io::stdout();
weave_cli::queue::submit(Path::new("."), &q, host, &mut out)
};
match run() {
Ok(weave_cli::queue::QueueOutcome::Landed(_)) => std::process::exit(0),
Ok(weave_cli::queue::QueueOutcome::Refused(_)) => std::process::exit(1),
Err(e) => {
eprintln!("weave land --queue: {e}. Nothing was published by this run.");
std::process::exit(2);
}
}
}
fn land(args: Args<'_>, host: &Host) -> R<bool> {
let run = land::Run {
base: args.base,
ours: args.ours,
theirs: args.theirs,
result: args.result,
resolver: args.resolver.map(|command| Resolver {
command: command.to_string(),
timeout: Duration::from_secs(args.resolver_timeout),
}),
dry_run: args.dry_run,
};
let landing = land::run(Path::new("."), &run, host)?;
if let Some(path) = args.certificate {
std::fs::write(path, serde_json::to_string_pretty(&landing.doc)? + "\n")
.map_err(|e| format!("could not write the certificate to {path}: {e}"))?;
}
if args.json {
println!("{}", serde_json::to_string_pretty(&landing.doc)?);
} else {
print!("{}", landing.text);
}
Ok(landing.refused)
}