From bd7b5e61aa8d8f8a7dfd1ce4b49bf6461fce57b8 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Thu, 27 Jul 2023 17:24:22 +0800
Subject: [PATCH] Release attachments duplicated check (#26176)

---
 models/repo/release.go | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/models/repo/release.go b/models/repo/release.go
index c63b324457..a00585111e 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -14,6 +14,7 @@ import (
 
 	"code.gitea.io/gitea/models/db"
 	user_model "code.gitea.io/gitea/models/user"
+	"code.gitea.io/gitea/modules/container"
 	"code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/timeutil"
 	"code.gitea.io/gitea/modules/util"
@@ -336,6 +337,17 @@ func (s releaseMetaSearch) Less(i, j int) bool {
 	return s.ID[i] < s.ID[j]
 }
 
+func hasDuplicateName(attaches []*Attachment) bool {
+	attachSet := container.Set[string]{}
+	for _, attachment := range attaches {
+		if attachSet.Contains(attachment.Name) {
+			return true
+		}
+		attachSet.Add(attachment.Name)
+	}
+	return false
+}
+
 // GetReleaseAttachments retrieves the attachments for releases
 func GetReleaseAttachments(ctx context.Context, rels ...*Release) (err error) {
 	if len(rels) == 0 {
@@ -360,7 +372,7 @@ func GetReleaseAttachments(ctx context.Context, rels ...*Release) (err error) {
 	err = db.GetEngine(ctx).
 		Asc("release_id", "name").
 		In("release_id", sortedRels.ID).
-		Find(&attachments, Attachment{})
+		Find(&attachments)
 	if err != nil {
 		return err
 	}
@@ -381,21 +393,8 @@ func GetReleaseAttachments(ctx context.Context, rels ...*Release) (err error) {
 			continue
 		}
 
-		// Check if there are two or more attachments with the same name
-		hasDuplicates := false
-		foundNames := make(map[string]bool)
-		for _, attachment := range release.Attachments {
-			_, found := foundNames[attachment.Name]
-			if found {
-				hasDuplicates = true
-				break
-			} else {
-				foundNames[attachment.Name] = true
-			}
-		}
-
 		// If the names unique, use the URL with the Name instead of the UUID
-		if !hasDuplicates {
+		if !hasDuplicateName(release.Attachments) {
 			for _, attachment := range release.Attachments {
 				attachment.CustomDownloadURL = release.Repo.HTMLURL() + "/releases/download/" + url.PathEscape(release.TagName) + "/" + url.PathEscape(attachment.Name)
 			}