1use std::{fmt::Display, process::exit};
4
5use crate::build_info::VERSION;
6use clap::ValueEnum;
7
8#[derive(ValueEnum, Debug, Clone)]
10#[value(rename_all = "kebab-case")]
11pub enum VersionFormat {
12 None,
14 Short,
16 Features,
18 Full,
20 Json,
22 JsonPlain,
24}
25
26impl Display for VersionFormat {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 f.write_str(self.to_possible_value().unwrap().get_name())
29 }
30}
31
32#[derive(serde::Serialize, serde::Deserialize)]
34struct VersionInfo {
35 name: &'static str,
36 version: &'static str,
37 features: Vec<&'static str>,
38
39 program_semver: &'static str,
40 program_commit_hash: &'static str,
41 program_target_triple: &'static str,
42 program_opt_level: &'static str,
43 program_build_timestamp: &'static str,
44
45 rustc_semver: &'static str,
46 rustc_commit_hash: &'static str,
47 rustc_host_triple: &'static str,
48 rustc_channel: &'static str,
49 rustc_llvm_version: &'static str,
50}
51
52impl VersionInfo {
53 fn new() -> Self {
54 Self {
55 name: "mitex-cli",
56 version: VERSION,
57 features: env!("VERGEN_CARGO_FEATURES").split(',').collect::<Vec<_>>(),
58 program_semver: match env!("VERGEN_GIT_DESCRIBE") {
59 "VERGEN_IDEMPOTENT_OUTPUT" => "000000000000",
60 s => s,
61 },
62 program_commit_hash: match env!("VERGEN_GIT_SHA") {
63 "VERGEN_IDEMPOTENT_OUTPUT" => "0000000000000000000000000000000000000000",
64 s => s,
65 },
66 program_target_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
67 program_opt_level: env!("VERGEN_CARGO_OPT_LEVEL"),
68 program_build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
69
70 rustc_semver: env!("VERGEN_RUSTC_SEMVER"),
71 rustc_commit_hash: env!("VERGEN_RUSTC_COMMIT_HASH"),
72 rustc_host_triple: env!("VERGEN_RUSTC_HOST_TRIPLE"),
73 rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
74 rustc_llvm_version: env!("VERGEN_RUSTC_LLVM_VERSION"),
75 }
76 }
77
78 fn program_build(&self) -> String {
79 format!(
80 "{} with opt_level({}) at {}",
81 self.program_target_triple, self.program_opt_level, self.program_build_timestamp
82 )
83 }
84
85 fn rustc_build(&self) -> String {
86 format!(
87 "{}-{} with LLVM {}",
88 self.rustc_host_triple, self.rustc_channel, self.rustc_llvm_version
89 )
90 }
91}
92
93impl Default for VersionInfo {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99pub fn intercept_version(v: bool, f: VersionFormat) {
104 let f = match f {
105 VersionFormat::None if v => VersionFormat::Short,
106 VersionFormat::None => return,
107 _ => f,
108 };
109 let version_info = VersionInfo::new();
110 match f {
111 VersionFormat::Full => print_full_version(version_info),
112 VersionFormat::Features => println!("{}", version_info.features.join(",")),
113 VersionFormat::Json => {
114 println!("{}", serde_json::to_string_pretty(&version_info).unwrap())
115 }
116 VersionFormat::JsonPlain => println!("{}", serde_json::to_string(&version_info).unwrap()),
117 _ => print_short_version(version_info),
118 }
119 exit(0);
120}
121
122fn print_full_version(vi: VersionInfo) {
123 let program_semver = vi.program_semver;
124 let program_commit_hash = vi.program_commit_hash;
125 let program_build = vi.program_build();
126
127 let rustc_semver = vi.rustc_semver;
128 let rustc_commit_hash = vi.rustc_commit_hash;
129 let rustc_build = vi.rustc_build();
130
131 print_short_version(vi);
132 println!(
133 r##"
134program-ver: {program_semver}
135program-rev: {program_commit_hash}
136program-build: {program_build}
137
138rustc-ver: {rustc_semver}
139rustc-rev: {rustc_commit_hash}
140rustc-build: {rustc_build}"##
141 );
142}
143
144fn print_short_version(vi: VersionInfo) {
145 let name = vi.name;
146 let version = vi.version;
147 let features = vi
148 .features
149 .iter()
150 .copied()
151 .filter(|&s| s != "default" && !s.ends_with("_exporter"))
152 .collect::<Vec<_>>()
153 .join(" ");
154
155 println!(
156 r##"{name} version {version}
157features: {features}"##
158 );
159}