#![cfg_attr(test, deny(warnings))]
#![warn(rust_2018_idioms)]
#![allow(clippy::boxed_local)] #![allow(clippy::cyclomatic_complexity)] #![allow(clippy::derive_hash_xor_eq)] #![allow(clippy::explicit_into_iter_loop)] #![allow(clippy::explicit_iter_loop)] #![allow(clippy::identity_op)] #![allow(clippy::implicit_hasher)] #![allow(clippy::large_enum_variant)] #![allow(clippy::redundant_closure_call)] #![allow(clippy::too_many_arguments)] #![allow(clippy::type_complexity)] #![allow(clippy::wrong_self_convention)]
use std::fmt;
use failure::Error;
use log::debug;
use serde::ser;
use crate::core::shell::Verbosity::Verbose;
use crate::core::Shell;
pub use crate::util::errors::Internal;
pub use crate::util::{CargoResult, CliError, CliResult, Config};
pub const CARGO_ENV: &str = "CARGO";
#[macro_use]
mod macros;
pub mod core;
pub mod ops;
pub mod sources;
pub mod util;
pub struct CommitInfo {
pub short_commit_hash: String,
pub commit_hash: String,
pub commit_date: String,
}
pub struct CfgInfo {
pub commit_info: Option<CommitInfo>,
pub release_channel: String,
}
pub struct VersionInfo {
pub major: u8,
pub minor: u8,
pub patch: u8,
pub pre_release: Option<String>,
pub cfg_info: Option<CfgInfo>,
}
impl fmt::Display for VersionInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "cargo {}.{}.{}", self.major, self.minor, self.patch)?;
if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
if channel != "stable" {
write!(f, "-{}", channel)?;
let empty = String::new();
write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
}
};
if let Some(ref cfg) = self.cfg_info {
if let Some(ref ci) = cfg.commit_info {
write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
}
};
Ok(())
}
}
pub fn print_json<T: ser::Serialize>(obj: &T) {
let encoded = serde_json::to_string(&obj).unwrap();
println!("{}", encoded);
}
pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
debug!("exit_with_error; err={:?}", err);
if let Some(ref err) = err.error {
if let Some(clap_err) = err.downcast_ref::<clap::Error>() {
clap_err.exit()
}
}
let CliError {
error,
exit_code,
unknown,
} = err;
let fatal = exit_code != 0;
let hide = unknown && shell.verbosity() != Verbose;
if let Some(error) = error {
if hide {
drop(shell.error("An unknown error occurred"))
} else if fatal {
drop(shell.error(&error))
} else {
println!("{}", error);
}
if !handle_cause(&error, shell) || hide {
drop(writeln!(
shell.err(),
"\nTo learn more, run the command again \
with --verbose."
));
}
}
std::process::exit(exit_code)
}
pub fn handle_error(err: &failure::Error, shell: &mut Shell) {
debug!("handle_error; err={:?}", err);
let _ignored_result = shell.error(err);
handle_cause(err, shell);
}
fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool {
fn print(error: &str, shell: &mut Shell) {
drop(writeln!(shell.err(), "\nCaused by:"));
drop(writeln!(shell.err(), " {}", error));
}
let verbose = shell.verbosity();
if verbose == Verbose {
for err in cargo_err.iter_causes() {
print(&err.to_string(), shell);
}
} else {
for err in cargo_err.iter_causes() {
if err.downcast_ref::<Internal>().is_some() {
return false;
}
print(&err.to_string(), shell);
}
}
true
}
pub fn version() -> VersionInfo {
macro_rules! option_env_str {
($name:expr) => {
option_env!($name).map(|s| s.to_string())
};
}
let major = 1;
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
match option_env!("CFG_RELEASE_CHANNEL") {
Some(_) => {
let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
commit_hash: s.to_string(),
short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
});
VersionInfo {
major,
minor,
patch,
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
cfg_info: Some(CfgInfo {
release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
commit_info,
}),
}
}
None => VersionInfo {
major,
minor,
patch,
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
cfg_info: None,
},
}
}