vergen_pretty/
lib.rs

1// Copyright (c) 2022 vergen developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9//! `vergen-pretty` - A pretty printer for vergen environment variables
10//!
11//! Because `cargo` doesn't pass compile time environment variables to dependencies,
12//! the [`vergen_pretty_env`] macro embeds a map of all the possible `vergen` environment variables with
13//! [`option_env!`](std::option_env!).  Values not set in by your `build.rs` are skipped
14//! when pretty-printing the output.
15//!
16//! # Example
17//! ```
18//! # use anyhow::Result;
19//! # use std::{collections::BTreeMap, io::Write};
20//! # use vergen_pretty::{vergen_pretty_env, Pretty};
21//! # fn has_value(
22//! #     tuple: (&&'static str, &Option<&'static str>),
23//! # ) -> Option<(&'static str, &'static str)> {
24//! #     let (key, value) = tuple;
25//! #     if value.is_some() {
26//! #         Some((*key, value.unwrap_or_default()))
27//! #     } else {
28//! #         None
29//! #     }
30//! # }
31//! # fn is_empty(map: &BTreeMap<&'static str, Option<&'static str>>) -> bool {
32//! #     map.iter().filter_map(has_value).count() == 0
33//! # }
34//! # fn main() -> Result<()> {
35//! let mut stdout = vec![];
36//! # let map = vergen_pretty_env!();
37//! # let empty = is_empty(&map);
38//! Pretty::builder()
39//!     .env(vergen_pretty_env!())
40//!     .build()
41//!     .display(&mut stdout)?;
42//! # if empty {
43//! #    assert!(stdout.is_empty());
44//! # } else {
45//! assert!(!stdout.is_empty());
46//! # }
47//! #     Ok(())
48//! # }
49//! ```
50//!
51//! See the [`Pretty`] documentation for more examples
52//!
53#![cfg_attr(
54    feature = "header",
55    doc = r"If you enable the header feature, you can also use the [`header()`] function
56with the associated [`Config`] as a convenience wrapper around [`Pretty`].
57
58# Example
59```
60# use anyhow::Result;
61# use vergen_pretty::{Config, header, vergen_pretty_env};"
62)]
63#![cfg_attr(feature = "color", doc = r"# use vergen_pretty::Style;")]
64#![cfg_attr(
65    feature = "header",
66    doc = r"
67#
68# pub fn main() -> Result<()> {
69let mut buf = vec![];
70let config = Config::builder()"
71)]
72#![cfg_attr(
73    all(feature = "color", feature = "header"),
74    doc = r"    .style(Style::new().green())"
75)]
76#![cfg_attr(
77    feature = "header",
78    doc = r#"
79    .prefix("HEADER_PREFIX")
80    .env(vergen_pretty_env!())
81    .suffix("HEADER_SUFFIX")
82    .build();
83assert!(header(&config, Some(&mut buf)).is_ok());
84assert!(!buf.is_empty());
85#     Ok(())
86# }
87```
88"#
89)]
90//!
91//! ## Features
92//! `vergen-pretty` has two feature toggles allowing you to customize your output. No features are enabled by default.
93//! You **must** specifically enable the features you wish to use.
94//!
95//! | Feature | Enables |
96//! | ------- | ------- |
97//! |  color  | Colorize output, allow configuration of coloring via [`console`] |
98//! |  header | Generate pretty printed header output based on the given [`Config`] |
99//! |  trace  | Enable support for [`tracing`](https://docs.rs/tracing/latest/tracing/) output |
100//!
101
102// rustc lints
103#![cfg_attr(
104    all(feature = "unstable", nightly),
105    feature(
106        multiple_supertrait_upcastable,
107        must_not_suspend,
108        non_exhaustive_omitted_patterns_lint,
109        rustdoc_missing_doc_code_examples,
110        strict_provenance_lints,
111        supertrait_item_shadowing,
112        unqualified_local_imports,
113    )
114)]
115#![cfg_attr(nightly, allow(single_use_lifetimes, unexpected_cfgs))]
116#![cfg_attr(
117    nightly,
118    deny(
119        absolute_paths_not_starting_with_crate,
120        ambiguous_glob_imports,
121        ambiguous_glob_reexports,
122        ambiguous_negative_literals,
123        ambiguous_wide_pointer_comparisons,
124        anonymous_parameters,
125        array_into_iter,
126        asm_sub_register,
127        async_fn_in_trait,
128        bad_asm_style,
129        bare_trait_objects,
130        boxed_slice_into_iter,
131        break_with_label_and_loop,
132        clashing_extern_declarations,
133        closure_returning_async_block,
134        coherence_leak_check,
135        confusable_idents,
136        const_evaluatable_unchecked,
137        const_item_mutation,
138        dangling_pointers_from_temporaries,
139        dead_code,
140        dependency_on_unit_never_type_fallback,
141        deprecated,
142        deprecated_in_future,
143        deprecated_safe_2024,
144        deprecated_where_clause_location,
145        deref_into_dyn_supertrait,
146        deref_nullptr,
147        double_negations,
148        drop_bounds,
149        dropping_copy_types,
150        dropping_references,
151        duplicate_macro_attributes,
152        dyn_drop,
153        // Add this back with 2024 edition
154        // edition_2024_expr_fragment_specifier,
155        elided_lifetimes_in_paths,
156        ellipsis_inclusive_range_patterns,
157        explicit_outlives_requirements,
158        exported_private_dependencies,
159        ffi_unwind_calls,
160        forbidden_lint_groups,
161        forgetting_copy_types,
162        forgetting_references,
163        for_loops_over_fallibles,
164        function_item_references,
165        hidden_glob_reexports,
166        if_let_rescope,
167        impl_trait_overcaptures,
168        impl_trait_redundant_captures,
169        improper_ctypes,
170        improper_ctypes_definitions,
171        inline_no_sanitize,
172        internal_features,
173        invalid_from_utf8,
174        invalid_macro_export_arguments,
175        invalid_nan_comparisons,
176        invalid_value,
177        irrefutable_let_patterns,
178        keyword_idents_2018,
179        keyword_idents_2024,
180        large_assignments,
181        late_bound_lifetime_arguments,
182        legacy_derive_helpers,
183        let_underscore_drop,
184        macro_use_extern_crate,
185        map_unit_fn,
186        meta_variable_misuse,
187        mismatched_lifetime_syntaxes,
188        missing_abi,
189        missing_copy_implementations,
190        missing_debug_implementations,
191        missing_docs,
192        missing_unsafe_on_extern,
193        mixed_script_confusables,
194        named_arguments_used_positionally,
195        never_type_fallback_flowing_into_unsafe,
196        no_mangle_generic_items,
197        non_ascii_idents,
198        non_camel_case_types,
199        non_contiguous_range_endpoints,
200        non_fmt_panics,
201        non_local_definitions,
202        non_shorthand_field_patterns,
203        non_snake_case,
204        non_upper_case_globals,
205        noop_method_call,
206        opaque_hidden_inferred_bound,
207        out_of_scope_macro_calls,
208        overlapping_range_endpoints,
209        path_statements,
210        private_bounds,
211        private_interfaces,
212        ptr_to_integer_transmute_in_consts,
213        redundant_imports,
214        redundant_lifetimes,
215        redundant_semicolons,
216        refining_impl_trait_internal,
217        refining_impl_trait_reachable,
218        renamed_and_removed_lints,
219        repr_transparent_external_private_fields,
220        rust_2021_incompatible_closure_captures,
221        rust_2021_incompatible_or_patterns,
222        rust_2021_prefixes_incompatible_syntax,
223        rust_2021_prelude_collisions,
224        rust_2024_guarded_string_incompatible_syntax,
225        rust_2024_incompatible_pat,
226        rust_2024_prelude_collisions,
227        self_constructor_from_outer_item,
228        semicolon_in_expressions_from_macros,
229        single_use_lifetimes,
230        special_module_name,
231        stable_features,
232        static_mut_refs,
233        suspicious_double_ref_op,
234        tail_expr_drop_order,
235        trivial_bounds,
236        trivial_casts,
237        trivial_numeric_casts,
238        type_alias_bounds,
239        tyvar_behind_raw_pointer,
240        uncommon_codepoints,
241        unconditional_recursion,
242        uncovered_param_in_projection,
243        unfulfilled_lint_expectations,
244        ungated_async_fn_track_caller,
245        uninhabited_static,
246        unit_bindings,
247        unknown_lints,
248        unknown_or_malformed_diagnostic_attributes,
249        unnameable_test_items,
250        unnameable_types,
251        unpredictable_function_pointer_comparisons,
252        unreachable_code,
253        unreachable_patterns,
254        unreachable_pub,
255        unsafe_attr_outside_unsafe,
256        unsafe_code,
257        unsafe_op_in_unsafe_fn,
258        unstable_name_collisions,
259        unstable_syntax_pre_expansion,
260        unused_allocation,
261        unused_assignments,
262        unused_associated_type_bounds,
263        unused_attributes,
264        unused_braces,
265        unused_comparisons,
266        unused_crate_dependencies,
267        unused_doc_comments,
268        unused_extern_crates,
269        unused_features,
270        unused_import_braces,
271        unused_imports,
272        unused_labels,
273        unused_lifetimes,
274        unused_macro_rules,
275        unused_macros,
276        unused_must_use,
277        unused_mut,
278        unused_parens,
279        unused_qualifications,
280        unused_results,
281        unused_unsafe,
282        unused_variables,
283        useless_ptr_null_checks,
284        uses_power_alignment,
285        variant_size_differences,
286        while_true,
287    )
288)]
289// If nightly and unstable, allow `incomplete_features` and `unstable_features`
290#![cfg_attr(
291    all(feature = "unstable", nightly),
292    allow(incomplete_features, unstable_features)
293)]
294// If nightly and not unstable, deny `incomplete_features` and `unstable_features`
295#![cfg_attr(
296    all(not(feature = "unstable"), nightly),
297    deny(incomplete_features, unstable_features)
298)]
299// The unstable lints
300#![cfg_attr(
301    all(feature = "unstable", nightly),
302    deny(
303        fuzzy_provenance_casts,
304        lossy_provenance_casts,
305        multiple_supertrait_upcastable,
306        must_not_suspend,
307        non_exhaustive_omitted_patterns,
308        supertrait_item_shadowing_definition,
309        supertrait_item_shadowing_usage,
310        unqualified_local_imports,
311    )
312)]
313// clippy lints
314#![cfg_attr(nightly, deny(clippy::all, clippy::pedantic))]
315#![cfg_attr(nightly, allow(clippy::doc_markdown))]
316// rustdoc lints
317#![cfg_attr(
318    nightly,
319    deny(
320        rustdoc::bare_urls,
321        rustdoc::broken_intra_doc_links,
322        rustdoc::invalid_codeblock_attributes,
323        rustdoc::invalid_html_tags,
324        rustdoc::missing_crate_level_docs,
325        rustdoc::private_doc_tests,
326        rustdoc::private_intra_doc_links,
327    )
328)]
329#![cfg_attr(
330    all(nightly, feature = "unstable"),
331    deny(rustdoc::missing_doc_code_examples)
332)]
333#![cfg_attr(all(docsrs, nightly), feature(doc_cfg))]
334#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
335
336#[cfg(feature = "header")]
337mod header;
338mod pretty;
339mod utils;
340
341#[cfg(feature = "header")]
342pub use self::header::Config;
343#[cfg(feature = "header")]
344pub use self::header::Env;
345#[cfg(feature = "header")]
346pub use self::header::header;
347pub use self::pretty::Pretty;
348#[cfg(any(feature = "bincode", feature = "serde"))]
349pub use self::pretty::feature::PrettyExt;
350pub use self::pretty::prefix::Prefix;
351pub use self::pretty::suffix::Suffix;
352#[cfg(feature = "color")]
353#[doc(inline)]
354pub use console::Style;
355#[cfg(feature = "trace")]
356#[doc(inline)]
357pub use tracing::Level;
358
359#[cfg(all(feature = "header", not(feature = "color")))]
360use rand as _;
361#[cfg(test)]
362use regex as _;
363#[cfg(all(test, not(feature = "serde")))]
364use serde_json as _;
365#[cfg(all(test, not(feature = "trace")))]
366use tracing_subscriber as _;
367
368/// Used to initialize `env` in [`Pretty`](self::Pretty)
369///
370/// Because `cargo` doesn't pass compile time environment variables to dependencies,
371/// this macro embeds a map of all the possible `vergen` environment variables with
372/// [`option_env!`](std::option_env!).  Non-set values are skipped when pretty-printing the output.
373///
374/// # Example
375/// ```
376/// # use anyhow::Result;
377/// # use std::{collections::BTreeMap, io::Write};
378/// # use vergen_pretty::{vergen_pretty_env, Pretty};
379/// #
380/// # fn main() -> Result<()> {
381/// let mut stdout = vec![];
382/// Pretty::builder()
383///     .env(vergen_pretty_env!())
384///     .build()
385///     .display(&mut stdout)?;
386/// #     Ok(())
387/// # }
388#[macro_export]
389macro_rules! vergen_pretty_env {
390    () => {{
391        use std::collections::BTreeMap;
392        let mut map = BTreeMap::new();
393        let _old = map.insert("VERGEN_BUILD_DATE", option_env!("VERGEN_BUILD_DATE"));
394        let _old = map.insert(
395            "VERGEN_BUILD_TIMESTAMP",
396            option_env!("VERGEN_BUILD_TIMESTAMP"),
397        );
398        let _old = map.insert("VERGEN_CARGO_DEBUG", option_env!("VERGEN_CARGO_DEBUG"));
399        let _old = map.insert(
400            "VERGEN_CARGO_FEATURES",
401            option_env!("VERGEN_CARGO_FEATURES"),
402        );
403        let _old = map.insert(
404            "VERGEN_CARGO_OPT_LEVEL",
405            option_env!("VERGEN_CARGO_OPT_LEVEL"),
406        );
407        let _old = map.insert(
408            "VERGEN_CARGO_TARGET_TRIPLE",
409            option_env!("VERGEN_CARGO_TARGET_TRIPLE"),
410        );
411        let _old = map.insert(
412            "VERGEN_CARGO_DEPENDENCIES",
413            option_env!("VERGEN_CARGO_DEPENDENCIES"),
414        );
415        let _old = map.insert("VERGEN_GIT_BRANCH", option_env!("VERGEN_GIT_BRANCH"));
416        let _old = map.insert(
417            "VERGEN_GIT_COMMIT_AUTHOR_EMAIL",
418            option_env!("VERGEN_GIT_COMMIT_AUTHOR_EMAIL"),
419        );
420        let _old = map.insert(
421            "VERGEN_GIT_COMMIT_AUTHOR_NAME",
422            option_env!("VERGEN_GIT_COMMIT_AUTHOR_NAME"),
423        );
424        let _old = map.insert(
425            "VERGEN_GIT_COMMIT_COUNT",
426            option_env!("VERGEN_GIT_COMMIT_COUNT"),
427        );
428        let _old = map.insert(
429            "VERGEN_GIT_COMMIT_DATE",
430            option_env!("VERGEN_GIT_COMMIT_DATE"),
431        );
432        let _old = map.insert(
433            "VERGEN_GIT_COMMIT_MESSAGE",
434            option_env!("VERGEN_GIT_COMMIT_MESSAGE"),
435        );
436        let _old = map.insert(
437            "VERGEN_GIT_COMMIT_TIMESTAMP",
438            option_env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
439        );
440        let _old = map.insert("VERGEN_GIT_DESCRIBE", option_env!("VERGEN_GIT_DESCRIBE"));
441        let _old = map.insert("VERGEN_GIT_SHA", option_env!("VERGEN_GIT_SHA"));
442        let _old = map.insert("VERGEN_GIT_DIRTY", option_env!("VERGEN_GIT_DIRTY"));
443        let _old = map.insert("VERGEN_RUSTC_CHANNEL", option_env!("VERGEN_RUSTC_CHANNEL"));
444        let _old = map.insert(
445            "VERGEN_RUSTC_COMMIT_DATE",
446            option_env!("VERGEN_RUSTC_COMMIT_DATE"),
447        );
448        let _old = map.insert(
449            "VERGEN_RUSTC_COMMIT_HASH",
450            option_env!("VERGEN_RUSTC_COMMIT_HASH"),
451        );
452        let _old = map.insert(
453            "VERGEN_RUSTC_HOST_TRIPLE",
454            option_env!("VERGEN_RUSTC_HOST_TRIPLE"),
455        );
456        let _old = map.insert(
457            "VERGEN_RUSTC_LLVM_VERSION",
458            option_env!("VERGEN_RUSTC_LLVM_VERSION"),
459        );
460        let _old = map.insert("VERGEN_RUSTC_SEMVER", option_env!("VERGEN_RUSTC_SEMVER"));
461        let _old = map.insert("VERGEN_SYSINFO_NAME", option_env!("VERGEN_SYSINFO_NAME"));
462        let _old = map.insert(
463            "VERGEN_SYSINFO_OS_VERSION",
464            option_env!("VERGEN_SYSINFO_OS_VERSION"),
465        );
466        let _old = map.insert("VERGEN_SYSINFO_USER", option_env!("VERGEN_SYSINFO_USER"));
467        let _old = map.insert(
468            "VERGEN_SYSINFO_TOTAL_MEMORY",
469            option_env!("VERGEN_SYSINFO_TOTAL_MEMORY"),
470        );
471        let _old = map.insert(
472            "VERGEN_SYSINFO_CPU_VENDOR",
473            option_env!("VERGEN_SYSINFO_CPU_VENDOR"),
474        );
475        let _old = map.insert(
476            "VERGEN_SYSINFO_CPU_CORE_COUNT",
477            option_env!("VERGEN_SYSINFO_CPU_CORE_COUNT"),
478        );
479        let _old = map.insert(
480            "VERGEN_SYSINFO_CPU_NAME",
481            option_env!("VERGEN_SYSINFO_CPU_NAME"),
482        );
483        let _old = map.insert(
484            "VERGEN_SYSINFO_CPU_BRAND",
485            option_env!("VERGEN_SYSINFO_CPU_BRAND"),
486        );
487        let _old = map.insert(
488            "VERGEN_SYSINFO_CPU_FREQUENCY",
489            option_env!("VERGEN_SYSINFO_CPU_FREQUENCY"),
490        );
491        map
492    }};
493    ( $( $x:expr ),* ) => {{
494        {
495            let mut map = $crate::vergen_pretty_env!();
496            $(
497                let _old = map.insert($x, option_env!($x));
498            )*
499            map
500        }
501    }};
502}