Skip to content

Commit fe69af3

Browse files
committed
Auto merge of #10178 - ehuss:version-from-rustc, r=alexcrichton
Sync cargo-the-cli version with rustc. People occasionally get confused when cargo's version does not match the version of rustc. This happens in a variety of scenarios: * Point releases. * Beta releases (cargo is missing the .1 .2, etc.) * Nightly releases when cargo's version has not yet been bumped. This changes it so that cargo-the-cli will always report the same version as rustc (assuming they were built with rustbuild). The git information remains the same (reports cargo's last commit sha). Closes #10122
2 parents 6d75259 + a58725a commit fe69af3

File tree

3 files changed

+98
-103
lines changed

3 files changed

+98
-103
lines changed

src/bin/cargo/cli.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,7 @@ pub fn get_version_string(is_verbose: bool) -> String {
164164
let version = cargo::version();
165165
let mut version_string = format!("cargo {}\n", version);
166166
if is_verbose {
167-
version_string.push_str(&format!(
168-
"release: {}.{}.{}\n",
169-
version.major, version.minor, version.patch
170-
));
167+
version_string.push_str(&format!("release: {}\n", version.version,));
171168
if let Some(ref cfg) = version.cfg_info {
172169
if let Some(ref ci) = cfg.commit_info {
173170
version_string.push_str(&format!("commit-hash: {}\n", ci.commit_hash));

src/cargo/lib.rs

+2-99
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ use crate::core::shell::Verbosity::Verbose;
1212
use crate::core::Shell;
1313
use anyhow::Error;
1414
use log::debug;
15-
use std::fmt;
1615

1716
pub use crate::util::errors::{InternalError, VerboseError};
1817
pub use crate::util::{indented_lines, CargoResult, CliError, CliResult, Config};
18+
pub use crate::version::version;
1919

2020
pub const CARGO_ENV: &str = "CARGO";
2121

@@ -26,49 +26,7 @@ pub mod core;
2626
pub mod ops;
2727
pub mod sources;
2828
pub mod util;
29-
30-
pub struct CommitInfo {
31-
pub short_commit_hash: String,
32-
pub commit_hash: String,
33-
pub commit_date: String,
34-
}
35-
36-
pub struct CfgInfo {
37-
// Information about the Git repository we may have been built from.
38-
pub commit_info: Option<CommitInfo>,
39-
// The release channel we were built for.
40-
pub release_channel: String,
41-
}
42-
43-
pub struct VersionInfo {
44-
pub major: u8,
45-
pub minor: u8,
46-
pub patch: u8,
47-
pub pre_release: Option<String>,
48-
// Information that's only available when we were built with
49-
// configure/make, rather than Cargo itself.
50-
pub cfg_info: Option<CfgInfo>,
51-
}
52-
53-
impl fmt::Display for VersionInfo {
54-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55-
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
56-
if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
57-
if channel != "stable" {
58-
write!(f, "-{}", channel)?;
59-
let empty = String::new();
60-
write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
61-
}
62-
};
63-
64-
if let Some(ref cfg) = self.cfg_info {
65-
if let Some(ref ci) = cfg.commit_info {
66-
write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
67-
}
68-
};
69-
Ok(())
70-
}
71-
}
29+
mod version;
7230

7331
pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
7432
debug!("exit_with_error; err={:?}", err);
@@ -143,58 +101,3 @@ fn _display_error(err: &Error, shell: &mut Shell, as_err: bool) -> bool {
143101
}
144102
false
145103
}
146-
147-
pub fn version() -> VersionInfo {
148-
macro_rules! option_env_str {
149-
($name:expr) => {
150-
option_env!($name).map(|s| s.to_string())
151-
};
152-
}
153-
154-
// So this is pretty horrible...
155-
// There are two versions at play here:
156-
// - version of cargo-the-binary, which you see when you type `cargo --version`
157-
// - version of cargo-the-library, which you download from crates.io for use
158-
// in your packages.
159-
//
160-
// We want to make the `binary` version the same as the corresponding Rust/rustc release.
161-
// At the same time, we want to keep the library version at `0.x`, because Cargo as
162-
// a library is (and probably will always be) unstable.
163-
//
164-
// Historically, Cargo used the same version number for both the binary and the library.
165-
// Specifically, rustc 1.x.z was paired with cargo 0.x+1.w.
166-
// We continue to use this scheme for the library, but transform it to 1.x.w for the purposes
167-
// of `cargo --version`.
168-
let major = 1;
169-
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
170-
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
171-
172-
match option_env!("CFG_RELEASE_CHANNEL") {
173-
// We have environment variables set up from configure/make.
174-
Some(_) => {
175-
let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
176-
commit_hash: s.to_string(),
177-
short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
178-
commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
179-
});
180-
VersionInfo {
181-
major,
182-
minor,
183-
patch,
184-
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
185-
cfg_info: Some(CfgInfo {
186-
release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
187-
commit_info,
188-
}),
189-
}
190-
}
191-
// We are being compiled by Cargo itself.
192-
None => VersionInfo {
193-
major,
194-
minor,
195-
patch,
196-
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
197-
cfg_info: None,
198-
},
199-
}
200-
}

src/cargo/version.rs

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

0 commit comments

Comments
 (0)