cargo/version.rs
1//! Code for representing cargo's release version number.
2
3use std::fmt;
4
5/// Information about the git repository where cargo was built from.
6pub struct CommitInfo {
7 pub short_commit_hash: String,
8 pub commit_hash: String,
9 pub commit_date: String,
10}
11
12/// Cargo's version.
13pub struct VersionInfo {
14 /// Cargo's version, such as "1.57.0", "1.58.0-beta.1", "1.59.0-nightly", etc.
15 pub version: String,
16 /// The release channel we were built for (stable/beta/nightly/dev).
17 ///
18 /// `None` if not built via bootstrap.
19 pub release_channel: Option<String>,
20 /// Information about the Git repository we may have been built from.
21 ///
22 /// `None` if not built from a git repo.
23 pub commit_info: Option<CommitInfo>,
24}
25
26impl fmt::Display for VersionInfo {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "{}", self.version)?;
29
30 if let Some(ref ci) = self.commit_info {
31 write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
32 };
33 Ok(())
34 }
35}
36
37/// Returns information about cargo's version.
38pub fn version() -> VersionInfo {
39 macro_rules! option_env_str {
40 ($name:expr) => {
41 option_env!($name).map(|s| s.to_string())
42 };
43 }
44
45 // This is the version set in bootstrap, which we use to match rustc.
46 let version = option_env_str!("CFG_RELEASE").unwrap_or_else(|| {
47 // If cargo is not being built by bootstrap, then we just use the
48 // version from cargo's own `Cargo.toml`.
49 //
50 // There are two versions at play here:
51 // - version of cargo-the-binary, which you see when you type `cargo --version`
52 // - version of cargo-the-library, which you download from crates.io for use
53 // in your packages.
54 //
55 // The library is permanently unstable, so it always has a 0 major
56 // version. However, the CLI now reports a stable 1.x version
57 // (starting in 1.26) which stays in sync with rustc's version.
58 //
59 // Coincidentally, the minor version for cargo-the-library is always
60 // +1 of rustc's minor version (that is, `rustc 1.11.0` corresponds to
61 // `cargo `0.12.0`). The versions always get bumped in lockstep, so
62 // this should continue to hold.
63 let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
64 let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
65 format!("1.{}.{}", minor, patch)
66 });
67
68 let release_channel = option_env_str!("CFG_RELEASE_CHANNEL");
69 let commit_info = option_env_str!("CARGO_COMMIT_HASH").map(|commit_hash| CommitInfo {
70 short_commit_hash: option_env_str!("CARGO_COMMIT_SHORT_HASH").unwrap(),
71 commit_hash,
72 commit_date: option_env_str!("CARGO_COMMIT_DATE").unwrap(),
73 });
74
75 VersionInfo {
76 version,
77 release_channel,
78 commit_info,
79 }
80}