From 8c34b46a22960e3f91ae3ad5eeff6be92df4dc1b Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Sat, 3 Apr 2021 17:41:48 +0100 Subject: [PATCH] Version output changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Bring what's shown in the version string in line with my other projects (URL, description, git hash and date for release-mode non-final builds only, potential for colours in the future) • Show +git or -git depending on feature status • Tests for the above, and for checking that the command-line flag is warned about --- Justfile | 6 ++ build.rs | 112 +++++++++++++++++------ src/options/version.rs | 6 +- xtests/features/none.toml | 27 ++++++ xtests/features/outputs/disabled_git.txt | 1 + 5 files changed, 120 insertions(+), 32 deletions(-) create mode 100644 xtests/features/none.toml create mode 100644 xtests/features/outputs/disabled_git.txt diff --git a/Justfile b/Justfile index 3c62a73..867fc80 100644 --- a/Justfile +++ b/Justfile @@ -79,6 +79,12 @@ all-release: build-release test-release command -v cargo-hack >/dev/null || (echo "cargo-hack not installed" && exit 1) cargo hack check --feature-powerset +# build exa and run extended tests with features disabled +@feature-checks *args: + cargo build --no-default-features + specsheet xtests/features/none.toml -shide {{args}} \ + -O cmd.target.exa="${CARGO_TARGET_DIR:-../../target}/debug/exa" + # print versions of the necessary build tools @versions: rustc --version diff --git a/build.rs b/build.rs index ea0de1d..f27aa24 100644 --- a/build.rs +++ b/build.rs @@ -10,11 +10,50 @@ /// - https://stackoverflow.com/q/43753491/3484614 /// - https://crates.io/crates/vergen -extern crate datetime; use std::env; -use std::io; +use std::fs::File; +use std::io::{self, Write}; +use std::path::PathBuf; + +use datetime::{LocalDateTime, ISO}; +/// The build script entry point. +fn main() -> io::Result<()> { + #![allow(clippy::write_with_newline)] + + let tagline = "exa - list files on the command-line"; + let url = "https://the.exa.website/"; + + let ver = + if is_debug_build() { + format!("{}\nv{} \\1;31m(pre-release debug build!)\\0m\n\\1;4;34m{}\\0m", tagline, version_string(), url) + } + else if is_development_version() { + format!("{}\nv{} [{}] built on {} \\1;31m(pre-release!)\\0m\n\\1;4;34m{}\\0m", tagline, version_string(), git_hash(), build_date(), url) + } + else { + format!("{}\nv{}\n\\1;4;34m{}\\0m", tagline, version_string(), url) + }; + + // We need to create these files in the Cargo output directory. + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + + // Bland version text + let mut f = File::create(&out.join("version_string.txt"))?; + writeln!(f, "{}", strip_codes(&ver))?; + + Ok(()) +} + +/// Removes escape codes from a string. +fn strip_codes(input: &str) -> String { + input.replace("\\0m", "") + .replace("\\1;31m", "") + .replace("\\1;4;34m", "") +} + +/// Retrieve the project’s current Git hash, as a string. fn git_hash() -> String { use std::process::Command; @@ -25,40 +64,59 @@ fn git_hash() -> String { .stdout).trim().to_string() } -fn main() { - write_statics().unwrap(); -} - +/// Whether we should show pre-release info in the version string. +/// +/// Both weekly releases and actual releases are --release releases, +/// but actual releases will have a proper version number. fn is_development_version() -> bool { - // Both weekly releases and actual releases are --release releases, - // but actual releases will have a proper version number cargo_version().ends_with("-pre") || env::var("PROFILE").unwrap() == "debug" } +/// Whether we are building in debug mode. +fn is_debug_build() -> bool { + env::var("PROFILE").unwrap() == "debug" +} + +/// Retrieves the [package] version in Cargo.toml as a string. fn cargo_version() -> String { env::var("CARGO_PKG_VERSION").unwrap() } -fn build_date() -> String { - use datetime::{LocalDateTime, ISO}; +/// Returns the version and build parameters string. +fn version_string() -> String { + let mut ver = cargo_version(); + let feats = nonstandard_features_string(); + if ! feats.is_empty() { + ver.push_str(&format!(" [{}]", &feats)); + } + + ver +} + +/// Finds whether a feature is enabled by examining the Cargo variable. +fn feature_enabled(name: &str) -> bool { + env::var(&format!("CARGO_FEATURE_{}", name)) + .map(|e| ! e.is_empty()) + .unwrap_or(false) +} + +/// A comma-separated list of non-standard feature choices. +fn nonstandard_features_string() -> String { + let mut s = Vec::new(); + + if feature_enabled("GIT") { + s.push("+git"); + } + else { + s.push("-git"); + } + + s.join(", ") +} + +/// Formats the current date as an ISO 8601 string. +fn build_date() -> String { let now = LocalDateTime::now(); format!("{}", now.date().iso()) } - -fn write_statics() -> io::Result<()> { - use std::fs::File; - use std::io::Write; - use std::path::PathBuf; - - let ver = if is_development_version() { - format!("exa v{} ({} built on {})", cargo_version(), git_hash(), build_date()) - } - else { - format!("exa v{}", cargo_version()) - }; - - let out = PathBuf::from(env::var("OUT_DIR").unwrap()); - let mut f = File::create(&out.join("version_string.txt"))?; - write!(f, "{:?}", ver) -} diff --git a/src/options/version.rs b/src/options/version.rs index 3a52f70..2214164 100644 --- a/src/options/version.rs +++ b/src/options/version.rs @@ -31,11 +31,7 @@ impl VersionString { impl fmt::Display for VersionString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - writeln!( - f, - "{} (git support: {})", - include!(concat!(env!("OUT_DIR"), "/version_string.txt")), - if cfg!(feature = "git") { "enabled" } else { "disabled" }) + write!(f, "{}", include_str!(concat!(env!("OUT_DIR"), "/version_string.txt"))) } } diff --git a/xtests/features/none.toml b/xtests/features/none.toml new file mode 100644 index 0000000..b0c39c9 --- /dev/null +++ b/xtests/features/none.toml @@ -0,0 +1,27 @@ +# These tests are meant to be run against an exa binary compiled with +# `--no-default-features`. They will fail otherwise. + + +[[cmd]] +name = "The missing features are documented in the version" +shell = "exa --version" +stdout = { string = "[-git]" } +stderr = { empty = true } +status = 0 +tags = [ 'features' ] + +[[cmd]] +name = "The ‘--git’ option is not accepted when the feature is disabled" +shell = "exa --git" +stdout = { empty = true } +stderr = { file = "outputs/disabled_git.txt" } +status = 3 +tags = [ 'features' ] + +[[cmd]] +name = "The ‘--git-ignore option is not accepted when the feature is disabled" +shell = "exa --git-ignore" +stdout = { empty = true } +stderr = { file = "outputs/disabled_git.txt" } +status = 3 +tags = [ 'features' ] diff --git a/xtests/features/outputs/disabled_git.txt b/xtests/features/outputs/disabled_git.txt new file mode 100644 index 0000000..6001bad --- /dev/null +++ b/xtests/features/outputs/disabled_git.txt @@ -0,0 +1 @@ +exa: Options --git and --git-ignore can't be used because `git` feature was disabled in this build of exa