in src/main.rs [2051:2177]
fn cmd_diff(out: &Arc<dyn Out>, cfg: &Config, sub_args: &DiffArgs) -> Result<(), miette::Report> {
let version1 = &sub_args.version1;
let version2 = &sub_args.version2;
let package = &*sub_args.package;
let to_compare = {
let network = Network::acquire(cfg);
let store = Store::acquire(cfg, network.as_ref(), false)?;
let cache = Cache::acquire(cfg)?;
// Record this command for magic in `vet certify`
cache.set_last_fetch(FetchCommand::Diff {
package: package.to_owned(),
version1: version1.clone(),
version2: version2.clone(),
});
// Determine the fetch mode to use. We'll need to do a local diff if the
// selected version has a git revision.
let mode = cache.select_fetch_mode(
sub_args.mode,
version1.git_rev.is_some() || version2.git_rev.is_some(),
);
if mode != FetchMode::Local {
let url = match mode {
FetchMode::Sourcegraph => {
format!(
"https://sourcegraph.com/crates/{package}/-/compare/v{version1}...v{version2}?visible=7000"
)
}
FetchMode::DiffRs => {
format!("https://diff.rs/{package}/{version1}/{version2}/")
}
FetchMode::Local => unreachable!(),
};
tokio::runtime::Handle::current()
.block_on(prompt_criteria_eulas(
out,
cfg,
network.as_ref(),
&store,
package,
Some(version1),
version2,
Some(&url),
))
.into_diagnostic()?;
open::that(&url).into_diagnostic().wrap_err_with(|| {
format!("Couldn't open {url} in your browser, try --mode=local?")
})?;
writeln!(out, "\nUse |cargo vet certify| to record your audit.");
return Ok(());
}
tokio::runtime::Handle::current().block_on(async {
// NOTE: don't `try_join` everything as we don't want to abort the
// prompt to the user if the download fails while it is being shown, as
// that could be disorienting.
let (to_compare, eulas) = tokio::join!(
async {
let (pkg1, pkg2) = tokio::try_join!(
cache.fetch_package(&cfg.metadata, network.as_ref(), package, version1),
cache.fetch_package(&cfg.metadata, network.as_ref(), package, version2)
)?;
let (_, to_compare) = cache
.diffstat_package(
&pkg1,
&pkg2,
version1.git_rev.is_some() || version2.git_rev.is_some(),
)
.await?;
Ok::<_, FetchAndDiffError>(to_compare)
},
prompt_criteria_eulas(
out,
cfg,
network.as_ref(),
&store,
package,
Some(version1),
version2,
None,
)
);
eulas.into_diagnostic()?;
to_compare.into_diagnostic()
})?
};
writeln!(out);
// Start a pager to show the output from our diff invocations. This will
// fall back to just printing to `stdout` if no pager is available or we're
// not piped to a terminal.
let mut pager = Pager::new(&**out).into_diagnostic()?;
for (from, to) in to_compare {
let output = std::process::Command::new("git")
.arg("-c")
.arg("core.safecrlf=false")
.arg("diff")
.arg(if pager.use_color() {
"--color=always"
} else {
"--color=never"
})
.arg("--no-index")
.arg("--ignore-cr-at-eol")
.arg(&from)
.arg(&to)
.stdout(Stdio::piped())
.output()
.map_err(CommandError::CommandFailed)
.into_diagnostic()?;
io::Write::write_all(&mut pager, &output.stdout).into_diagnostic()?;
}
pager.wait().into_diagnostic()?;
writeln!(out, "\nUse |cargo vet certify| to record your audit.");
Ok(())
}