diff --git a/Makefile.in b/Makefile.in index f4862903678..da0256b129b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,28 +9,22 @@ include config.mk export PATH := $(dir $(CFG_RUSTC)):$(PATH) ifeq ($(CFG_RELEASE_CHANNEL),stable) -CFG_RELEASE=$(CFG_RELEASE_NUM) CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) else ifeq ($(CFG_RELEASE_CHANNEL),beta) -CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION) CFG_PACKAGE_VERS=beta else ifeq ($(CFG_RELEASE_CHANNEL),nightly) -CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly CFG_PACKAGE_VERS=nightly else ifeq ($(CFG_RELEASE_CHANNEL),dev) -CFG_RELEASE=$(CFG_RELEASE_NUM)-dev CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-dev endif # allow build systems to use a constant date instead of the current one CFG_BUILD_DATE = $(shell SOURCE_DATE_EPOCH="$${SOURCE_DATE_EPOCH:-$$(date +%s)}" ; date -u -d "@$$SOURCE_DATE_EPOCH" +%F 2>/dev/null || date -u -r "$$SOURCE_DATE_EPOCH" +%F 2>/dev/null || date -u +%F) -ifeq ($(wildcard $(CFG_SRC_DIR)/.git),) -CFG_VERSION = $(CFG_RELEASE) (built $(CFG_BUILD_DATE)) -else -CFG_VER_DATE = $(shell git --git-dir='$(CFG_SRC_DIR).git' log -1 --date=short --pretty=format:'%cd') -CFG_VER_HASH = $(shell git --git-dir='$(CFG_SRC_DIR).git' rev-parse --short HEAD) -CFG_VERSION = $(CFG_RELEASE) ($(CFG_VER_HASH) $(CFG_VER_DATE)) +ifneq ($(wildcard $(CFG_SRC_DIR)/.git),) +CFG_COMMIT_DATE = $(shell git --git-dir='$(CFG_SRC_DIR).git' log -1 --date=short --pretty=format:'%cd') +CFG_SHORT_COMMIT_HASH = $(shell git --git-dir='$(CFG_SRC_DIR).git' rev-parse --short HEAD) +CFG_COMMIT_HASH = $(shell git --git-dir='$(CFG_SRC_DIR).git' rev-parse HEAD) endif PKG_NAME = cargo-$(CFG_PACKAGE_VERS) @@ -58,7 +52,25 @@ endif S := $(CFG_SRC_DIR)/ +CFG_RELEASE_PARTS := $(subst ., ,$(CFG_RELEASE_NUM)) +CFG_VERSION_MAJOR := $(word 1,$(CFG_RELEASE_PARTS)) +CFG_VERSION_MINOR := $(word 2,$(CFG_RELEASE_PARTS)) +CFG_VERSION_PATCH := $(word 3,$(CFG_RELEASE_PARTS)) + export CFG_VERSION +export CFG_VERSION_MAJOR +export CFG_VERSION_MINOR +export CFG_VERSION_PATCH +ifneq ($(CFG_PRERELEASE_VERSION),) +export CFG_PRERELEASE_VERSION +endif +ifneq ($(CFG_COMMIT_HASH),) +export CFG_COMMIT_HASH +export CFG_COMMIT_DATE +export CFG_SHORT_COMMIT_HASH +endif +export CFG_BUILD_DATE +export CFG_RELEASE_CHANNEL export CFG_DISABLE_CROSS_TESTS ifeq ($(OS),Windows_NT) diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index c9149c51af5..8b9d1a23573 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -128,7 +128,18 @@ fn execute(flags: Flags, config: &Config) -> CliResult> { let _token = cargo::util::job::setup(); if flags.flag_version { - println!("{}", cargo::version()); + let version = cargo::version(); + println!("{}", version); + if flags.flag_verbose > 0{ + println!("release: {}.{}.{}", + version.major, version.minor, version.patch); + if let Some(ref cfg) = version.cfg_info { + if let Some(ref ci) = cfg.commit_info { + println!("commit-hash: {}", ci.commit_hash); + println!("commit-date: {}", ci.commit_date); + } + } + } return Ok(None) } diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs old mode 100644 new mode 100755 index f0a93022a78..fbcb62c1e0f --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -26,6 +26,7 @@ extern crate toml; extern crate url; use std::env; +use std::fmt; use std::io; use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::json; @@ -49,6 +50,62 @@ 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, + // The date that the build was performed. + pub build_date: String, + // The release channel we were built for. + pub release_channel: String, +} + +pub struct VersionInfo { + pub major: String, + pub minor: String, + pub patch: String, + pub pre_release: Option, + // Information that's only available when we were built with + // configure/make, rather than cargo itself. + pub cfg_info: Option, +} + +impl fmt::Display for VersionInfo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "cargo-{}.{}.{}", + self.major, self.minor, self.patch)?; + match self.cfg_info.as_ref().map(|ci| &ci.release_channel) { + Some(channel) => { + if channel != "stable" { + write!(f, "-{}", channel)?; + let empty = String::from(""); + write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?; + } + }, + None => (), + }; + + if let Some(ref cfg) = self.cfg_info { + match cfg.commit_info { + Some(ref ci) => { + write!(f, " ({} {})", + ci.short_commit_hash, ci.commit_date)?; + }, + None => { + write!(f, " (built {})", + cfg.build_date)?; + } + } + }; + Ok(()) + } +} + pub fn execute_main_without_stdin( exec: fn(T, &Config) -> CliResult>, options_first: bool, @@ -208,15 +265,47 @@ fn handle_cause(mut cargo_err: &CargoError, shell: &mut MultiShell) -> bool { } } -pub fn version() -> String { - format!("cargo {}", match option_env!("CFG_VERSION") { - Some(s) => s.to_string(), - None => format!("{}.{}.{}{}", - env!("CARGO_PKG_VERSION_MAJOR"), - env!("CARGO_PKG_VERSION_MINOR"), - env!("CARGO_PKG_VERSION_PATCH"), - option_env!("CARGO_PKG_VERSION_PRE").unwrap_or("")) - }) +pub fn version() -> VersionInfo { + macro_rules! env_str { + ($name:expr) => { env!($name).to_string() } + } + macro_rules! option_env_str { + ($name:expr) => { option_env!($name).map(|s| s.to_string()) } + } + 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: option_env_str!("CFG_VERSION_MAJOR").unwrap(), + minor: option_env_str!("CFG_VERSION_MINOR").unwrap(), + patch: option_env_str!("CFG_VERSION_PATCH").unwrap(), + pre_release: option_env_str!("CFG_PRERELEASE_VERSION"), + cfg_info: Some(CfgInfo { + build_date: option_env_str!("CFG_BUILD_DATE").unwrap(), + release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(), + commit_info: commit_info, + }), + } + }, + // We are being compiled by Cargo itself. + None => { + VersionInfo { + major: env_str!("CARGO_PKG_VERSION_MAJOR"), + minor: env_str!("CARGO_PKG_VERSION_MINOR"), + patch: env_str!("CARGO_PKG_VERSION_PATCH"), + pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"), + cfg_info: None, + } + } + } } fn flags_from_args(usage: &str, args: &[String], options_first: bool) -> CliResult diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index f3c8de93415..f8ca6dbc403 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -225,7 +225,7 @@ pub fn http_handle(config: &Config) -> CargoResult { handle.connect_timeout(Duration::new(30, 0))?; handle.low_speed_limit(10 /* bytes per second */)?; handle.low_speed_time(Duration::new(30, 0))?; - handle.useragent(&version())?; + handle.useragent(&version().to_string())?; if let Some(proxy) = http_proxy(config)? { handle.proxy(&proxy)?; }