diff --git a/models/repo/attachment.go b/models/repo/attachment.go index cb05386d93..93b83aae8a 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -18,17 +18,18 @@ import ( // Attachment represent a attachment of issue/comment/release. type Attachment struct { - ID int64 `xorm:"pk autoincr"` - UUID string `xorm:"uuid UNIQUE"` - RepoID int64 `xorm:"INDEX"` // this should not be zero - IssueID int64 `xorm:"INDEX"` // maybe zero when creating - ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating - UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added - CommentID int64 - Name string - DownloadCount int64 `xorm:"DEFAULT 0"` - Size int64 `xorm:"DEFAULT 0"` - CreatedUnix timeutil.TimeStamp `xorm:"created"` + ID int64 `xorm:"pk autoincr"` + UUID string `xorm:"uuid UNIQUE"` + RepoID int64 `xorm:"INDEX"` // this should not be zero + IssueID int64 `xorm:"INDEX"` // maybe zero when creating + ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating + UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added + CommentID int64 + Name string + DownloadCount int64 `xorm:"DEFAULT 0"` + Size int64 `xorm:"DEFAULT 0"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + CustomDownloadURL string `xorm:"-"` } func init() { @@ -57,6 +58,10 @@ func (a *Attachment) RelativePath() string { // DownloadURL returns the download url of the attached file func (a *Attachment) DownloadURL() string { + if a.CustomDownloadURL != "" { + return a.CustomDownloadURL + } + return setting.AppURL + "attachments/" + url.PathEscape(a.UUID) } diff --git a/models/repo/release.go b/models/repo/release.go index c8dd7fbc7a..75eb27f074 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -7,6 +7,7 @@ package repo import ( "context" "fmt" + "net/url" "sort" "strconv" "strings" @@ -372,6 +373,34 @@ func GetReleaseAttachments(ctx context.Context, rels ...*Release) (err error) { sortedRels.Rel[currentIndex].Attachments = append(sortedRels.Rel[currentIndex].Attachments, attachment) } + // Makes URL's predictable + for _, release := range rels { + // If we have no Repo, we don't need to execute this loop + if release.Repo == nil { + 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 { + for _, attachment := range release.Attachments { + attachment.CustomDownloadURL = release.Repo.HTMLURL() + "/releases/download/" + url.PathEscape(release.TagName) + "/" + url.PathEscape(attachment.Name) + } + } + } + return err } diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go index c6d8828fac..9fb9cb00bf 100644 --- a/routers/web/repo/attachment.go +++ b/routers/web/repo/attachment.go @@ -86,9 +86,9 @@ func DeleteAttachment(ctx *context.Context) { }) } -// GetAttachment serve attachments -func GetAttachment(ctx *context.Context) { - attach, err := repo_model.GetAttachmentByUUID(ctx, ctx.Params(":uuid")) +// GetAttachment serve attachments with the given UUID +func ServeAttachment(ctx *context.Context, uuid string) { + attach, err := repo_model.GetAttachmentByUUID(ctx, uuid) if err != nil { if repo_model.IsErrAttachmentNotExist(err) { ctx.Error(http.StatusNotFound) @@ -153,3 +153,8 @@ func GetAttachment(ctx *context.Context) { return } } + +// GetAttachment serve attachments +func GetAttachment(ctx *context.Context) { + ServeAttachment(ctx, ctx.Params(":uuid")) +} diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 14ef1372c0..e8caa2cbb7 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -142,6 +142,10 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { return } + for _, release := range releases { + release.Repo = ctx.Repo.Repository + } + if err = repo_model.GetReleaseAttachments(ctx, releases...); err != nil { ctx.ServerError("GetReleaseAttachments", err) return @@ -248,6 +252,8 @@ func SingleRelease(ctx *context.Context) { ctx.Data["Title"] = release.Title } + release.Repo = ctx.Repo.Repository + err = repo_model.GetReleaseAttachments(ctx, release) if err != nil { ctx.ServerError("GetReleaseAttachments", err) diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 9b80e85324..5a97c5190c 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -373,7 +373,7 @@ func RedirectDownload(ctx *context.Context) { return } if att != nil { - ctx.Redirect(att.DownloadURL()) + ServeAttachment(ctx, att.UUID) return } }