From ed0b23d009cff67fcc53288bd60241692c1bafa1 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Fri, 7 Apr 2023 06:07:12 -0700 Subject: [PATCH] cli: include commit id from build in version This changes the version number reported by `jj version` from "0.7.0" to something like "0.7.0-24a512683bc921699575b6a953624b05c068d544a". The hash is added if running in a jj repo or a git repo. --- Cargo.lock | 42 ++++++++++++++++++++++++++ Cargo.toml | 3 ++ build.rs | 63 +++++++++++++++++++++++++++++++++++++++ src/cli_util.rs | 6 +--- src/commands/mod.rs | 4 ++- tests/test_global_opts.rs | 9 ++++-- 6 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 build.rs diff --git a/Cargo.lock b/Cargo.lock index c55fb96ec..dca03daf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -162,6 +162,38 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "camino" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cast" version = "0.3.0" @@ -791,6 +823,7 @@ version = "0.7.0" dependencies = [ "assert_cmd", "assert_matches", + "cargo_metadata", "chrono", "clap 4.1.11", "clap_complete", @@ -1568,6 +1601,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +dependencies = [ + "serde", +] + [[package]] name = "serde" version = "1.0.159" diff --git a/Cargo.toml b/Cargo.toml index b17beab9b..631fbe014 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,9 @@ path = "testing/fake-diff-editor.rs" [workspace] members = ["lib", "lib/testutils", "lib/gen-protos"] +[build-dependencies] +cargo_metadata = "0.15.4" + [dependencies] chrono = { version = "0.4.24", default-features = false, features = ["std", "clock"] } clap = { version = "4.1.11", features = ["derive", "deprecated"] } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..fd3faf526 --- /dev/null +++ b/build.rs @@ -0,0 +1,63 @@ +// Copyright 2023 The Jujutsu Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::process::Command; + +use cargo_metadata::MetadataCommand; + +fn main() -> std::io::Result<()> { + let path = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let meta = MetadataCommand::new() + .manifest_path("./Cargo.toml") + .current_dir(&path) + .exec() + .unwrap(); + let root = meta.root_package().unwrap(); + let version = &root.version; + + if let Some(git_hash) = get_git_hash() { + println!("cargo:rustc-env=JJ_VERSION={}-{}", version, git_hash); + } else { + println!("cargo:rustc-env=JJ_VERSION={}", version); + } + + Ok(()) +} + +fn get_git_hash() -> Option { + if let Ok(output) = Command::new("jj") + .args([ + "--ignore-working-copy", + "log", + "--no-graph", + "-r=@-", + "-T=commit_id", + ]) + .output() + { + if output.status.success() { + println!("cargo:rerun-if-changed=.jj/repo/op_heads/heads/"); + return Some(String::from_utf8(output.stdout).unwrap()); + } + } + + if let Ok(output) = Command::new("git").args(["rev-parse", "HEAD"]).output() { + if output.status.success() { + println!("cargo:rerun-if-changed=.git/HEAD"); + return Some(String::from_utf8(output.stdout).unwrap()); + } + } + + None +} diff --git a/src/cli_util.rs b/src/cli_util.rs index 82f537c99..349f1a108 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -1860,11 +1860,7 @@ pub fn short_operation_hash(operation_id: &OperationId) -> String { /// /// To get started, see the tutorial at https://github.com/martinvonz/jj/blob/main/docs/tutorial.md. #[derive(clap::Parser, Clone, Debug)] -#[command( - name = "jj", - author = "Martin von Zweigbergk ", - version -)] +#[command(name = "jj", author = "Martin von Zweigbergk ")] pub struct Args { #[command(flatten)] pub global_args: GlobalArgs, diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 079939ea6..c76aa2ad2 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -3445,7 +3445,9 @@ fn cmd_sparse(ui: &mut Ui, command: &CommandHelper, args: &SparseArgs) -> Result pub fn default_app() -> Command { let app: Command = Commands::augment_subcommands(Args::command()); - app.arg_required_else_help(true).subcommand_required(true) + app.arg_required_else_help(true) + .subcommand_required(true) + .version(env!("JJ_VERSION")) } pub fn run_command( diff --git a/tests/test_global_opts.rs b/tests/test_global_opts.rs index a67030204..16e508a64 100644 --- a/tests/test_global_opts.rs +++ b/tests/test_global_opts.rs @@ -55,9 +55,12 @@ fn test_no_subcommand() { insta::assert_snapshot!(stderr.lines().next().unwrap(), @"error: 'jj' requires a subcommand but one was not provided"); let stdout = test_env.jj_cmd_success(test_env.env_root(), &["--version"]); - insta::assert_snapshot!(stdout.replace(|c: char| c.is_ascii_digit(), "?"), @r###" - jj ?.?.? - "###); + let sanitized = stdout.replace(|c: char| c.is_ascii_hexdigit(), "?"); + assert!( + sanitized == "jj ?.?.?\n" + || sanitized == "jj ?.?.?-????????????????????????????????????????\n", + "{sanitized}" + ); let stdout = test_env.jj_cmd_success(test_env.env_root(), &["--help"]); insta::assert_snapshot!(stdout.lines().next().unwrap(), @"Jujutsu (An experimental VCS)");