Skip to content

Commit 56d4893

Browse files
authored
Add RSS Feeds for branches and files (go-gitea#22719)
Fix go-gitea#22228 adding RSS feeds for branches and files. RSS feeds are accessed through: * [gitea]/src/branch/{branch}.rss * [gitea]/src/branch/{branch}/{file_name}.rss No changes have been made to the UI to expose the feed urls for branches and files.
1 parent f16b668 commit 56d4893

File tree

11 files changed

+170
-6
lines changed

11 files changed

+170
-6
lines changed

routers/web/feed/branch.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package feed
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
"time"
10+
11+
"code.gitea.io/gitea/models/repo"
12+
"code.gitea.io/gitea/modules/context"
13+
14+
"github.com/gorilla/feeds"
15+
)
16+
17+
// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed
18+
func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
19+
commits, err := ctx.Repo.Commit.CommitsByRange(0, 10)
20+
if err != nil {
21+
ctx.ServerError("ShowBranchFeed %s", err)
22+
return
23+
}
24+
25+
title := fmt.Sprintf("Latest commits for branch %s", ctx.Repo.BranchName)
26+
link := &feeds.Link{Href: repo.HTMLURL() + "/" + ctx.Repo.BranchNameSubURL()}
27+
28+
feed := &feeds.Feed{
29+
Title: title,
30+
Link: link,
31+
Description: repo.Description,
32+
Created: time.Now(),
33+
}
34+
35+
for _, commit := range commits {
36+
feed.Items = append(feed.Items, &feeds.Item{
37+
Id: commit.ID.String(),
38+
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
39+
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
40+
Author: &feeds.Author{
41+
Name: commit.Author.Name,
42+
Email: commit.Author.Email,
43+
},
44+
Description: commit.Message(),
45+
Content: commit.Message(),
46+
})
47+
}
48+
49+
writeFeed(ctx, feed, formatType)
50+
}

routers/web/feed/file.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package feed
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
"time"
10+
11+
"code.gitea.io/gitea/models/repo"
12+
"code.gitea.io/gitea/modules/context"
13+
"code.gitea.io/gitea/modules/util"
14+
15+
"github.com/gorilla/feeds"
16+
)
17+
18+
// ShowFileFeed shows tags and/or releases on the repo as RSS / Atom feed
19+
func ShowFileFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
20+
fileName := ctx.Repo.TreePath
21+
if len(fileName) == 0 {
22+
return
23+
}
24+
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(ctx.Repo.RefName, fileName, 1)
25+
if err != nil {
26+
ctx.ServerError("ShowBranchFeed %s", err)
27+
return
28+
}
29+
30+
title := fmt.Sprintf("Latest commits for file %s", ctx.Repo.TreePath)
31+
32+
link := &feeds.Link{Href: repo.HTMLURL() + "/" + ctx.Repo.BranchNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)}
33+
34+
feed := &feeds.Feed{
35+
Title: title,
36+
Link: link,
37+
Description: repo.Description,
38+
Created: time.Now(),
39+
}
40+
41+
for _, commit := range commits {
42+
feed.Items = append(feed.Items, &feeds.Item{
43+
Id: commit.ID.String(),
44+
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
45+
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
46+
Author: &feeds.Author{
47+
Name: commit.Author.Name,
48+
Email: commit.Author.Email,
49+
},
50+
Description: commit.Message(),
51+
Content: commit.Message(),
52+
})
53+
}
54+
55+
writeFeed(ctx, feed, formatType)
56+
}

