Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli version: Show date as part of the version next to the commit id, shorten commit id #2034

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ name = "runner"

[build-dependencies]
cargo_metadata = { workspace = true }
chrono = { workspace = true }

[dependencies]
chrono = { workspace = true }
Expand Down
59 changes: 47 additions & 12 deletions cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate chrono;

use std::path::Path;
use std::process::Command;
use std::str;

use cargo_metadata::MetadataCommand;
use chrono::prelude::*;

const GIT_HEAD_PATH: &str = "../.git/HEAD";
const JJ_OP_HEADS_PATH: &str = "../.jj/repo/op_heads/heads";
Expand All @@ -41,21 +44,51 @@ fn main() -> std::io::Result<()> {
}
println!("cargo:rerun-if-env-changed=NIX_JJ_GIT_HASH");

if let Some(git_hash) = get_git_hash() {
println!("cargo:rustc-env=JJ_VERSION={}-{}", version, git_hash);
if let Some((mut git_hash, maybe_date)) = get_git_timestamp_and_hash() {
git_hash.truncate(16);
println!(
"cargo:rustc-env=JJ_VERSION={}+{}-{}",
version,
Comment on lines +50 to +51
Copy link
Collaborator

@jyn514 jyn514 Feb 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated to this PR, but it would be simpler to use CARGO_PKG_VERSION instead of parsing the version from cargo metadata https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts (see CARGO_PKG_<var>)

maybe_date
.map(|d| d.format("%Y%m%d").to_string())
.unwrap_or_else(|| "dateunknown".to_string()),
git_hash
);
} else {
println!("cargo:rustc-env=JJ_VERSION={}", version);
}

Ok(())
}

fn get_git_hash() -> Option<String> {
if let Some(nix_hash) = std::env::var("NIX_JJ_GIT_HASH")
/// Convert a string with a unix timestamp to a date
fn timestamp_to_date(ts_str: &str) -> Option<DateTime<Utc>> {
ts_str
.parse::<i64>()
.ok()
.filter(|s| !s.is_empty())
{
return Some(nix_hash);
.and_then(|ts| DateTime::<Utc>::from_timestamp(ts, 0))
}

/// Return the UTC committer date (maybe) and the git hash
fn get_git_timestamp_and_hash() -> Option<(String, Option<DateTime<Utc>>)> {
if let (Ok(nix_hash), maybe_nix_timestamp) = (
std::env::var("NIX_JJ_GIT_HASH"),
std::env::var("NIX_JJ_GIT_TIMESTAMP"),
Comment on lines +74 to +76
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have it for NIX_JJ_GIT_HASH above, but not for NIX_JJ_GIT_TIMESTAMP. might make sense to move the println into this function, or add a wrapper which prints rerun every time you try to access the variable.

) {
if !nix_hash.is_empty() {
return Some((
nix_hash,
maybe_nix_timestamp
.ok()
.and_then(|ts_str| timestamp_to_date(&ts_str)),
));
}
}

fn parse_timestamp_vbar_hash(bytes: &[u8]) -> (String, Option<DateTime<Utc>>) {
let s = str::from_utf8(bytes).unwrap().trim_end();
let (ts_str, id) = s.split_once('|').unwrap();
(id.to_owned(), timestamp_to_date(ts_str))
}
if let Ok(output) = Command::new("jj")
.args([
Expand All @@ -64,19 +97,21 @@ fn get_git_hash() -> Option<String> {
"log",
"--no-graph",
"-r=@-",
"-T=commit_id",
r#"-T=committer.timestamp().utc().format("%s") ++ "|" ++ commit_id"#,
])
.output()
{
if output.status.success() {
return Some(String::from_utf8(output.stdout).unwrap());
return Some(parse_timestamp_vbar_hash(&output.stdout));
}
}

if let Ok(output) = Command::new("git").args(["rev-parse", "HEAD"]).output() {
if let Ok(output) = Command::new("git")
.args(["log", "-1", "--format=%ct|%H", "HEAD"])
.output()
{
if output.status.success() {
let line = str::from_utf8(&output.stdout).unwrap();
return Some(line.trim_end().to_owned());
return Some(parse_timestamp_vbar_hash(&output.stdout));
}
}

Expand Down
4 changes: 3 additions & 1 deletion cli/tests/test_global_opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ fn test_version() {
let sanitized = stdout.replace(|c: char| c.is_ascii_hexdigit(), "?");
let expected = [
"jj ?.??.?\n",
"jj ?.??.?-????????????????????????????????????????\n",
"jj ?.??.?+????????-????????????????\n",
// `dateunknown` turns into `??t?unknown` since d,a,e are hex digits.
"jj ?.??.?+??t?unknown-????????????????\n",
];
assert!(
expected.contains(&sanitized.as_str()),
Expand Down
12 changes: 10 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
} //
(flake-utils.lib.eachDefaultSystem (system:
let
# TODO(aseipp): Use dirtyRev and dirtyShortRev to record dirty checkout
# when we update `build.rs` to understand dirty checkouts.
gitRev = self.rev or "";
gitTimestamp = toString self.lastModified;

pkgs = import nixpkgs {
inherit system;
overlays = [
Expand Down Expand Up @@ -100,7 +105,8 @@
ZSTD_SYS_USE_PKG_CONFIG = "1";
LIBSSH2_SYS_USE_PKG_CONFIG = "1";
RUSTFLAGS = pkgs.lib.optionalString useMoldLinker "-C link-arg=-fuse-ld=mold";
NIX_JJ_GIT_HASH = self.rev or "";
NIX_JJ_GIT_HASH = gitRev;
NIX_JJ_GIT_TIMESTAMP = gitTimestamp;
CARGO_INCREMENTAL = "0";

preCheck = ''
Expand Down Expand Up @@ -175,8 +181,10 @@
export RUST_BACKTRACE=1
export ZSTD_SYS_USE_PKG_CONFIG=1
export LIBSSH2_SYS_USE_PKG_CONFIG=1

export RUSTFLAGS="-Zthreads=0"

export NIX_JJ_GIT_HASH="${gitRev}"
export NIX_JJ_GIT_TIMESTAMP="${gitTimestamp}";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will ensure NIX_JJ_GIT_TIMESTAMP (and NIX_JJ_GIT_HASH) only actually gets configured when the environment is populated, which typically happens only when you run nix develop for the first time. I think this is probably OK, to be honest, since it's only a minor glitch when nix-oriented developers are hacking. It just means the --version will be wrong, but that's probably OK in the working copy.

To fix this we'd need to have a third case where we set something like NIX_JJ_SHELL=1 and then have build.rs handle that case like the normal one where we just interrogate the .git dir.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, these variables would only populate in the case when jj is compelled outside a git repo by nix.

It's beyond the scope of my comfort level with nix, though. Somebody else would have to test these things and make another PR, I think.

'' + pkgs.lib.optionalString useMoldLinker ''
export RUSTFLAGS+=" -C link-arg=-fuse-ld=mold -C link-arg=-Wl,--compress-debug-sections=zstd"
'' + darwinNextestHack;
Expand Down