Files
benilla-octo/crates/benilla-world/src/build_id.rs
T
gromandClaude Opus 5 81d96af35d Everwood: the HD/OctoWoW line of benilla, imported onto upstream
This checkout had no git history at all, so this one commit carries the whole
of the Everwood work as a single import on top of chairmanpow/benilla-octo's
`main` (706cd71). The two trees have genuinely diverged — each has files the
other does not — so this is a fork point, not a catch-up.

Today's work, which is the reason a baseline exists at all:

- Booth previews no longer cast world shadows (`NO_BOOTH_SHADOW`). Portrait
  characters were entering the sun's shadow cascades, so every skinned-rig
  shadow specialization compiled live mid-frame; the hitch detector logged
  "main thread blocked 1316 ms" beside a `compiled LIVE` warning. This was
  the Fashion/Tmog stutter.
- Per-pane dress-up: each `DressUpModel` pane assembles and stages its own
  tried-on look instead of every pane mirroring the live player.
- Item template cache is append-only JSONL written on the IO pool, replacing
  an 11.6 MB whole-map JSON rewrite on the main thread every 10 s.
- `WOW_SYSTEM_TIMING` rebuilt per-thread: it took 2 mutexes per system enter
  and 4 per exit, costing 15 ms a frame (590 fps -> 60) and corrupting the
  measurements it was taken to produce.
- The visibility-churn sweep moved to its own `WOW_FLASH_CHURN` switch, so a
  frame-cost reading no longer pays 2.7 ms a frame for it.

Local state (`benilla-config/`, `logs/`, `target/`) is excluded by the
existing .gitignore; the account credential it holds is not in this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
2026-10-15 15:01:14 -06:00

131 lines
4.6 KiB
Rust

//! Which build is running: the release and the commit the binary was built from, stamped at
//! compile time by the launcher shims' build script (`benilla-buildstamp`) and passed to `run` as
//! the [`BuildId`] resource. It shows in the startup log line ([`banner`]), in crash reports and in
//! the debug panel's footer.
use bevy::prelude::*;
/// The launcher shim's compile-time stamp. The git fields are empty when the build had no
/// checkout or no `git` on `PATH`, which [`BuildId::summary`] reports as an unknown commit.
#[derive(Resource, Clone, Copy)]
pub struct BuildId {
/// The workspace version from `Cargo.toml`, which every release bumps.
pub version: &'static str,
/// `git describe --tags --long` against the nearest `v*` tag (`v0.2.0-12-gb17be27`); empty
/// when no release tag is in reach, as in a source archive or a shallow clone.
pub describe: &'static str,
/// The full sha, which the debug panel copies.
pub sha: &'static str,
/// Git's own abbreviation of [`sha`](Self::sha).
pub short: &'static str,
/// The commit date of [`sha`](Self::sha) (`YYYY-MM-DD`), not the build date.
pub date: &'static str,
/// The cargo profile directory: `debug`, `release` or `ship`.
pub profile: &'static str,
}
impl BuildId {
/// The release this build is: the version, and `+N` when the commit is N past that version's
/// tag. With no tag for this version in reach (none fetched, or the release commit before its
/// tag exists), the version alone.
pub fn release(&self) -> String {
match commits_past_tag(self.describe, self.version) {
Some(n) if n > 0 => format!("{}+{n}", self.version),
_ => self.version.to_owned(),
}
}
/// The one-line build id: release, short sha, commit date and profile.
pub fn summary(&self) -> String {
if self.short.is_empty() {
format!(
"{} · unknown commit (built without a git checkout) · {}",
self.release(),
self.profile
)
} else {
format!(
"{} · {} · {} · {}",
self.release(),
self.short,
self.date,
self.profile
)
}
}
}
/// How many commits past `v{version}` a `--long` describe (`<tag>-<n>-g<hash>`) is, or `None`
/// when the describe is empty, malformed or names another version's tag.
fn commits_past_tag(describe: &str, version: &str) -> Option<u32> {
let mut parts = describe.rsplitn(3, '-');
parts.next().filter(|hash| hash.starts_with('g'))?;
let n: u32 = parts.next()?.parse().ok()?;
let tag = parts.next()?;
(tag.strip_prefix('v')? == version).then_some(n)
}
/// Log the build id once at startup, not env-gated, so every pasted log carries it.
pub fn banner(build: Res<BuildId>) {
info!("benilla build {}", build.summary());
}
#[cfg(test)]
mod tests {
use super::*;
fn build(version: &'static str, describe: &'static str, short: &'static str) -> BuildId {
BuildId {
version,
describe,
sha: "",
short,
date: "2026-09-27",
profile: "release",
}
}
#[test]
fn a_tagged_release_reads_as_its_version() {
let b = build("0.2.0", "v0.2.0-0-gb17be27", "b17be27");
assert_eq!(b.summary(), "0.2.0 · b17be27 · 2026-09-27 · release");
}
#[test]
fn a_commit_past_the_release_counts_its_distance() {
assert_eq!(
build("0.2.0", "v0.2.0-12-gb17be27", "b17be27").release(),
"0.2.0+12"
);
// A pre-release tag's own hyphens stay in the tag.
assert_eq!(
build("1.0.0-rc1", "v1.0.0-rc1-3-gabc1234", "abc1234").release(),
"1.0.0-rc1+3"
);
}
#[test]
fn another_versions_tag_or_none_reads_as_the_version_alone() {
// The release commit itself, before its tag exists: the nearest tag is the previous one.
assert_eq!(
build("0.2.0", "v0.1.0-450-gb17be27", "b17be27").release(),
"0.2.0"
);
// No release tag in reach: a source archive or a shallow clone.
assert_eq!(build("0.2.0", "", "b17be27").release(), "0.2.0");
assert_eq!(
build("0.2.0", "not-a-describe", "b17be27").release(),
"0.2.0"
);
}
#[test]
fn a_build_without_git_still_names_its_release() {
let b = build("0.2.0", "", "");
assert_eq!(
b.summary(),
"0.2.0 · unknown commit (built without a git checkout) · release"
);
}
}