routers/web/feed/render.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package feed
5+
6+
import (
7+
model "code.gitea.io/gitea/models/repo"
8+
"code.gitea.io/gitea/modules/context"
9+
)
10+
11+
// RenderBranchFeed render format for branch or file
12+
func RenderBranchFeed(ctx *context.Context) {
13+
_, _, showFeedType := GetFeedType(ctx.Params(":reponame"), ctx.Req)
14+
var renderer func(ctx *context.Context, repo *model.Repository, formatType string)
15+
switch {
16+
case ctx.Repo.TreePath == "":
17+
renderer = ShowBranchFeed
18+
case ctx.Repo.TreePath != "":
19+
renderer = ShowFileFeed
20+
}
21+
renderer(ctx, ctx.Repo.Repository, showFeedType)
22+
}

routers/web/repo/branch.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"code.gitea.io/gitea/modules/util"
2626
"code.gitea.io/gitea/modules/web"
2727
"code.gitea.io/gitea/routers/utils"
28+
"code.gitea.io/gitea/routers/web/feed"
2829
"code.gitea.io/gitea/services/forms"
2930
release_service "code.gitea.io/gitea/services/release"
3031
repo_service "code.gitea.io/gitea/services/repository"
@@ -340,6 +341,11 @@ func getDeletedBranches(ctx *context.Context) ([]*Branch, error) {
340341
return branches, nil
341342
}
342343

344+
// BranchFeedRSS get feeds for tags in RSS format
345+
func BranchFeedRSS(ctx *context.Context) {
346+
feed.ShowBranchFeed(ctx, ctx.Repo.Repository, "rss")
347+
}
348+
343349
// CreateBranch creates new branch in repository
344350
func CreateBranch(ctx *context.Context) {
345351
form := web.GetForm(ctx).(*forms.NewBranchForm)

routers/web/repo/view.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,14 @@ func Home(ctx *context.Context) {
710710
if setting.Other.EnableFeed {
711711
isFeed, _, showFeedType := feed.GetFeedType(ctx.Params(":reponame"), ctx.Req)
712712
if isFeed {
713-
feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType)
713+
switch {
714+
case ctx.Link == fmt.Sprintf("%s.%s", ctx.Repo.RepoLink, showFeedType):
715+
feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType)
716+
case ctx.Repo.TreePath == "":
717+
feed.ShowBranchFeed(ctx, ctx.Repo.Repository, showFeedType)
718+
case ctx.Repo.TreePath != "":
719+
feed.ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType)
720+
}
714721
return
715722
}
716723
}

routers/web/web.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,9 @@ func RegisterRoutes(m *web.Route) {
14501450
m.Get("/cherry-pick/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
14511451
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
14521452

1453+
m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feed.RenderBranchFeed)
1454+
m.Get("/atom/branch/*", context.RepoRefByType(context.RepoRefBranch), feed.RenderBranchFeed)
1455+
14531456
m.Group("/src", func() {
14541457
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
14551458
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)

templates/repo/branch/list.tmpl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
{{svg "octicon-git-branch"}}
2727
</button>
2828
{{end}}
29+
{{if .EnableFeed}}
30+
<a role="button" class="ui basic button icon" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranch}}">
31+
{{svg "octicon-rss"}}
32+
</a>
33+
{{end}}
2934
{{if not $.DisableDownloadSourceArchives}}
3035
<button class="ui basic jump dropdown icon button" data-tooltip-content="{{$.locale.Tr "repo.branch.download" ($.DefaultBranch)}}">
3136
{{svg "octicon-download"}}
@@ -113,6 +118,11 @@
113118
{{svg "octicon-git-branch"}}
114119
</button>
115120
{{end}}
121+
{{if $.EnableFeed}}
122+
<a role="button" class="ui basic button icon" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .Name}}">
123+
{{svg "octicon-rss"}}
124+
</a>
125+
{{end}}
116126
{{if and (not .IsDeleted) (not $.DisableDownloadSourceArchives)}}
117127
<button class="ui basic jump dropdown icon button" data-tooltip-content="{{$.locale.Tr "repo.branch.download" (.Name)}}">
118128
{{svg "octicon-download"}}

