1*d4726bddSHONG Yifan //! Command line interface entry points and utilities
2*d4726bddSHONG Yifan
3*d4726bddSHONG Yifan mod generate;
4*d4726bddSHONG Yifan mod query;
5*d4726bddSHONG Yifan mod splice;
6*d4726bddSHONG Yifan mod vendor;
7*d4726bddSHONG Yifan
8*d4726bddSHONG Yifan use clap::Parser;
9*d4726bddSHONG Yifan use tracing::{Level, Subscriber};
10*d4726bddSHONG Yifan use tracing_subscriber::fmt::format::{Format, Full};
11*d4726bddSHONG Yifan use tracing_subscriber::fmt::time::SystemTime;
12*d4726bddSHONG Yifan use tracing_subscriber::fmt::{FormatEvent, FormatFields};
13*d4726bddSHONG Yifan use tracing_subscriber::registry::LookupSpan;
14*d4726bddSHONG Yifan use tracing_subscriber::FmtSubscriber;
15*d4726bddSHONG Yifan
16*d4726bddSHONG Yifan pub use self::generate::GenerateOptions;
17*d4726bddSHONG Yifan pub use self::query::QueryOptions;
18*d4726bddSHONG Yifan pub use self::splice::SpliceOptions;
19*d4726bddSHONG Yifan pub use self::vendor::VendorOptions;
20*d4726bddSHONG Yifan
21*d4726bddSHONG Yifan // Entrypoints
22*d4726bddSHONG Yifan pub use generate::generate;
23*d4726bddSHONG Yifan pub use query::query;
24*d4726bddSHONG Yifan pub use splice::splice;
25*d4726bddSHONG Yifan pub use vendor::vendor;
26*d4726bddSHONG Yifan
27*d4726bddSHONG Yifan #[derive(Parser, Debug)]
28*d4726bddSHONG Yifan #[clap(
29*d4726bddSHONG Yifan name = "cargo-bazel",
30*d4726bddSHONG Yifan about = "crate_universe` is a collection of tools which use Cargo to generate build targets for Bazel.",
31*d4726bddSHONG Yifan version
32*d4726bddSHONG Yifan )]
33*d4726bddSHONG Yifan pub enum Options {
34*d4726bddSHONG Yifan /// Generate Bazel Build files from a Cargo manifest.
35*d4726bddSHONG Yifan Generate(GenerateOptions),
36*d4726bddSHONG Yifan
37*d4726bddSHONG Yifan /// Splice together disjoint Cargo and Bazel info into a single Cargo workspace manifest.
38*d4726bddSHONG Yifan Splice(SpliceOptions),
39*d4726bddSHONG Yifan
40*d4726bddSHONG Yifan /// Query workspace info to determine whether or not a repin is needed.
41*d4726bddSHONG Yifan Query(QueryOptions),
42*d4726bddSHONG Yifan
43*d4726bddSHONG Yifan /// Vendor BUILD files to the workspace with either repository definitions or `cargo vendor` generated sources.
44*d4726bddSHONG Yifan Vendor(VendorOptions),
45*d4726bddSHONG Yifan }
46*d4726bddSHONG Yifan
47*d4726bddSHONG Yifan // Convenience wrappers to avoid dependencies in the binary
48*d4726bddSHONG Yifan pub type Result<T> = anyhow::Result<T>;
49*d4726bddSHONG Yifan
parse_args() -> Options50*d4726bddSHONG Yifan pub fn parse_args() -> Options {
51*d4726bddSHONG Yifan Options::parse()
52*d4726bddSHONG Yifan }
53*d4726bddSHONG Yifan
54*d4726bddSHONG Yifan const EXPECTED_LOGGER_NAMES: [&str; 4] = ["Generate", "Splice", "Query", "Vendor"];
55*d4726bddSHONG Yifan
56*d4726bddSHONG Yifan /// A wrapper for the tracing-subscriber default [FormatEvent]
57*d4726bddSHONG Yifan /// that prepends the name of the active CLI option.
58*d4726bddSHONG Yifan struct LoggingFormatEvent {
59*d4726bddSHONG Yifan name: String,
60*d4726bddSHONG Yifan base: Format<Full, SystemTime>,
61*d4726bddSHONG Yifan }
62*d4726bddSHONG Yifan
63*d4726bddSHONG Yifan impl<S, N> FormatEvent<S, N> for LoggingFormatEvent
64*d4726bddSHONG Yifan where
65*d4726bddSHONG Yifan S: Subscriber + for<'a> LookupSpan<'a>,
66*d4726bddSHONG Yifan N: for<'a> FormatFields<'a> + 'static,
67*d4726bddSHONG Yifan {
format_event( &self, ctx: &tracing_subscriber::fmt::FmtContext<'_, S, N>, mut writer: tracing_subscriber::fmt::format::Writer<'_>, event: &tracing::Event<'_>, ) -> std::fmt::Result68*d4726bddSHONG Yifan fn format_event(
69*d4726bddSHONG Yifan &self,
70*d4726bddSHONG Yifan ctx: &tracing_subscriber::fmt::FmtContext<'_, S, N>,
71*d4726bddSHONG Yifan mut writer: tracing_subscriber::fmt::format::Writer<'_>,
72*d4726bddSHONG Yifan event: &tracing::Event<'_>,
73*d4726bddSHONG Yifan ) -> std::fmt::Result {
74*d4726bddSHONG Yifan write!(writer, "{} ", self.name)?;
75*d4726bddSHONG Yifan self.base.format_event(ctx, writer, event)
76*d4726bddSHONG Yifan }
77*d4726bddSHONG Yifan }
78*d4726bddSHONG Yifan
79*d4726bddSHONG Yifan impl LoggingFormatEvent {
new(name: &str) -> Self80*d4726bddSHONG Yifan fn new(name: &str) -> Self {
81*d4726bddSHONG Yifan Self {
82*d4726bddSHONG Yifan name: name.to_owned(),
83*d4726bddSHONG Yifan base: Format::default(),
84*d4726bddSHONG Yifan }
85*d4726bddSHONG Yifan }
86*d4726bddSHONG Yifan }
87*d4726bddSHONG Yifan
88*d4726bddSHONG Yifan /// Initialize logging for one of the cli options.
init_logging(name: &str)89*d4726bddSHONG Yifan pub fn init_logging(name: &str) {
90*d4726bddSHONG Yifan if !EXPECTED_LOGGER_NAMES.contains(&name) {
91*d4726bddSHONG Yifan panic!(
92*d4726bddSHONG Yifan "Unexpected logger name {}, use of one of {:?}",
93*d4726bddSHONG Yifan name, EXPECTED_LOGGER_NAMES
94*d4726bddSHONG Yifan );
95*d4726bddSHONG Yifan }
96*d4726bddSHONG Yifan
97*d4726bddSHONG Yifan // a builder for `FmtSubscriber`.
98*d4726bddSHONG Yifan let subscriber = FmtSubscriber::builder()
99*d4726bddSHONG Yifan // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.)
100*d4726bddSHONG Yifan // will be written to stdout.
101*d4726bddSHONG Yifan .with_max_level(
102*d4726bddSHONG Yifan std::env::var("CARGO_BAZEL_DEBUG")
103*d4726bddSHONG Yifan .map(|_| Level::DEBUG)
104*d4726bddSHONG Yifan .unwrap_or(Level::INFO),
105*d4726bddSHONG Yifan )
106*d4726bddSHONG Yifan .event_format(LoggingFormatEvent::new(name))
107*d4726bddSHONG Yifan // completes the builder.
108*d4726bddSHONG Yifan .finish();
109*d4726bddSHONG Yifan
110*d4726bddSHONG Yifan tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
111*d4726bddSHONG Yifan }
112