Prechádzať zdrojové kódy

Version output changes

• 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
Benjamin Sago 4 rokov pred
rodič
commit
8c34b46a22

+ 6 - 0
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

+ 81 - 23
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 now = LocalDateTime::now();
-    format!("{}", now.date().iso())
+    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)
 }
 
-fn write_statics() -> io::Result<()> {
-    use std::fs::File;
-    use std::io::Write;
-    use std::path::PathBuf;
+/// A comma-separated list of non-standard feature choices.
+fn nonstandard_features_string() -> String {
+    let mut s = Vec::new();
 
-    let ver = if is_development_version() {
-        format!("exa v{} ({} built on {})", cargo_version(), git_hash(), build_date())
+    if feature_enabled("GIT") {
+        s.push("+git");
     }
     else {
-        format!("exa v{}", cargo_version())
-    };
+        s.push("-git");
+    }
 
-    let out = PathBuf::from(env::var("OUT_DIR").unwrap());
-    let mut f = File::create(&out.join("version_string.txt"))?;
-    write!(f, "{:?}", ver)
+    s.join(", ")
+}
+
+/// Formats the current date as an ISO 8601 string.
+fn build_date() -> String {
+    let now = LocalDateTime::now();
+    format!("{}", now.date().iso())
 }

+ 1 - 5
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")))
     }
 }
 

+ 27 - 0
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' ]

+ 1 - 0
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