fix(app): Stop panicking at startup when parsing the app version - release blocker (#6888)
* Fix a startup panic in app_version() * Fix a potential RPC panic in get_info() * Fix typo
This commit is contained in:
parent
286ebdbf8c
commit
a18f47d5f6
|
@ -374,10 +374,10 @@ where
|
||||||
// remove everything after the `+` character if any
|
// remove everything after the `+` character if any
|
||||||
.split('+')
|
.split('+')
|
||||||
.next()
|
.next()
|
||||||
.expect("always at least 1 slice")
|
.expect("always at least 1 slice");
|
||||||
// remove the previously added `v` character at the start since it's not a part of the user agent.
|
// Remove the previously added `v` character at the start since it's not a part of the user agent.
|
||||||
.strip_prefix('v')
|
let release_version = release_version.strip_prefix('v').unwrap_or(release_version);
|
||||||
.expect("we are always expecting the `v` prefix");
|
|
||||||
let user_agent = format!("/Zebra:{release_version}/");
|
let user_agent = format!("/Zebra:{release_version}/");
|
||||||
|
|
||||||
let response = GetInfo {
|
let response = GetInfo {
|
||||||
|
|
|
@ -36,45 +36,98 @@ pub static APPLICATION: AppCell<ZebradApp> = AppCell::new();
|
||||||
///
|
///
|
||||||
/// For details, see <https://semver.org/>
|
/// For details, see <https://semver.org/>
|
||||||
pub fn app_version() -> Version {
|
pub fn app_version() -> Version {
|
||||||
|
// CARGO_PKG_VERSION is always a valid SemVer 2.0 version.
|
||||||
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
let vergen_git_describe: Option<&str> = option_env!("VERGEN_GIT_DESCRIBE");
|
|
||||||
|
|
||||||
match vergen_git_describe {
|
// VERGEN_GIT_DESCRIBE should be in the format:
|
||||||
// change the git describe format to the semver 2.0 format
|
// - v1.0.0-rc.9-6-g319b01bb84
|
||||||
Some(mut vergen_git_describe) if !vergen_git_describe.is_empty() => {
|
// - v1.0.0-6-g319b01bb84
|
||||||
// strip the leading "v", if present
|
// but sometimes it is just a short commit hash. See #6879 for details.
|
||||||
if &vergen_git_describe[0..1] == "v" {
|
//
|
||||||
vergen_git_describe = &vergen_git_describe[1..];
|
// Currently it is the output of `git describe --tags --dirty --match='v*.*.*'`,
|
||||||
}
|
// or whatever is specified in zebrad/build.rs.
|
||||||
|
const VERGEN_GIT_DESCRIBE: Option<&str> = option_env!("VERGEN_GIT_DESCRIBE");
|
||||||
|
|
||||||
// split into tag, commit count, hash
|
// We're using the same library as cargo uses internally, so this is guaranteed.
|
||||||
let rparts: Vec<_> = vergen_git_describe.rsplitn(3, '-').collect();
|
let fallback_version = CARGO_PKG_VERSION.parse().unwrap_or_else(|error| {
|
||||||
|
panic!(
|
||||||
|
"unexpected invalid CARGO_PKG_VERSION: {error:?} in {CARGO_PKG_VERSION:?}, \
|
||||||
|
should have been checked by cargo"
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
match rparts.as_slice() {
|
// The SemVer 2.0 format is:
|
||||||
// assume it's a cargo package version or a git tag with no hash
|
// - 1.0.0-rc.9+6.g319b01bb84
|
||||||
[_] | [_, _] => vergen_git_describe.parse().unwrap_or_else(|_| {
|
// - 1.0.0+6.g319b01bb84
|
||||||
panic!(
|
//
|
||||||
"VERGEN_GIT_DESCRIBE without a hash {vergen_git_describe:?} must be valid semver 2.0"
|
// Or as a pattern:
|
||||||
)
|
// - version: major`.`minor`.`patch
|
||||||
}),
|
// - optional pre-release: `-`tag[`.`tag ...]
|
||||||
|
// - optional build: `+`tag[`.`tag ...]
|
||||||
|
// change the git describe format to the semver 2.0 format
|
||||||
|
let Some(vergen_git_describe) = VERGEN_GIT_DESCRIBE else {
|
||||||
|
return fallback_version;
|
||||||
|
};
|
||||||
|
|
||||||
// it's the "git describe" format, which doesn't quite match SemVer 2.0
|
// Split using "git describe" separators.
|
||||||
[hash, commit_count, tag] => {
|
let mut vergen_git_describe = vergen_git_describe.split('-').peekable();
|
||||||
let semver_fix = format!("{tag}+{commit_count}.{hash}");
|
|
||||||
semver_fix.parse().unwrap_or_else(|_|
|
|
||||||
panic!("Modified VERGEN_GIT_DESCRIBE {vergen_git_describe:?} -> {rparts:?} -> {semver_fix:?} must be valid. Note: CARGO_PKG_VERSION was {CARGO_PKG_VERSION:?}."))
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => unreachable!("split is limited to 3 parts"),
|
// Check the "version core" part.
|
||||||
}
|
let version = vergen_git_describe.next();
|
||||||
}
|
let Some(mut version) = version else {
|
||||||
_ => CARGO_PKG_VERSION.parse().unwrap_or_else(|_| {
|
return fallback_version;
|
||||||
panic!("CARGO_PKG_VERSION {CARGO_PKG_VERSION:?} must be valid semver 2.0")
|
};
|
||||||
}),
|
|
||||||
|
// strip the leading "v", if present.
|
||||||
|
version = version.strip_prefix('v').unwrap_or(version);
|
||||||
|
|
||||||
|
// If the initial version is empty, just a commit hash, or otherwise invalid.
|
||||||
|
if Version::parse(version).is_err() {
|
||||||
|
return fallback_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut semver = version.to_string();
|
||||||
|
|
||||||
|
// Check if the next part is a pre-release or build part,
|
||||||
|
// but only consume it if it is a pre-release tag.
|
||||||
|
let Some(part) = vergen_git_describe.peek() else {
|
||||||
|
// No pre-release or build.
|
||||||
|
return semver.parse().expect("just checked semver is valid");
|
||||||
|
};
|
||||||
|
|
||||||
|
if part.starts_with(char::is_alphabetic) {
|
||||||
|
// It's a pre-release tag.
|
||||||
|
semver.push('-');
|
||||||
|
semver.push_str(part);
|
||||||
|
|
||||||
|
// Consume the pre-release tag to move on to the build tags, if any.
|
||||||
|
let _ = vergen_git_describe.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the next part is a build part.
|
||||||
|
let Some(build) = vergen_git_describe.peek() else {
|
||||||
|
// No build tags.
|
||||||
|
return semver.parse().unwrap_or(fallback_version);
|
||||||
|
};
|
||||||
|
|
||||||
|
if !build.starts_with(char::is_numeric) {
|
||||||
|
// It's not a valid "commit count" build tag from "git describe".
|
||||||
|
return fallback_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the rest of the build parts with the correct `+` and `.` separators.
|
||||||
|
let build_parts: Vec<_> = vergen_git_describe.collect();
|
||||||
|
let build_parts = build_parts.join(".");
|
||||||
|
|
||||||
|
semver.push('+');
|
||||||
|
semver.push_str(&build_parts);
|
||||||
|
|
||||||
|
semver.parse().unwrap_or(fallback_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The Zebra current release version.
|
/// The Zebra current release version.
|
||||||
|
//
|
||||||
|
// TODO: deduplicate this code with release_version in zebra_rpc::get_info()
|
||||||
pub fn release_version() -> String {
|
pub fn release_version() -> String {
|
||||||
app_version()
|
app_version()
|
||||||
.to_string()
|
.to_string()
|
||||||
|
@ -89,6 +142,8 @@ pub fn release_version() -> String {
|
||||||
/// This must be a valid [BIP 14] user agent.
|
/// This must be a valid [BIP 14] user agent.
|
||||||
///
|
///
|
||||||
/// [BIP 14]: https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki
|
/// [BIP 14]: https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki
|
||||||
|
//
|
||||||
|
// TODO: deduplicate this code with the user agent in zebra_rpc::get_info()
|
||||||
pub fn user_agent() -> String {
|
pub fn user_agent() -> String {
|
||||||
let release_version = release_version();
|
let release_version = release_version();
|
||||||
format!("/Zebra:{release_version}/")
|
format!("/Zebra:{release_version}/")
|
||||||
|
|
Loading…
Reference in New Issue