templates/repo/home.tmpl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@
6363
{{$n := len .TreeNames}}
6464
{{$l := Eval $n "-" 1}}
6565
<!-- If home page, show new pr. If not, show breadcrumb -->
66+
{{if and (eq $n 0) .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
67+
<a href="{{CompareLink .BaseRepo .Repository .BranchName}}">
68+
<button id="new-pull-request" class="ui compact basic button" data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}"><span class="text">{{svg "octicon-git-pull-request"}}</span></button>
69+
</a>
70+
{{end}}
6671
{{if eq $n 0}}
67-
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
68-
<a href="{{CompareLink .BaseRepo .Repository .BranchName}}">
69-
<button id="new-pull-request" class="ui compact basic button" data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}"><span class="text">{{svg "octicon-git-pull-request"}}</span></button>
70-
</a>
71-
{{end}}
7272
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{.locale.Tr "repo.find_file.go_to_file"}}</a>
7373
{{end}}
7474

templates/repo/view_file.tmpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
</div>
4343
<a download href="{{$.RawFileLink}}"><span class="btn-octicon" data-tooltip-content="{{.locale.Tr "repo.download_file"}}">{{svg "octicon-download"}}</span></a>
4444
<a id="copy-content" class="btn-octicon {{if not .CanCopyContent}} disabled{{end}}"{{if or .IsImageFile (and .HasSourceRenderedToggle (not .IsDisplayingSource))}} data-link="{{$.RawFileLink}}"{{end}} data-tooltip-content="{{if .CanCopyContent}}{{.locale.Tr "copy_content"}}{{else}}{{.locale.Tr "copy_type_unsupported"}}{{end}}">{{svg "octicon-copy" 14}}</a>
45+
{{if .EnableFeed}}
46+
<a class="btn-octicon" href="{{$.FeedURL}}/rss/{{$.BranchNameSubURL}}{{range $i, $v := .TreeNames}}/{{$v}}{{end}}">
47+
{{svg "octicon-rss" 14}}
48+
</a>
49+
{{end}}
4550
{{if .Repository.CanEnableEditor}}
4651
{{if .CanEditFile}}
4752
<a href="{{.RepoLink}}/_edit/{{PathEscapeSegments .BranchName}}/{{PathEscapeSegments .TreePath}}"><span class="btn-octicon" data-tooltip-content="{{.EditFileTooltip}}">{{svg "octicon-pencil"}}</span></a>

web_src/js/components/RepoBranchTagSelector.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
<div class="scrolling menu" ref="scrollContainer">
4040
<div v-for="(item, index) in filteredItems" :key="item.name" class="item" :class="{selected: item.selected, active: active === index}" @click="selectItem(item)" :ref="'listItem' + index">
4141
{{ item.name }}
42+
<a v-if="mode === 'branches'" role="button" class="ui compact muted right" :href="(branchURLPrefix + item.url).replace('src', 'rss')">
43+
<svg-icon name="octicon-rss" :size="14"/>
44+
</a>
4245
</div>
4346
<div class="item" v-if="showCreateNewBranch" :class="{active: active === filteredItems.length}" :ref="'listItem' + filteredItems.length">
4447
<a href="#" @click="createNewBranch()">

web_src/js/svg.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg';
4343
import octiconOrganization from '../../public/img/svg/octicon-organization.svg';
4444
import octiconTag from '../../public/img/svg/octicon-tag.svg';
4545
import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg';
46+
import octiconRss from '../../public/img/svg/octicon-rss.svg';
4647

4748
const svgs = {
4849
'octicon-blocked': octiconBlocked,
@@ -89,6 +90,7 @@ const svgs = {
8990
'octicon-organization': octiconOrganization,
9091
'octicon-tag': octiconTag,
9192
'octicon-git-branch': octiconGitBranch,
93+
'octicon-rss': octiconRss,
9294
};
9395

9496
// TODO: use a more general approach to access SVG icons.

0 commit comments

Comments
 (0)