diff --git a/atsf_server/service/update.go b/atsf_server/service/update.go index b373e1df..cff3c56f 100644 --- a/atsf_server/service/update.go +++ b/atsf_server/service/update.go @@ -580,10 +580,12 @@ func isVersionNewer(current string, latest string) bool { } type versionInfo struct { - Valid bool - IsDev bool - Numbers []int - Prerelease []string + Valid bool + IsDev bool + Numbers []int + Prerelease []string + GitDescribeDistance int + GitDescribeTail []string } func parseVersionInfo(version string) versionInfo { @@ -626,11 +628,32 @@ func parseVersionInfo(version string) versionInfo { } info := versionInfo{Valid: len(parts) > 0, Numbers: parts} if prerelease != "" { - info.Prerelease = splitPrereleaseIdentifiers(prerelease) + identifiers := splitPrereleaseIdentifiers(prerelease) + if distance, tail, ok := parseGitDescribeIdentifiers(identifiers); ok { + info.GitDescribeDistance = distance + info.GitDescribeTail = tail + } else { + info.Prerelease = identifiers + } } return info } +func parseGitDescribeIdentifiers(identifiers []string) (int, []string, bool) { + if len(identifiers) < 2 { + return 0, nil, false + } + distance, err := strconv.Atoi(strings.TrimSpace(identifiers[0])) + if err != nil || distance <= 0 { + return 0, nil, false + } + commitToken := strings.TrimSpace(identifiers[1]) + if commitToken == "" || !strings.HasPrefix(strings.ToLower(commitToken), "g") { + return 0, nil, false + } + return distance, identifiers[1:], true +} + func splitPrereleaseIdentifiers(value string) []string { parts := strings.FieldsFunc(strings.TrimSpace(value), func(r rune) bool { return r == '.' || r == '-' @@ -667,6 +690,34 @@ func compareVersionInfo(left versionInfo, right versionInfo) int { } } + if left.GitDescribeDistance != right.GitDescribeDistance { + if left.GitDescribeDistance < right.GitDescribeDistance { + return -1 + } + return 1 + } + if left.GitDescribeDistance > 0 || right.GitDescribeDistance > 0 { + maxLen = len(left.GitDescribeTail) + if len(right.GitDescribeTail) > maxLen { + maxLen = len(right.GitDescribeTail) + } + for index := 0; index < maxLen; index++ { + if index >= len(left.GitDescribeTail) { + return -1 + } + if index >= len(right.GitDescribeTail) { + return 1 + } + if left.GitDescribeTail[index] < right.GitDescribeTail[index] { + return -1 + } + if left.GitDescribeTail[index] > right.GitDescribeTail[index] { + return 1 + } + } + return 0 + } + if len(left.Prerelease) == 0 && len(right.Prerelease) == 0 { return 0 } diff --git a/atsf_server/service/update_test.go b/atsf_server/service/update_test.go index 90425a43..618826c6 100644 --- a/atsf_server/service/update_test.go +++ b/atsf_server/service/update_test.go @@ -53,6 +53,8 @@ func TestIsVersionNewer(t *testing.T) { {name: "stable newer than prerelease", current: "v1.2.3-rc.1", latest: "v1.2.3", expected: true}, {name: "prerelease not newer than same stable", current: "v1.2.3", latest: "v1.2.3-rc.1", expected: false}, {name: "newer prerelease sequence", current: "v1.2.3-rc.1", latest: "v1.2.3-rc.2", expected: true}, + {name: "git describe newer than same tag", current: "v0.6.3", latest: "v0.6.3-2-gf4d36be", expected: true}, + {name: "git describe distance compares numerically", current: "v0.6.3-2-gf4d36be", latest: "v0.6.3-5-gabc1234", expected: true}, {name: "dev build", current: "dev", latest: "v0.4.0", expected: true}, } @@ -225,6 +227,13 @@ func TestUploadManualServerBinary(t *testing.T) { } } +func TestBuildUploadedServerBinaryViewAcceptsGitDescribeNewerThanTag(t *testing.T) { + info := buildUploadedServerBinaryView("atsflare-server-test", "v0.6.3", "v0.6.3-2-gf4d36be", time.Now()) + if !info.HasUpdate || !info.ReadyToUpgrade { + t.Fatalf("expected git describe binary to be upgradeable: %+v", info) + } +} + func TestUploadManualServerBinaryRejectsSameVersion(t *testing.T) { originalVersion := common.Version common.Version = "v0.5.0"