blob: 9172c97f66e55db1aa518bd624fc63e534845ce6 [file] [log] [blame]
//! Command line interface entry points and utilities
mod generate;
mod query;
mod splice;
mod vendor;
use clap::Parser;
use tracing::{Level, Subscriber};
use tracing_subscriber::fmt::format::{Format, Full};
use tracing_subscriber::fmt::time::SystemTime;
use tracing_subscriber::fmt::{FormatEvent, FormatFields};
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::FmtSubscriber;
pub use self::generate::GenerateOptions;
pub use self::query::QueryOptions;
pub use self::splice::SpliceOptions;
pub use self::vendor::VendorOptions;
// Entrypoints
pub use generate::generate;
pub use query::query;
pub use splice::splice;
pub use vendor::vendor;
#[derive(Parser, Debug)]
#[clap(
name = "cargo-bazel",
about = "crate_universe` is a collection of tools which use Cargo to generate build targets for Bazel.",
version
)]
pub enum Options {
/// Generate Bazel Build files from a Cargo manifest.
Generate(GenerateOptions),
/// Splice together disjoint Cargo and Bazel info into a single Cargo workspace manifest.
Splice(SpliceOptions),
/// Query workspace info to determine whether or not a repin is needed.
Query(QueryOptions),
/// Vendor BUILD files to the workspace with either repository definitions or `cargo vendor` generated sources.
Vendor(VendorOptions),
}
// Convenience wrappers to avoid dependencies in the binary
pub type Result<T> = anyhow::Result<T>;
pub fn parse_args() -> Options {
Options::parse()
}
const EXPECTED_LOGGER_NAMES: [&str; 4] = ["Generate", "Splice", "Query", "Vendor"];
/// A wrapper for the tracing-subscriber default [FormatEvent]
/// that prepends the name of the active CLI option.
struct LoggingFormatEvent {
name: String,
base: Format<Full, SystemTime>,
}
impl<S, N> FormatEvent<S, N> for LoggingFormatEvent
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &tracing_subscriber::fmt::FmtContext<'_, S, N>,
mut writer: tracing_subscriber::fmt::format::Writer<'_>,
event: &tracing::Event<'_>,
) -> std::fmt::Result {
write!(writer, "{} ", self.name)?;
self.base.format_event(ctx, writer, event)
}
}
impl LoggingFormatEvent {
fn new(name: &str) -> Self {
Self {
name: name.to_owned(),
base: Format::default(),
}
}
}
/// Initialize logging for one of the cli options.
pub fn init_logging(name: &str, verbose: bool) {
if !EXPECTED_LOGGER_NAMES.contains(&name) {
panic!(
"Unexpected logger name {}, use of one of {:?}",
name, EXPECTED_LOGGER_NAMES
);
}
// a builder for `FmtSubscriber`.
let subscriber = FmtSubscriber::builder()
// all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
// will be written to stdout.
.with_max_level(if verbose { Level::DEBUG } else { Level::INFO })
.event_format(LoggingFormatEvent::new(name))
// completes the builder.
.finish();
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
}