Show the exact build in About, Copy Info, REPORT and --version

Builds from main reported only the release version (2026.36) even when
HEAD was hundreds of commits past the tag. build.rs now also emits
OCS_TAG_DISTANCE, OCS_COMMIT_DATE, OCS_BUILD_METADATA and
OCS_FULL_VERSION: a clean checkout of the release tag stays "2026.36",
anything else becomes "2026.36+194.gef189d77", with ".dirty" appended
for uncommitted changes and only the hash when no tag can be counted
from (shallow clone, tarball). OCS_APP_VERSION is unchanged so the
update check, donation gate, User-Agents and window title keep working.

The About dialog gains Build / Commit date / Profile cards, Copy Info,
the REPORT issue template and recovery reports carry the full version,
and `-V`/`--version` print it instead of Cargo's 2026.36.0. Release
workflows check out full history so release binaries see the tag.

Also fixes the build being marked dirty when there is no repository:
diff-index exits 128 there, not 1.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
PanosandClaude Opus 5 committed 2026-09-12 16:19:40 +03:00
1 parent 58c9fcb748
commit 5f161bb037
31 files changed
+204 -18

No files matched your search

+3
View File
@@ -53,6 +53,9 @@ jobs:
- uses: actions/checkout@v4
with:
ref: ${{ steps.source.outputs.commit }}
# Full history so build.rs can measure the distance from the
# release tag; a shallow clone would label the build `+g<hash>`.
fetch-depth: 0
- name: Validate release version
env:
+12
View File
@@ -39,6 +39,9 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit || github.sha }}
# Full history so build.rs can measure the distance from the
# release tag; a shallow clone would label the build `+g<hash>`.
fetch-depth: 0
- name: Validate package versions
id: version
@@ -127,6 +130,9 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit || github.sha }}
# Full history so build.rs can measure the distance from the
# release tag; a shallow clone would label the build `+g<hash>`.
fetch-depth: 0
- name: Validate package versions
id: version
@@ -194,6 +200,9 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit || github.sha }}
# Full history so build.rs can measure the distance from the
# release tag; a shallow clone would label the build `+g<hash>`.
fetch-depth: 0
- name: Validate package versions
id: version
@@ -315,6 +324,9 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit || github.sha }}
# Full history so build.rs can measure the distance from the
# release tag; a shallow clone would label the build `+g<hash>`.
fetch-depth: 0
- name: Validate package versions
id: version
+69 -10
View File
@@ -14,32 +14,78 @@ fn main() {
version.clone()
};
println!("cargo:rustc-env=OCS_APP_VERSION={app_version}");
// Rerun on commit and branch switch only. Watching `.git/index` as well
// would keep the dirty flag fresh, but Cargo recompiles the crate every
// time this script reruns, and `git status` rewrites the index.
println!("cargo:rerun-if-changed=.git/HEAD");
if let Ok(head) = std::fs::read_to_string(".git/HEAD") {
if let Some(reference) = head.trim().strip_prefix("ref: ") {
println!("cargo:rerun-if-changed=.git/{reference}");
}
}
let revision = std::process::Command::new("git")
.args(["rev-parse", "--short=12", "HEAD"])
.output()
.ok()
.filter(|output| output.status.success())
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())
let revision = git_output(&["rev-parse", "--short=12", "HEAD"])
.unwrap_or_else(|| "unknown".to_string());
// diff-index exits 1 for differences and 128 when there is no repository,
// so only a real difference marks the build dirty.
let dirty = std::process::Command::new("git")
.args(["diff-index", "--quiet", "HEAD", "--"])
.status()
.ok()
.is_some_and(|status| !status.success());
.is_some_and(|status| status.code() == Some(1));
let commit = revision.clone();
let revision = if dirty {
format!("{revision}-dirty")
} else {
revision
};
println!("cargo:rustc-env=OCS_GIT_REV={revision}");
// Builds from the main branch report how far past the release tag they
// are. Release tags are `v` + the display version (scripts/release.py),
// so counting first-parent commits from that tag ties the distance to
// the version the app already claims. Shallow clones and source
// tarballs have no tag to count from and fall back to the hash alone.
let tag_distance = git_output(&[
"rev-list",
"--count",
"--first-parent",
&format!("v{app_version}..HEAD"),
])
.and_then(|value| value.parse::<u64>().ok());
println!(
"cargo:rustc-env=OCS_TAG_DISTANCE={}",
tag_distance.map_or_else(|| "unknown".to_string(), |n| n.to_string())
);
let commit_date = git_output(&["log", "-1", "--format=%cs", "HEAD"])
.unwrap_or_else(|| "unknown".to_string());
println!("cargo:rustc-env=OCS_COMMIT_DATE={commit_date}");
// Semver-style build metadata: empty for a clean build on the release
// tag, `+N.g<hash>` for N first-parent commits past it, `+g<hash>` when
// the distance is unknown, and `.dirty` appended for uncommitted changes.
let short_hash = (commit != "unknown").then(|| commit[..commit.len().min(8)].to_string());
let mut metadata_parts: Vec<String> = Vec::new();
match (tag_distance, &short_hash) {
(Some(0), _) => {}
(Some(n), Some(hash)) => {
metadata_parts.push(n.to_string());
metadata_parts.push(format!("g{hash}"));
}
(Some(n), None) => metadata_parts.push(n.to_string()),
(None, Some(hash)) => metadata_parts.push(format!("g{hash}")),
(None, None) => {}
}
if dirty {
metadata_parts.push("dirty".to_string());
}
let build_metadata = if metadata_parts.is_empty() {
String::new()
} else {
format!("+{}", metadata_parts.join("."))
};
println!("cargo:rustc-env=OCS_BUILD_METADATA={build_metadata}");
let full_version = format!("{app_version}{build_metadata}");
println!("cargo:rustc-env=OCS_FULL_VERSION={full_version}");
let profile = std::env::var("PROFILE").unwrap_or_else(|_| "unknown".to_string());
println!("cargo:rustc-env=OCS_BUILD_PROFILE={profile}");
if std::env::var("TARGET").ok().as_deref() == Some("x86_64-pc-windows-msvc")
@@ -73,7 +119,7 @@ fn main() {
if Path::new("packaging/windows/AppIcon.ico").exists() {
let mut res = winresource::WindowsResource::new();
res.set_icon("packaging/windows/AppIcon.ico");
res.set("ProductVersion", &app_version);
res.set("ProductVersion", &full_version);
res.set("FileVersion", &app_version);
if let Err(e) = res.compile() {
println!("cargo:warning=failed to embed Windows icon: {e}");
@@ -81,3 +127,16 @@ fn main() {
}
}
}
/// Runs `git` with `args` and returns trimmed stdout, or `None` when git is
/// missing, fails (no repository, unknown tag), or prints nothing.
fn git_output(args: &[&str]) -> Option<String> {
std::process::Command::new("git")
.args(args)
.output()
.ok()
.filter(|output| output.status.success())
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())
}
+9
View File
@@ -18,6 +18,15 @@ download for the installed platform.
The app shows `2026.35`, Cargo and macOS use `2026.35.0`, and MSI uses `26.35.0`.
The main window title is `Open CAD Studio 2026.35 - Drawing.dwg`.
Builds that are not a clean checkout of the release tag carry build metadata:
`2026.35+194.gef189d77` means 194 first-parent commits past `v2026.35` at
commit `ef189d77`, and `.dirty` is appended when the tree has uncommitted
changes. `build.rs` derives this from git at compile time (`OCS_FULL_VERSION`);
without a tag to count from (shallow clone, source tarball) only the hash is
shown. The full form appears in About, **Copy Info**, `REPORT`, `--version`
and recovery reports. The window title, update check and User-Agent keep the
plain `2026.35`.
To preview release notes, manually run **Weekly release** on `main` with
**publish** unchecked. Check **publish** to release immediately. Rerunning
within the same week reuses the original tag and commit. To rebuild just a
+3
View File
@@ -4621,6 +4621,8 @@ plugins =
.no-releases = لا توجد إصدارات
ui =
.build = البناء
.commit-date = تاريخ الإيداع
.count-steps-available = تتوفر __ocs_arg_count__ خطوات
.label-history = سجل __ocs_arg_label__
.n-vp = __ocs_arg_n__ منفذ عرض
@@ -4720,6 +4722,7 @@ ui =
.quick-select-menu-period-title-case = تحديد سريع...
.reading-file = يجري قراءة الملف…
.redo = إعادة
.release = إصدار
.repeat-last = تكرار __ocs_arg_last__
.replace-all = استبدال الكل
.replace-with = الاستبدال بـ:
+3
View File
@@ -4609,6 +4609,8 @@ plugins =
.no-releases = няма версии
ui =
.build = Компилация
.commit-date = Дата на комита
.count-steps-available = налични __ocs_arg_count__ стъпки
.label-history = история на __ocs_arg_label__
.n-vp = __ocs_arg_n__ VP
@@ -4708,6 +4710,7 @@ ui =
.quick-select-menu-period-title-case = Бърз избор...
.reading-file = Четене на файл…
.redo = Повтори
.release = Издание
.repeat-last = Повтори __ocs_arg_last__
.replace-all = Замени всички
.replace-with = Замени с:
+3
View File
@@ -4606,6 +4606,8 @@ plugins =
.no-releases = žádná vydání
ui =
.build = Sestavení
.commit-date = Datum commitu
.count-steps-available = K dispozici jsou kroky __ocs_arg_count__
.label-history = Historie __ocs_arg_label__
.n-vp = __ocs_arg_n__ VP
@@ -4705,6 +4707,7 @@ ui =
.quick-select-menu-period-title-case = Rychlý výběr...
.reading-file = Čtení souboru…
.redo = Znovu
.release = Vydání
.repeat-last = Opakujte __ocs_arg_last__
.replace-all = Nahradit vše
.replace-with = Nahradit za:
+3
View File
@@ -4607,6 +4607,8 @@ plugins =
.no-releases = Keine Freigaben
ui =
.build = Build
.commit-date = Commit-Datum
.count-steps-available = __ocs_arg_count__ Schritte verfügbar
.label-history = __ocs_arg_label__ Verlauf
.n-vp = __ocs_arg_n__ Ansichtsfenster
@@ -4706,6 +4708,7 @@ ui =
.quick-select-menu-period-title-case = Schnellauswahl…
.reading-file = Lesedatei...
.redo = Wiederholen
.release = Release
.repeat-last = Wiederholen __ocs_arg_last__
.replace-all = Ersetzen Sie alle
.replace-with = Ersetzen Sie durch:
+3
View File
@@ -4609,6 +4609,8 @@ plugins =
.no-releases = καμία έκδοση
ui =
.build = Build
.commit-date = Ημερομηνία commit
.count-steps-available = __ocs_arg_count__ διαθέσιμα βήματα
.label-history = Ιστορικό: __ocs_arg_label__
.n-vp = __ocs_arg_n__ ΘΠ
@@ -4708,6 +4710,7 @@ ui =
.quick-select-menu-period-title-case = Γρήγορη επιλογή...
.reading-file = Ανάγνωση αρχείου…
.redo = Επανάληψη
.release = Έκδοση
.repeat-last = Επανάληψη __ocs_arg_last__
.replace-all = Αντικατάσταση όλων
.replace-with = Αντικατάσταση με:
+3
View File
@@ -4610,6 +4610,8 @@ plugins =
.no-releases = no releases
ui =
.build = Build
.commit-date = Commit date
.count-steps-available = __ocs_arg_count__ steps available
.label-history = __ocs_arg_label__ history
.n-vp = __ocs_arg_n__ VP
@@ -4709,6 +4711,7 @@ ui =
.quick-select-menu-period-title-case = Quick Select...
.reading-file = Reading file…
.redo = Redo
.release = Release
.repeat-last = Repeat __ocs_arg_last__
.replace-all = Replace All
.replace-with = Replace with:
+3
View File
@@ -4609,6 +4609,8 @@ plugins =
.no-releases = sin versiones
ui =
.build = Compilación
.commit-date = Fecha del commit
.count-steps-available = __ocs_arg_count__ pasos disponibles
.label-history = Historial de __ocs_arg_label__
.n-vp = __ocs_arg_n__ VG
@@ -4708,6 +4710,7 @@ ui =
.quick-select-menu-period-title-case = Selección rápida...
.reading-file = Leyendo archivo…
.redo = Rehacer
.release = Versión oficial
.repeat-last = Repetir __ocs_arg_last__
.replace-all = Reemplazar todo
.replace-with = Reemplazar por:
+3
View File
@@ -4608,6 +4608,8 @@ plugins =
.no-releases = ei julkaisuja
ui =
.build = Koontiversio
.commit-date = Commitin päivämäärä
.count-steps-available = __ocs_arg_count__ portaat saatavilla
.label-history = __ocs_arg_label__ historia
.n-vp = __ocs_arg_n__ VP
@@ -4705,6 +4707,7 @@ ui =
.quick-select-menu-period-title-case = Pikavalinta...
.reading-file = Luetaan tiedostoa…
.redo = Toista
.release = Julkaisu
.repeat-last = Toista __ocs_arg_last__
.replace-all = Korvaa kaikki
.replace-with = Korvaa seuraavalla:
+3
View File
@@ -4609,6 +4609,8 @@ plugins =
.no-releases = pas de libération
ui =
.build = Build
.commit-date = Date du commit
.count-steps-available = __ocs_arg_count__ étapes disponibles
.label-history = __ocs_arg_label__ historique
.n-vp = __ocs_arg_n__ fenêtre(s)
@@ -4707,6 +4709,7 @@ ui =
.quick-select-menu-period-title-case = Sélection rapide...
.reading-file = Lecture du fichier...
.redo = Refaire
.release = Version officielle
.repeat-last = Répéter __ocs_arg_last__
.replace-all = Remplacer tout
.replace-with = Remplacer par :
+3
View File
@@ -4597,6 +4597,8 @@ plugins =
.no-releases = कोई विज्ञप्ति नहीं
ui =
.build = बिल्ड
.commit-date = कमिट तिथि
.count-steps-available = __ocs_arg_count__ उपलब्ध चरणों
.label-history = __ocs_arg_label__ इतिहास
.n-vp = __ocs_arg_n__ व्यूपोर्ट
@@ -4696,6 +4698,7 @@ ui =
.quick-select-menu-period-title-case = त्वरित चयन...
.reading-file = फ़ाइल पढ़ना...
.redo = रेडो
.release = रिलीज़
.repeat-last = दोहराएँ __ocs_arg_last__
.replace-all = सबको बदल दें
.replace-with = इसके साथ बदलें:
+3
View File
@@ -4608,6 +4608,8 @@ plugins =
.no-releases = nincs kiadás
ui =
.build = Build
.commit-date = Commit dátuma
.count-steps-available = __ocs_arg_count__ lépcsők állnak rendelkezésre
.label-history = __ocs_arg_label__ története
.n-vp = __ocs_arg_n__ VP
@@ -4707,6 +4709,7 @@ ui =
.quick-select-menu-period-title-case = Gyors kiválasztás...
.reading-file = Fájl olvasása…
.redo = Újra
.release = Kiadás
.repeat-last = Ismételje meg a __ocs_arg_last__
.replace-all = Cserélje ki az összeset
.replace-with = Csere erre:
+3
View File
@@ -4608,6 +4608,8 @@ plugins =
.no-releases = nessuna release
ui =
.build = Build
.commit-date = Data del commit
.count-steps-available = __ocs_arg_count__ gradini disponibili
.label-history = Storia di __ocs_arg_label__
.n-vp = __ocs_arg_n__ VP
@@ -4707,6 +4709,7 @@ ui =
.quick-select-menu-period-title-case = Selezione rapida...
.reading-file = Lettura del file…
.redo = Rifare
.release = Release
.repeat-last = Ripeti __ocs_arg_last__
.replace-all = Sostituisci tutto
.replace-with = Sostituisci con:
+3
View File
@@ -4597,6 +4597,8 @@ plugins =
.no-releases = リリースなし
ui =
.build = ビルド
.commit-date = コミット日
.count-steps-available = __ocs_arg_count__ ステップ利用可能
.label-history = __ocs_arg_label__ の履歴
.n-vp = __ocs_arg_n__ 個の VP
@@ -4696,6 +4698,7 @@ ui =
.quick-select-menu-period-title-case = クイック選択...
.reading-file = ファイルを読み込み中…
.redo = やり直し
.release = リリース
.repeat-last = __ocs_arg_last__ を繰り返し
.replace-all = すべて置換
.replace-with = 置換後:
+3
View File
@@ -4608,6 +4608,8 @@ plugins =
.no-releases = 릴리스 없음
ui =
.build = 빌드
.commit-date = 커밋 날짜
.count-steps-available = __ocs_arg_count__ 단계 사용 가능
.label-history = __ocs_arg_label__ 역사
.n-vp = __ocs_arg_n__ VP
@@ -4707,6 +4709,7 @@ ui =
.quick-select-menu-period-title-case = 빠른 선택...
.reading-file = 파일을 읽는 중…
.redo = 다시 실행
.release = 릴리스
.repeat-last = __ocs_arg_last__ 반복
.replace-all = 모두 바꾸기
.replace-with = 다음으로 교체:
+3
View File
@@ -4607,6 +4607,8 @@ plugins =
.no-releases = geen releases
ui =
.build = Build
.commit-date = Commitdatum
.count-steps-available = __ocs_arg_count__ stappen beschikbaar
.label-history = __ocs_arg_label__ geschiedenis
.n-vp = __ocs_arg_n__ weergavevenster
@@ -4706,6 +4708,7 @@ ui =
.quick-select-menu-period-title-case = Snel selecteren...
.reading-file = Bestand wordt gelezen...
.redo = Opnieuw
.release = Release
.repeat-last = __ocs_arg_last__ herhalen
.replace-all = Alles vervangen
.replace-with = Vervangen door:
+3
View File
@@ -4608,6 +4608,8 @@ plugins =
.no-releases = żadnych wydań
ui =
.build = Kompilacja
.commit-date = Data commita
.count-steps-available = Dostępne stopnie __ocs_arg_count__
.label-history = Historia __ocs_arg_label__
.n-vp = __ocs_arg_n__ VP
@@ -4707,6 +4709,7 @@ ui =
.quick-select-menu-period-title-case = Szybki wybór...
.reading-file = Czytanie pliku…
.redo = Powtórz
.release = Wydanie
.repeat-last = Powtórz __ocs_arg_last__
.replace-all = Zamień wszystko
.replace-with = Zamień na:
+3
View File
@@ -4609,6 +4609,8 @@ plugins =
.no-releases = sem versões
ui =
.build = Build
.commit-date = Data do commit
.count-steps-available = __ocs_arg_count__ etapas disponíveis
.label-history = Histórico de __ocs_arg_label__
.n-vp = __ocs_arg_n__ VG
@@ -4708,6 +4710,7 @@ ui =
.quick-select-menu-period-title-case = Seleção rápida...
.reading-file = Lendo arquivo…
.redo = Refazer
.release = Versão oficial
.repeat-last = Repetir __ocs_arg_last__
.replace-all = Substituir tudo
.replace-with = Substituir por:
+3
View File
@@ -4610,6 +4610,8 @@ plugins =
.no-releases = без релизов
ui =
.build = Сборка
.commit-date = Дата коммита
.count-steps-available = __ocs_arg_count__ доступные шаги
.label-history = __ocs_arg_label__ История
.n-vp = __ocs_arg_n__ вид. экранов
@@ -4709,6 +4711,7 @@ ui =
.quick-select-menu-period-title-case = Быстрый выбор...
.reading-file = Чтение файла...
.redo = Повторить
.release = Релиз
.repeat-last = Повторить __ocs_arg_last__
.replace-all = Заменить все
.replace-with = Заменить на:
+3
View File
@@ -4546,6 +4546,8 @@ plugins =
.no-releases = sürüm yok
ui =
.build = Derleme
.commit-date = Commit tarihi
.count-steps-available = __ocs_arg_count__ adım kullanılabilir
.label-history = __ocs_arg_label__ geçmişi
.n-vp = __ocs_arg_n__ görünüm alanı
@@ -4635,6 +4637,7 @@ ui =
.quick-select-menu-period-title-case = Hızlı Seçim...
.reading-file = Dosya okunuyor…
.redo = Yinele
.release = Sürüm
.repeat-last = __ocs_arg_last__ komutunu yinele
.replace-all = Tümünü Değiştir
.replace-with = Şununla değiştir:
+3
View File
@@ -4592,6 +4592,8 @@ plugins =
.no-releases = 无发布版本
ui =
.build = 构建
.commit-date = 提交日期
.count-steps-available = 可用 __ocs_arg_count__ 步
.label-history = __ocs_arg_label__ 历史
.n-vp = __ocs_arg_n__ 个视口
@@ -4691,6 +4693,7 @@ ui =
.quick-select-menu-period-title-case = 快速选择...
.reading-file = 正在读取文件…
.redo = 重做
.release = 正式版
.repeat-last = 重复 __ocs_arg_last__
.replace-all = 全部替换
.replace-with = 替换为:
+3
View File
@@ -4604,6 +4604,8 @@ plugins =
.no-releases = 無發行版本
ui =
.build = 組建
.commit-date = 提交日期
.count-steps-available = 可用 __ocs_arg_count__ 步
.label-history = __ocs_arg_label__ 歷史
.n-vp = __ocs_arg_n__ 個視口
@@ -4703,6 +4705,7 @@ ui =
.quick-select-menu-period-title-case = 快速選擇...
.reading-file = 正在讀取檔案…
.redo = 重做
.release = 正式版
.repeat-last = 重復 __ocs_arg_last__
.replace-all = 全部替換
.replace-with = 替換為:
+5 -2
View File
@@ -262,8 +262,11 @@ impl OpenCADStudio {
// reports arrive with the basics already filled in.
let body = format!(
"<!-- Describe the issue and the steps to reproduce it. -->\n\n\n\
---\n- Open CAD Studio: v{}\n- Platform: {}\n",
env!("OCS_APP_VERSION"),
---\n- Open CAD Studio: v{}\n- Revision: {} ({}, {})\n- Platform: {}\n",
env!("OCS_FULL_VERSION"),
env!("OCS_GIT_REV"),
env!("OCS_COMMIT_DATE"),
env!("OCS_BUILD_PROFILE"),
crate::sys::platform_info(),
);
let url = format!(
+7 -3
View File
@@ -6949,8 +6949,12 @@ impl OpenCADStudio {
Message::AboutCopyInfo => {
let info = format!(
"Open CAD Studio v{}\nOS: {}\nArch: {}",
env!("OCS_APP_VERSION"),
"Open CAD Studio v{}\nRevision: {}\nCommit date: {}\nProfile: {}\nFeatures: {}\nOS: {}\nArch: {}",
env!("OCS_FULL_VERSION"),
env!("OCS_GIT_REV"),
env!("OCS_COMMIT_DATE"),
env!("OCS_BUILD_PROFILE"),
env!("OCS_BUILD_FEATURES"),
crate::ui::window::about::platform_name(),
crate::ui::window::about::architecture_name(),
);
@@ -7168,7 +7172,7 @@ impl OpenCADStudio {
if let Some(error) = &self.plugin_registry_error {
return iced::clipboard::write(format!(
"Open CAD Studio v{}\nOS: {}\nArchitecture: {}\nRegistry: {}\nError: {}",
env!("OCS_APP_VERSION"),
env!("OCS_FULL_VERSION"),
std::env::consts::OS,
std::env::consts::ARCH,
crate::plugin::marketplace::REGISTRY_URL,
+8 -1
View File
@@ -20,7 +20,14 @@ use clap::Parser;
#[derive(Parser, Debug, Default)]
#[command(
name = "OpenCADStudio",
version,
version = env!("OCS_FULL_VERSION"),
long_version = concat!(
env!("OCS_FULL_VERSION"),
"\nrevision: ", env!("OCS_GIT_REV"),
"\ncommit date: ", env!("OCS_COMMIT_DATE"),
"\nprofile: ", env!("OCS_BUILD_PROFILE"),
"\nfeatures: ", env!("OCS_BUILD_FEATURES"),
),
about = crate::t!("Open CAD Studio — 2D/3D CAD editor").into_owned(),
long_about = None,
)]
+1
View File
@@ -255,6 +255,7 @@ impl RecoveryReport {
lines.push(format!("Report schema: {}", REPORT_SCHEMA_VERSION));
lines.push(format!("Report ID: {}", self.report_id));
lines.push(format!("Application version: {}", env!("OCS_APP_VERSION")));
lines.push(format!("Application build: {}", env!("OCS_FULL_VERSION")));
lines.push(format!("Application revision: {}", env!("OCS_GIT_REV")));
lines.push(format!("Build profile: {}", env!("OCS_BUILD_PROFILE")));
lines.push(format!("Build features: {}", env!("OCS_BUILD_FEATURES")));
+3
View File
@@ -481,6 +481,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Bring to Front" => Some(("ui", "bring-to-front")),
"Browse, install, and manage add-ons. Select one to view its README." => Some(("plugins", "browse-install-and-manage-add-ons-select-one-t")),
"Browser storage" => Some(("options", "browser-storage")),
"Build" => Some(("ui", "build")),
"Building scene caches…" => Some(("ui", "building-scene-caches")),
"Bump Map" => Some(("properties", "bump-map")),
"By annotation scale" => Some(("styles", "by-annotation-scale")),
@@ -645,6 +646,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Command Aliases" => Some(("command", "command-aliases")),
"Command cancelled because the active drawing space changed." => Some(("common", "command-cancelled-because-the-active-drawing-s")),
"Command history navigation" => Some(("common", "command-history-navigation")),
"Commit date" => Some(("ui", "commit-date")),
"Command:" => Some(("common", "command-label-title-case")),
"Commands: %{cmds}" => Some(("plugins", "commands-cmds")),
"Compact" => Some(("ui", "compact")),
@@ -2234,6 +2236,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Refraction Map" => Some(("properties", "refraction-map")),
"Region" => Some(("properties", "region")),
"Registered Class Entity" => Some(("properties", "registered-class-entity")),
"Release" => Some(("ui", "release")),
"Reload failed: {error}" => Some(("file", "reload-failed-error")),
"Reload from Disk" => Some(("modal", "reload-from-disk")),
"Remote Text" => Some(("properties", "remote-text")),
+24 -2
View File
@@ -73,10 +73,23 @@ pub(crate) fn architecture_name() -> &'static str {
}
}
/// Build card text: the metadata suffix without its leading `+`
/// (`194.gef189d77`, `gef189d77.dirty`), or "Release" for a clean build on
/// the release tag.
fn build_label() -> std::borrow::Cow<'static, str> {
match env!("OCS_BUILD_METADATA").strip_prefix('+') {
Some(suffix) => std::borrow::Cow::Borrowed(suffix),
None => t!("Release"),
}
}
pub fn view_window(
sizing: crate::ui::modal::ModalSizing,
) -> Element<'static, Message> {
let version = format!("v{}", env!("OCS_APP_VERSION"));
// The hero carries the full build identity (`2026.36+194.gef189d77`);
// the cards split it into the release version and the build details.
let version = format!("v{}", env!("OCS_FULL_VERSION"));
let build = build_label();
let content_width = if matches!(sizing.width, Length::Fill) {
Fill
} else {
@@ -113,13 +126,21 @@ pub fn view_window(
.style(surface_style);
let metadata = row![
info_card(t!("Version"), version, card_width),
info_card(t!("Version"), env!("OCS_APP_VERSION"), card_width),
info_card(t!("Platform"), platform_name(), card_width),
info_card(t!("Arch"), architecture_name(), card_width),
]
.spacing(8)
.width(content_width);
let build_info = row![
info_card(t!("Build"), build, card_width),
info_card(t!("Commit date"), env!("OCS_COMMIT_DATE"), card_width),
info_card(t!("Profile"), env!("OCS_BUILD_PROFILE"), card_width),
]
.spacing(8)
.width(content_width);
let copy = button(text(t!("Copy Info")).size(11))
.on_press(Message::AboutCopyInfo)
.style(button::primary)
@@ -129,6 +150,7 @@ pub fn view_window(
column![
hero,
metadata,
build_info,
row![Space::new().width(content_width), copy]
.width(sizing.width)
.align_y(iced::Center),