]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/rustc_tools_util/src/lib.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / clippy / rustc_tools_util / src / lib.rs
1 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
2
3 /// This macro creates the version string during compilation from the
4 /// current environment
5 #[macro_export]
6 macro_rules! get_version_info {
7 () => {{
8 let major = std::env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
9 let minor = std::env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
10 let patch = std::env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
11 let crate_name = String::from(std::env!("CARGO_PKG_NAME"));
12
13 let host_compiler = std::option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
14 let commit_hash = std::option_env!("GIT_HASH").map(str::to_string);
15 let commit_date = std::option_env!("COMMIT_DATE").map(str::to_string);
16
17 $crate::VersionInfo {
18 major,
19 minor,
20 patch,
21 host_compiler,
22 commit_hash,
23 commit_date,
24 crate_name,
25 }
26 }};
27 }
28
29 /// This macro can be used in `build.rs` to automatically set the needed
30 /// environment values, namely `GIT_HASH`, `COMMIT_DATE` and
31 /// `RUSTC_RELEASE_CHANNEL`
32 #[macro_export]
33 macro_rules! setup_version_info {
34 () => {{
35 println!(
36 "cargo:rustc-env=GIT_HASH={}",
37 $crate::get_commit_hash().unwrap_or_default()
38 );
39 println!(
40 "cargo:rustc-env=COMMIT_DATE={}",
41 $crate::get_commit_date().unwrap_or_default()
42 );
43 println!("cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", $crate::get_channel());
44 }};
45 }
46
47 // some code taken and adapted from RLS and cargo
48 pub struct VersionInfo {
49 pub major: u8,
50 pub minor: u8,
51 pub patch: u16,
52 pub host_compiler: Option<String>,
53 pub commit_hash: Option<String>,
54 pub commit_date: Option<String>,
55 pub crate_name: String,
56 }
57
58 impl std::fmt::Display for VersionInfo {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 let hash = self.commit_hash.clone().unwrap_or_default();
61 let hash_trimmed = hash.trim();
62
63 let date = self.commit_date.clone().unwrap_or_default();
64 let date_trimmed = date.trim();
65
66 if (hash_trimmed.len() + date_trimmed.len()) > 0 {
67 write!(
68 f,
69 "{} {}.{}.{} ({hash_trimmed} {date_trimmed})",
70 self.crate_name, self.major, self.minor, self.patch,
71 )?;
72 } else {
73 write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
74 }
75
76 Ok(())
77 }
78 }
79
80 impl std::fmt::Debug for VersionInfo {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 write!(
83 f,
84 "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}",
85 self.crate_name, self.major, self.minor, self.patch,
86 )?;
87 if self.commit_hash.is_some() {
88 write!(
89 f,
90 ", commit_hash: \"{}\", commit_date: \"{}\" }}",
91 self.commit_hash.clone().unwrap_or_default().trim(),
92 self.commit_date.clone().unwrap_or_default().trim()
93 )?;
94 } else {
95 write!(f, " }}")?;
96 }
97
98 Ok(())
99 }
100 }
101
102 #[must_use]
103 pub fn get_commit_hash() -> Option<String> {
104 std::process::Command::new("git")
105 .args(["rev-parse", "--short", "HEAD"])
106 .output()
107 .ok()
108 .and_then(|r| String::from_utf8(r.stdout).ok())
109 }
110
111 #[must_use]
112 pub fn get_commit_date() -> Option<String> {
113 std::process::Command::new("git")
114 .args(["log", "-1", "--date=short", "--pretty=format:%cd"])
115 .output()
116 .ok()
117 .and_then(|r| String::from_utf8(r.stdout).ok())
118 }
119
120 #[must_use]
121 pub fn get_channel() -> String {
122 match std::env::var("CFG_RELEASE_CHANNEL") {
123 Ok(channel) => channel,
124 Err(_) => {
125 // if that failed, try to ask rustc -V, do some parsing and find out
126 match std::process::Command::new("rustc")
127 .arg("-V")
128 .output()
129 .ok()
130 .and_then(|r| String::from_utf8(r.stdout).ok())
131 {
132 Some(rustc_output) => {
133 if rustc_output.contains("beta") {
134 String::from("beta")
135 } else if rustc_output.contains("stable") {
136 String::from("stable")
137 } else {
138 // default to nightly if we fail to parse
139 String::from("nightly")
140 }
141 },
142 // default to nightly
143 None => String::from("nightly"),
144 }
145 },
146 }
147 }
148
149 #[cfg(test)]
150 mod test {
151 use super::*;
152
153 #[test]
154 fn test_struct_local() {
155 let vi = get_version_info!();
156 assert_eq!(vi.major, 0);
157 assert_eq!(vi.minor, 3);
158 assert_eq!(vi.patch, 0);
159 assert_eq!(vi.crate_name, "rustc_tools_util");
160 // hard to make positive tests for these since they will always change
161 assert!(vi.commit_hash.is_none());
162 assert!(vi.commit_date.is_none());
163 }
164
165 #[test]
166 fn test_display_local() {
167 let vi = get_version_info!();
168 assert_eq!(vi.to_string(), "rustc_tools_util 0.3.0");
169 }
170
171 #[test]
172 fn test_debug_local() {
173 let vi = get_version_info!();
174 let s = format!("{vi:?}");
175 assert_eq!(
176 s,
177 "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 3, patch: 0 }"
178 );
179 }
180 }