Skip to content

Commit

Permalink
Auto merge of #10178 - ehuss:version-from-rustc, r=alexcrichton
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Dec 13, 2021
2 parents 6d75259 + a58725a commit fe69af3
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 103 deletions.
5 changes: 1 addition & 4 deletions src/bin/cargo/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,7 @@ pub fn get_version_string(is_verbose: bool) -> String {
let version = cargo::version();
let mut version_string = format!("cargo {}\n", version);
if is_verbose {
version_string.push_str(&format!(
"release: {}.{}.{}\n",
version.major, version.minor, version.patch
));
version_string.push_str(&format!("release: {}\n", version.version,));
if let Some(ref cfg) = version.cfg_info {
if let Some(ref ci) = cfg.commit_info {
version_string.push_str(&format!("commit-hash: {}\n", ci.commit_hash));
Expand Down
101 changes: 2 additions & 99 deletions src/cargo/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ use crate::core::shell::Verbosity::Verbose;
use crate::core::Shell;
use anyhow::Error;
use log::debug;
use std::fmt;

pub use crate::util::errors::{InternalError, VerboseError};
pub use crate::util::{indented_lines, CargoResult, CliError, CliResult, Config};
pub use crate::version::version;

pub const CARGO_ENV: &str = "CARGO";

Expand All @@ -26,49 +26,7 @@ pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub struct CommitInfo {
pub short_commit_hash: String,
pub commit_hash: String,
pub commit_date: String,
}

pub struct CfgInfo {
// Information about the Git repository we may have been built from.
pub commit_info: Option<CommitInfo>,
// The release channel we were built for.
pub release_channel: String,
}

pub struct VersionInfo {
pub major: u8,
pub minor: u8,
pub patch: u8,
pub pre_release: Option<String>,
// Information that's only available when we were built with
// configure/make, rather than Cargo itself.
pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
if channel != "stable" {
write!(f, "-{}", channel)?;
let empty = String::new();
write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
}
};

if let Some(ref cfg) = self.cfg_info {
if let Some(ref ci) = cfg.commit_info {
write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
}
};
Ok(())
}
}
mod version;

pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
debug!("exit_with_error; err={:?}", err);
Expand Down Expand Up @@ -143,58 +101,3 @@ fn _display_error(err: &Error, shell: &mut Shell, as_err: bool) -> bool {
}
false
}

pub fn version() -> VersionInfo {
macro_rules! option_env_str {
($name:expr) => {
option_env!($name).map(|s| s.to_string())
};
}

// So this is pretty horrible...
// There are two versions at play here:
// - version of cargo-the-binary, which you see when you type `cargo --version`
// - version of cargo-the-library, which you download from crates.io for use
// in your packages.
//
// We want to make the `binary` version the same as the corresponding Rust/rustc release.
// At the same time, we want to keep the library version at `0.x`, because Cargo as
// a library is (and probably will always be) unstable.
//
// Historically, Cargo used the same version number for both the binary and the library.
// Specifically, rustc 1.x.z was paired with cargo 0.x+1.w.
// We continue to use this scheme for the library, but transform it to 1.x.w for the purposes
// of `cargo --version`.
let major = 1;
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();

match option_env!("CFG_RELEASE_CHANNEL") {
// We have environment variables set up from configure/make.
Some(_) => {
let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
commit_hash: s.to_string(),
short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
});
VersionInfo {
major,
minor,
patch,
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
cfg_info: Some(CfgInfo {
release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
commit_info,
}),
}
}
// We are being compiled by Cargo itself.
None => VersionInfo {
major,
minor,
patch,
pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
cfg_info: None,
},
}
}
95 changes: 95 additions & 0 deletions src/cargo/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//! Code for representing cargo's release version number.

use std::fmt;

/// Information about the git repository where cargo was built from.
pub struct CommitInfo {
pub short_commit_hash: String,
pub commit_hash: String,
pub commit_date: String,
}

/// Information provided by the outer build system (rustbuild aka bootstrap).
pub struct CfgInfo {
/// Information about the Git repository we may have been built from.
pub commit_info: Option<CommitInfo>,
/// The release channel we were built for (stable/beta/nightly/dev).
pub release_channel: String,
}

/// Cargo's version.
pub struct VersionInfo {
/// Cargo's version, such as "1.57.0", "1.58.0-beta.1", "1.59.0-nightly", etc.
pub version: String,
/// Information that's only available when we were built with
/// rustbuild, rather than Cargo itself.
pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.version)?;

if let Some(ref cfg) = self.cfg_info {
if let Some(ref ci) = cfg.commit_info {
write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
}
};
Ok(())
}
}

/// Returns information about cargo's version.
pub fn version() -> VersionInfo {
macro_rules! option_env_str {
($name:expr) => {
option_env!($name).map(|s| s.to_string())
};
}

// This is the version set in rustbuild, which we use to match rustc.
let version = option_env_str!("CFG_RELEASE").unwrap_or_else(|| {
// If cargo is not being built by rustbuild, then we just use the
// version from cargo's own `Cargo.toml`.
//
// There are two versions at play here:
// - version of cargo-the-binary, which you see when you type `cargo --version`
// - version of cargo-the-library, which you download from crates.io for use
// in your packages.
//
// The library is permanently unstable, so it always has a 0 major
// version. However, the CLI now reports a stable 1.x version
// (starting in 1.26) which stays in sync with rustc's version.
//
// Coincidentally, the minor version for cargo-the-library is always
// +1 of rustc's minor version (that is, `rustc 1.11.0` corresponds to
// `cargo `0.12.0`). The versions always get bumped in lockstep, so
// this should continue to hold.
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
format!("1.{}.{}", minor, patch)
});

match option_env!("CFG_RELEASE_CHANNEL") {
// We have environment variables set up from configure/make.
Some(_) => {
let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
commit_hash: s.to_string(),
short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
});
VersionInfo {
version,
cfg_info: Some(CfgInfo {
release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
commit_info,
}),
}
}
// We are being compiled by Cargo itself.
None => VersionInfo {
version,
cfg_info: None,
},
}
}

0 comments on commit fe69af3

Please sign in to comment.