From 35131156876e3d4bda7f95dd807be1da6ea734c2 Mon Sep 17 00:00:00 2001 From: Reo Date: Sun, 6 Nov 2022 00:47:53 +0700 Subject: [PATCH 1/7] Add Feed for Releases and Tags Signed-off-by: Reo --- options/locale/locale_en-US.ini | 2 ++ routers/web/feed/convert.go | 45 +++++++++++++++++++++++++++++ routers/web/feed/release.go | 51 +++++++++++++++++++++++++++++++++ routers/web/repo/release.go | 25 ++++++++++++++++ routers/web/web.go | 9 ++++-- 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 routers/web/feed/release.go diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 1566dfc97d42..8d056d19b7ef 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2265,6 +2265,8 @@ release.downloads = Downloads release.download_count = Downloads: %s release.add_tag_msg = Use the title and content of release as tag message. release.add_tag = Create Tag Only +release.releases_for = Releases for %s +release.tags_for = Tags for %s branch.name = Branch Name branch.search = Search branches diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 306ecf7d6a3f..796c3b40d2c8 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -13,6 +13,7 @@ import ( "strings" activities_model "code.gitea.io/gitea/models/activities" + repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" @@ -263,3 +264,47 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) { return false, name, "" } + +// feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item +func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) { + for _, rel := range releases { + err := rel.LoadAttributes() + if err != nil { + return nil, err + } + + var title, content string + + if rel.IsTag { + title = rel.TagName + } else { + title = rel.Title + } + + link := &feeds.Link{Href: rel.HTMLURL()} + content, err = markdown.RenderString(&markup.RenderContext{ + Ctx: ctx, + URLPrefix: rel.Repo.Link(), + Metas: rel.Repo.ComposeMetas(), + }, rel.Note) + content = html.EscapeString(content) + + if err != nil { + return nil, err + } + + items = append(items, &feeds.Item{ + Title: title, + Link: link, + Created: rel.CreatedUnix.AsTime(), + Author: &feeds.Author{ + Name: rel.Publisher.DisplayName(), + Email: rel.Publisher.GetEmail(), + }, + Id: fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href), + Content: content, + }) + } + + return items, err +} diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go new file mode 100644 index 000000000000..5ee1b3045cbf --- /dev/null +++ b/routers/web/feed/release.go @@ -0,0 +1,51 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package feed + +import ( + "time" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/context" + + "github.com/gorilla/feeds" +) + +// shows tags and/or releases on the repo as RSS / Atom feed +func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) { + releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ + IncludeTags: !isReleasesOnly, + }) + if err != nil { + ctx.ServerError("GetReleasesByRepoID", err) + return + } + + var title string + var link *feeds.Link + + if isReleasesOnly { + title = ctx.Tr("repo.release.releases_for", repo.FullName()) + link = &feeds.Link{Href: repo.HTMLURL() + "/release"} + } else { + title = ctx.Tr("repo.release.tags_for", repo.FullName()) + link = &feeds.Link{Href: repo.HTMLURL() + "/tags"} + } + + feed := &feeds.Feed{ + Title: title, + Link: link, + Description: repo.Description, + Created: time.Now(), + } + + feed.Items, err = releasesToFeedItems(ctx, releases, isReleasesOnly) + if err != nil { + ctx.ServerError("releasesToFeedItems", err) + return + } + + writeFeed(ctx, feed, formatType) +} diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 0cb85f37984f..bb70d9c38b25 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/web/feed" "code.gitea.io/gitea/services/forms" releaseservice "code.gitea.io/gitea/services/release" ) @@ -200,6 +201,30 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { ctx.HTML(http.StatusOK, tplReleases) } +// ReleasesFeedRSS get feeds for releases in RSS format +func ReleasesFeedRSS(ctx *context.Context) { + releasesOrTagsFeed(ctx, true, "rss") +} + +// TagsListFeedRSS get feeds for tags in RSS format +func TagsListFeedRSS(ctx *context.Context) { + releasesOrTagsFeed(ctx, false, "rss") +} + +// ReleasesFeedAtom get feeds for releases in Atom format +func ReleasesFeedAtom(ctx *context.Context) { + releasesOrTagsFeed(ctx, true, "atom") +} + +// TagsListFeedAtom get feeds for tags in RSS format +func TagsListFeedAtom(ctx *context.Context) { + releasesOrTagsFeed(ctx, false, "atom") +} + +func releasesOrTagsFeed(ctx *context.Context, isReleasesOnly bool, formatType string) { + feed.ShowReleaseFeed(ctx, ctx.Repo.Repository, isReleasesOnly, formatType) +} + // SingleRelease renders a single release's page func SingleRelease(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.releases") diff --git a/routers/web/web.go b/routers/web/web.go index 0b16e756e182..c648120144a2 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1037,12 +1037,17 @@ func RegisterRoutes(m *web.Route) { // Releases m.Group("/{username}/{reponame}", func() { - m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty, - reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) + m.Group("/tags", func() { + m.Get("/", repo.TagsList) + m.Get(".rss", repo.TagsListFeedRSS) + m.Get(".atom", repo.TagsListFeedAtom) + }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) m.Group("/releases", func() { m.Get("/", repo.Releases) m.Get("/tag/*", repo.SingleRelease) m.Get("/latest", repo.LatestRelease) + m.Get(".rss", repo.ReleasesFeedRSS) + m.Get(".atom", repo.ReleasesFeedAtom) }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader) m.Group("/releases", func() { From ef6b32dc9b117dd79327a35400632f38363b097c Mon Sep 17 00:00:00 2001 From: Reo Date: Sun, 6 Nov 2022 13:58:20 +0700 Subject: [PATCH 2/7] Modify route for tags Signed-off-by: Reo --- routers/web/web.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/web/web.go b/routers/web/web.go index c648120144a2..3185b4a25ea2 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1038,10 +1038,10 @@ func RegisterRoutes(m *web.Route) { // Releases m.Group("/{username}/{reponame}", func() { m.Group("/tags", func() { - m.Get("/", repo.TagsList) + m.Get("", repo.TagsList) m.Get(".rss", repo.TagsListFeedRSS) m.Get(".atom", repo.TagsListFeedAtom) - }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) + }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) m.Group("/releases", func() { m.Get("/", repo.Releases) m.Get("/tag/*", repo.SingleRelease) From b2b2c9be7fcf4ebd0fcb7c640a1929f51f6e4a5e Mon Sep 17 00:00:00 2001 From: Reo Date: Sat, 26 Nov 2022 17:51:23 +0700 Subject: [PATCH 3/7] Add disable feed Signed-off-by: Reo --- routers/web/feed/convert.go | 2 +- routers/web/feed/release.go | 2 +- routers/web/web.go | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 53c8d895ef49..05dbd4f4df05 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -274,7 +274,7 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) { // feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) { for _, rel := range releases { - err := rel.LoadAttributes() + err := rel.LoadAttributes(ctx) if err != nil { return nil, err } diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go index 5ee1b3045cbf..08685ae12226 100644 --- a/routers/web/feed/release.go +++ b/routers/web/feed/release.go @@ -15,7 +15,7 @@ import ( // shows tags and/or releases on the repo as RSS / Atom feed func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) { - releases, err := repo_model.GetReleasesByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ IncludeTags: !isReleasesOnly, }) if err != nil { diff --git a/routers/web/web.go b/routers/web/web.go index 4b88366b056c..1c2ee4d14faf 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1083,15 +1083,15 @@ func RegisterRoutes(m *web.Route) { m.Group("/{username}/{reponame}", func() { m.Group("/tags", func() { m.Get("", repo.TagsList) - m.Get(".rss", repo.TagsListFeedRSS) - m.Get(".atom", repo.TagsListFeedAtom) + m.Get(".rss", feedEnabled, repo.TagsListFeedRSS) + m.Get(".atom", feedEnabled, repo.TagsListFeedAtom) }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) m.Group("/releases", func() { m.Get("/", repo.Releases) m.Get("/tag/*", repo.SingleRelease) m.Get("/latest", repo.LatestRelease) - m.Get(".rss", repo.ReleasesFeedRSS) - m.Get(".atom", repo.ReleasesFeedAtom) + m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) + m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom) }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader) m.Group("/releases", func() { From 2ec480f42c74fe004608766f09e332cccbe3a49a Mon Sep 17 00:00:00 2001 From: zeripath Date: Sun, 4 Dec 2022 11:41:15 +0000 Subject: [PATCH 4/7] Apply suggestions from code review --- routers/web/feed/convert.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 05dbd4f4df05..a4b3dc628f8a 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -293,7 +293,6 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, i URLPrefix: rel.Repo.Link(), Metas: rel.Repo.ComposeMetas(), }, rel.Note) - content = html.EscapeString(content) if err != nil { return nil, err From 1bc85f8cc8ef082697bbd643ca895d1fe7024a29 Mon Sep 17 00:00:00 2001 From: Reo <112817228+reopt999@users.noreply.github.com> Date: Mon, 5 Dec 2022 09:09:32 +0700 Subject: [PATCH 5/7] Update routers/web/feed/release.go Co-authored-by: Yarden Shoham --- routers/web/feed/release.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go index 08685ae12226..fbfa11c63ecf 100644 --- a/routers/web/feed/release.go +++ b/routers/web/feed/release.go @@ -1,6 +1,5 @@ // Copyright 2022 The Gitea Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT package feed From 5dacc701dae70fbb19f0d2beff6c3a729031152f Mon Sep 17 00:00:00 2001 From: Reo Date: Sun, 18 Dec 2022 15:32:11 +0700 Subject: [PATCH 6/7] Add RSS icon Signed-off-by: Reo --- routers/web/web.go | 4 ++++ templates/repo/release/list.tmpl | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/routers/web/web.go b/routers/web/web.go index eb6f0e27bcc0..d3f8be69d1b7 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1081,6 +1081,8 @@ func RegisterRoutes(m *web.Route) { m.Get("", repo.TagsList) m.Get(".rss", feedEnabled, repo.TagsListFeedRSS) m.Get(".atom", feedEnabled, repo.TagsListFeedAtom) + }, func(ctx *context.Context) { + ctx.Data["EnableFeed"] = setting.EnableFeed }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) m.Group("/releases", func() { m.Get("/", repo.Releases) @@ -1088,6 +1090,8 @@ func RegisterRoutes(m *web.Route) { m.Get("/latest", repo.LatestRelease) m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom) + }, func(ctx *context.Context) { + ctx.Data["EnableFeed"] = setting.EnableFeed }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader) m.Group("/releases", func() { diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index f8c54bf7f6e0..5d49da88b5b3 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -9,8 +9,11 @@ {{end}} {{if .Permission.CanRead $.UnitTypeCode}} {{.locale.Tr "repo.release.tags"}} - {{end}} + {{end}} + {{if .EnableFeed}} + {{svg "octicon-rss" 18}} + {{end}} {{if (and .CanCreateRelease (not .PageIsTagList))}} {{.locale.Tr "repo.release.new_release"}} From 0ca23ca70832602549ca9d02162a00a7b68d262b Mon Sep 17 00:00:00 2001 From: Reo Date: Sun, 18 Dec 2022 15:44:11 +0700 Subject: [PATCH 7/7] Fix whitespace Signed-off-by: Reo --- templates/repo/release/list.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index 5d49da88b5b3..9f4104bec5c1 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -9,7 +9,7 @@ {{end}} {{if .Permission.CanRead $.UnitTypeCode}} {{.locale.Tr "repo.release.tags"}} - {{end}} + {{end}} {{if .EnableFeed}} {{svg "octicon-rss" 18}}