versioning: generate nightly versions from git describe (#3399)

we introduce NEOVIDE_BUILD_VERSION in build.rs from `git describe` so tagged builds keep the
package version and non-tagged builds report `nightly-<count>+g<sha>` with `-dirty`
preserved when applicable.

we kinda of follow the neovim pattern for nightly versions since the target users are used to it.

we also add cargo rerun tracking for git metadata and tracked files, and use the generated version
for the CLI `--version` output, startup version logging and `g:neovide_version`
consecutively.

note: bundles will not be affected since they have its own limited versioning scheme.
This commit is contained in:
Alexsander Falcucci 2026-03-12 17:44:31 +01:00 committed by GitHub
parent eaf32cf110
commit a4fad9d89e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 97 additions and 3 deletions

View file

@ -146,6 +146,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup toolchain
uses: dtolnay/rust-toolchain@master

View file

@ -104,6 +104,8 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup toolchain
uses: dtolnay/rust-toolchain@master

View file

@ -1,4 +1,10 @@
use std::process::Command;
fn main() {
set_rerun();
println!("cargo:rustc-env=NEOVIDE_BUILD_VERSION={}", build_version());
#[cfg(windows)]
{
let mut res = winres::WindowsResource::new();
@ -6,3 +12,87 @@ fn main() {
res.compile().expect("Could not attach exe icon");
}
}
fn set_rerun() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=Cargo.toml");
println!("cargo:rerun-if-changed=assets/neovide.ico");
for path in ["HEAD", "refs", "index", "packed-refs"] {
if let Some(path) = git_path(path) {
println!("cargo:rerun-if-changed={path}");
}
}
if let Some(files) = git_output(&["ls-files", "-z"]) {
for file in files.split('\0').filter(|file| !file.is_empty()) {
println!("cargo:rerun-if-changed={file}");
}
} else {
println!("cargo:warning=Could not list tracked files for version rerun tracking");
}
}
fn build_version() -> String {
let package_version = env!("CARGO_PKG_VERSION");
let git_describe = git_output(&[
"describe",
"--tags",
"--match",
"[0-9]*.[0-9]*.[0-9]*",
"--dirty",
"--always",
]);
git_describe
.as_deref()
.map(|describe| format(package_version, describe))
.unwrap_or_else(|| package_version.to_owned())
}
fn format(version: &str, describe: &str) -> String {
if describe == version {
return version.to_owned();
}
if describe == format!("{version}-dirty") {
return describe.to_owned();
}
let (describe, dirty) = match describe.strip_suffix("-dirty") {
Some(version) => (version, true),
None => (describe, false),
};
let mut parts = describe.splitn(3, '-');
let tag = parts.next();
let height = parts.next();
let commit = parts.next();
match (tag, height, commit) {
// formats non-exact matches as <tag>-<count>-g<abbrev>
// see: https://git-scm.com/docs/git-describe#_examples
(Some(tag), Some(height), Some(commit)) if tag == version && commit.starts_with('g') => {
let mut version = format!("nightly-{height}+{commit}");
if dirty {
version.push_str("-dirty");
}
version
}
_ => version.to_owned(),
}
}
fn git_path(path: &str) -> Option<String> {
git_output(&["rev-parse", "--git-path", path])
}
fn git_output(args: &[&str]) -> Option<String> {
Command::new("git")
.args(args)
.output()
.ok()
.filter(|output| output.status.success())
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|output| output.trim().to_owned())
}

View file

@ -76,7 +76,7 @@ pub async fn setup_neovide_specific_state(
INIT_LUA,
call_args![nvim_dict! {
"neovide_channel_id" => api_information.channel,
"neovide_version" => crate_version!(),
"neovide_version" => env!("NEOVIDE_BUILD_VERSION"),
"config_path" => config_path().to_string_lossy().into_owned(),
"register_clipboard" => register_clipboard,
"register_right_click" => register_right_click,

View file

@ -27,7 +27,7 @@ fn get_styles() -> Styles {
}
#[derive(Clone, Debug, Parser)]
#[command(version, about, long_about = None, styles = get_styles())]
#[command(version = env!("NEOVIDE_BUILD_VERSION"), about, long_about = None, styles = get_styles())]
pub struct CmdLineSettings {
/// Files to open (usually plainly appended to NeoVim args, except when --wsl is used)
#[arg(

View file

@ -250,7 +250,7 @@ fn setup(proxy: EventLoopProxy<EventPayload>, settings: Arc<Settings>) -> Result
#[cfg(not(test))]
init_logger(&settings);
trace!("Neovide version: {}", crate_version!());
trace!("Neovide version: {}", env!("NEOVIDE_BUILD_VERSION"));
Ok(config)
}