fix(updater): pick the more complete release when two sources tie
The updater resolves the release from two hosts, Forgejo and GitHub. Forgejo is queried first, so on equal versions it was always the release that got shown, and a mirror that was missing an installer hid it from the user. The selection is now a function of its own: a newer version always wins, and on equal versions the release with more assets wins. Five tests cover the ordering, the tie on assets and the empty case.
This commit is contained in:
parent
40b05df364
commit
34d49274d3
1 changed files with 68 additions and 4 deletions
|
|
@ -55,6 +55,28 @@ pub fn is_newer(latest: &str, current: &str) -> bool {
|
|||
l_nums.len() > c_nums.len()
|
||||
}
|
||||
|
||||
/// Choose the release to offer between the one found so far and a candidate.
|
||||
///
|
||||
/// A newer version always wins. On equal versions the release carrying
|
||||
/// more assets wins, so a mirror that is missing an installer does not hide
|
||||
/// it from the user.
|
||||
fn pick_newer_release(current: Option<ReleaseInfo>, candidate: ReleaseInfo) -> ReleaseInfo {
|
||||
match current {
|
||||
None => candidate,
|
||||
Some(current) => {
|
||||
if is_newer(&candidate.version, ¤t.version) {
|
||||
candidate
|
||||
} else if candidate.version == current.version
|
||||
&& candidate.assets.len() > current.assets.len()
|
||||
{
|
||||
candidate
|
||||
} else {
|
||||
current
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_for_updates() -> Option<ReleaseInfo> {
|
||||
let urls = [
|
||||
format!("{}/api/v1/repos/{}/releases/latest", FORGEJO_HOST, REPO_OWNER_NAME),
|
||||
|
|
@ -97,10 +119,7 @@ pub fn check_for_updates() -> Option<ReleaseInfo> {
|
|||
assets: release.assets,
|
||||
};
|
||||
|
||||
best = Some(match best {
|
||||
Some(current) if !is_newer(&info.version, ¤t.version) => current,
|
||||
_ => info,
|
||||
});
|
||||
best = Some(pick_newer_release(best, info));
|
||||
}
|
||||
}
|
||||
best
|
||||
|
|
@ -469,4 +488,49 @@ mod tests {
|
|||
assert!(is_newer("0.2.1", "0.2.0"));
|
||||
assert!(!is_newer("0.0.9", "0.1.0"));
|
||||
}
|
||||
|
||||
fn release(version: &str, assets: usize) -> ReleaseInfo {
|
||||
ReleaseInfo {
|
||||
tag_name: format!("v{version}"),
|
||||
version: version.to_string(),
|
||||
assets: (0..assets).map(|i| ReleaseAsset {
|
||||
name: format!("asset-{i}"),
|
||||
browser_download_url: String::new(),
|
||||
size: None,
|
||||
}).collect(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_newer_release_wins_over_older() {
|
||||
let picked = pick_newer_release(Some(release("0.2.18", 2)), release("0.2.21", 1));
|
||||
assert_eq!(picked.version, "0.2.21");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_older_release_does_not_win() {
|
||||
let picked = pick_newer_release(Some(release("0.2.21", 7)), release("0.2.18", 2));
|
||||
assert_eq!(picked.version, "0.2.21");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_equal_version_prefers_more_assets() {
|
||||
// A mirror that is missing assets must not hide them from the user.
|
||||
let picked = pick_newer_release(Some(release("0.2.21", 4)), release("0.2.21", 7));
|
||||
assert_eq!(picked.assets.len(), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_equal_version_keeps_first_when_assets_match() {
|
||||
let picked = pick_newer_release(Some(release("0.2.21", 7)), release("0.2.21", 7));
|
||||
assert_eq!(picked.tag_name, "v0.2.21");
|
||||
assert_eq!(picked.assets.len(), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_first_release_is_kept_when_nothing_to_compare() {
|
||||
let picked = pick_newer_release(None, release("0.2.21", 7));
|
||||
assert_eq!(picked.version, "0.2.21");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue