diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index 39981f0590..82febe9615 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -183,7 +183,7 @@ func resolveExtensionMetadata(ctx context.Context, repo *repo_model.Repository, Element: strings.ToLower(repo.Name), DisplayName: fmt.Sprintf("%s - %s", repo.Owner.Name, repo.Name), ExtType: "component", - TargetVersion: "(5|6)\\..*", + TargetVersion: "6\\..*", } // Manifest is the source of truth for extension metadata. @@ -192,8 +192,8 @@ func resolveExtensionMetadata(ctx context.Context, repo *repo_model.Repository, log.Error("resolveExtensionMetadata: GetRepoManifest for repo %d: %v", repo.ID, err) } if manifest != nil { - if manifest.ElementName != "" { - m.Element = manifest.ElementName + if elem := manifest.FullElementName(); elem != "" { + m.Element = elem } if manifest.PackageType != "" { m.ExtType = manifest.PackageType @@ -318,6 +318,7 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require // Load attachments for download URLs. if err := rel.LoadAttributes(ctx); err != nil { + log.Error("GenerateJoomlaXML: LoadAttributes for release %d (tag %s): %v", rel.ID, rel.TagName, err) continue } @@ -361,11 +362,13 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require if version == "" { version = rel.TagName } + // Append channel suffix only if the version doesn't already + // contain one (e.g. "1.2.3-rc2" already has "-rc"). suffix := stream.Suffix if suffix == "" { - suffix = channelSuffix(ch) // fallback for Joomla defaults + suffix = channelSuffix(ch) } - if suffix != "" { + if suffix != "" && !versionHasChannelSuffix(version) { version = version + suffix } @@ -380,13 +383,12 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require infoURL = meta.SupportURL } - // Joomla element: admin-side extensions use "administrator", - // site-side extensions use "site". Packages, components, libraries, - // and files are admin-side by default. - client := "site" + // Joomla element: 0 = site, 1 = administrator. + // Packages, components, libraries, and files are admin-side. + client := "0" switch extType { case "package", "component", "library", "file": - client = "administrator" + client = "1" } u := xmlUpdate{ @@ -436,8 +438,9 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require return append([]byte(xml.Header), output...), nil } -// versionRegex matches semantic version patterns like 1.0.0, 02.29.04, etc. -var versionRegex = regexp.MustCompile(`(\d+\.\d+(?:\.\d+)?)`) +// versionRegex matches semantic version patterns with optional pre-release +// suffixes, e.g. 1.0.0, 02.29.04, 1.2.3-rc2, 1.0.0-beta1. +var versionRegex = regexp.MustCompile(`(\d+\.\d+(?:\.\d+)?(?:-(?:dev|alpha|beta|rc)\d*)?)`) // extractVersion finds a version number from a tag name or release title. // Tries: (1) strip common prefixes for version-style tags, (2) regex match for embedded versions. @@ -447,13 +450,10 @@ func extractVersion(s string) string { v = strings.TrimPrefix(v, "v") v = strings.TrimPrefix(v, "release-") v = strings.TrimPrefix(v, "release/") - // Strip channel suffixes. - for _, suffix := range []string{"-dev", "-alpha", "-beta", "-rc", "-development", "-release-candidate"} { - if idx := strings.Index(strings.ToLower(v), suffix); idx > 0 { - v = v[:idx] - break - } - } + // Do not strip channel suffixes (e.g. -rc2, -beta1) here. + // The caller appends stream suffixes only when the version + // doesn't already contain one, preserving the original + // pre-release number for correct Joomla version comparison. // If result looks like a version (starts with digit), use it. if len(v) > 0 && v[0] >= '0' && v[0] <= '9' { return strings.TrimSpace(v) @@ -467,6 +467,17 @@ func extractVersion(s string) string { return "" } +// channelSuffixRegex matches a pre-release channel suffix at the end of a +// version string, e.g. "-rc", "-rc2", "-beta1", "-dev". Anchored to avoid +// false positives like "-devtools". +var channelSuffixRegex = regexp.MustCompile(`(?i)-(dev|alpha|beta|rc)\d*$`) + +// versionHasChannelSuffix checks if a version string already ends with a +// pre-release channel suffix (e.g. "-rc2", "-beta1", "-dev"). +func versionHasChannelSuffix(version string) bool { + return channelSuffixRegex.MatchString(version) +} + // channelSuffix returns the version suffix for a channel. func channelSuffix(channel string) string { switch channel {