Skip to content

Commit b59d82d

Browse files
committed
fix
1 parent 3778538 commit b59d82d

File tree

10 files changed

+83
-29
lines changed

10 files changed

+83
-29
lines changed

modules/git/commit_submodule_file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (sf *CommitSubmoduleFile) getWebLinkInTargetRepo(ctx context.Context, moreL
4242
return nil
4343
}
4444
if strings.HasPrefix(sf.refURL, "../") {
45-
targetLink := path.Join(sf.repoLink, path.Dir(sf.fullPath), sf.refURL)
45+
targetLink := path.Join(sf.repoLink, sf.refURL)
4646
return &SubmoduleWebLink{RepoWebLink: targetLink, CommitWebLink: targetLink + moreLinkPath}
4747
}
4848
if !sf.parsed {

modules/git/commit_submodule_file_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestCommitSubmoduleLink(t *testing.T) {
3232
assert.Equal(t, "/subpath/user/repo", wl.RepoWebLink)
3333
assert.Equal(t, "/subpath/user/repo/tree/aaaa", wl.CommitWebLink)
3434

35-
sf = NewCommitSubmoduleFile("/subpath/any/repo-home-link", "dir/submodule", "../../../user/repo", "aaaa")
35+
sf = NewCommitSubmoduleFile("/subpath/any/repo-home-link", "dir/submodule", "../../user/repo", "aaaa")
3636
wl = sf.SubmoduleWebLinkCompare(t.Context(), "1111", "2222")
3737
assert.Equal(t, "/subpath/user/repo", wl.RepoWebLink)
3838
assert.Equal(t, "/subpath/user/repo/compare/1111...2222", wl.CommitWebLink)

modules/git/utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"strconv"
1212
"strings"
1313
"sync"
14+
15+
"code.gitea.io/gitea/modules/util"
1416
)
1517

1618
// ObjectCache provides thread-safe cache operations.
@@ -106,3 +108,16 @@ func HashFilePathForWebUI(s string) string {
106108
_, _ = h.Write([]byte(s))
107109
return hex.EncodeToString(h.Sum(nil))
108110
}
111+
112+
func SplitCommitTitleBody(commitMessage string, titleRuneLimit int) (title, body string) {
113+
title, body, _ = strings.Cut(commitMessage, "\n")
114+
title, title2 := util.EllipsisTruncateRunes(title, titleRuneLimit)
115+
if title2 != "" {
116+
if body == "" {
117+
body = title2
118+
} else {
119+
body = title2 + "\n" + body
120+
}
121+
}
122+
return title, body
123+
}

modules/git/utils_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,17 @@ func TestHashFilePathForWebUI(t *testing.T) {
1515
HashFilePathForWebUI("foobar"),
1616
)
1717
}
18+
19+
func TestSplitCommitTitleBody(t *testing.T) {
20+
title, body := SplitCommitTitleBody("啊bcdefg", 4)
21+
assert.Equal(t, "啊…", title)
22+
assert.Equal(t, "…bcdefg", body)
23+
24+
title, body = SplitCommitTitleBody("abcdefg\n1234567", 4)
25+
assert.Equal(t, "a…", title)
26+
assert.Equal(t, "…bcdefg\n1234567", body)
27+
28+
title, body = SplitCommitTitleBody("abcdefg\n1234567", 100)
29+
assert.Equal(t, "abcdefg", title)
30+
assert.Equal(t, "1234567", body)
31+
}

modules/util/truncate.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func IsLikelyEllipsisLeftPart(s string) bool {
1919
return strings.HasSuffix(s, utf8Ellipsis) || strings.HasSuffix(s, asciiEllipsis)
2020
}
2121

22-
func ellipsisGuessDisplayWidth(r rune) int {
22+
func ellipsisDisplayGuessWidth(r rune) int {
2323
// To make the truncated string as long as possible,
2424
// CJK/emoji chars are considered as 2-ASCII width but not 3-4 bytes width.
2525
// Here we only make the best guess (better than counting them in bytes),
@@ -48,13 +48,17 @@ func ellipsisGuessDisplayWidth(r rune) int {
4848
// It appends "…" or "..." at the end of truncated string.
4949
// It guarantees the length of the returned runes doesn't exceed the limit.
5050
func EllipsisDisplayString(str string, limit int) string {
51-
s, _, _, _ := ellipsisDisplayString(str, limit)
51+
s, _, _, _ := ellipsisDisplayString(str, limit, ellipsisDisplayGuessWidth)
5252
return s
5353
}
5454

5555
// EllipsisDisplayStringX works like EllipsisDisplayString while it also returns the right part
5656
func EllipsisDisplayStringX(str string, limit int) (left, right string) {
57-
left, offset, truncated, encounterInvalid := ellipsisDisplayString(str, limit)
57+
return ellipsisDisplayStringX(str, limit, ellipsisDisplayGuessWidth)
58+
}
59+
60+
func ellipsisDisplayStringX(str string, limit int, widthGuess func(rune) int) (left, right string) {
61+
left, offset, truncated, encounterInvalid := ellipsisDisplayString(str, limit, widthGuess)
5862
if truncated {
5963
right = str[offset:]
6064
r, _ := utf8.DecodeRune(UnsafeStringToBytes(right))
@@ -68,7 +72,7 @@ func EllipsisDisplayStringX(str string, limit int) (left, right string) {
6872
return left, right
6973
}
7074

71-
func ellipsisDisplayString(str string, limit int) (res string, offset int, truncated, encounterInvalid bool) {
75+
func ellipsisDisplayString(str string, limit int, widthGuess func(rune) int) (res string, offset int, truncated, encounterInvalid bool) {
7276
if len(str) <= limit {
7377
return str, len(str), false, false
7478
}
@@ -81,7 +85,7 @@ func ellipsisDisplayString(str string, limit int) (res string, offset int, trunc
8185
for i, r := range str {
8286
encounterInvalid = encounterInvalid || r == utf8.RuneError
8387
pos = i
84-
runeWidth := ellipsisGuessDisplayWidth(r)
88+
runeWidth := widthGuess(r)
8589
if used+runeWidth+3 > limit {
8690
break
8791
}
@@ -96,7 +100,7 @@ func ellipsisDisplayString(str string, limit int) (res string, offset int, trunc
96100
if nextCnt >= 4 {
97101
break
98102
}
99-
nextWidth += ellipsisGuessDisplayWidth(r)
103+
nextWidth += widthGuess(r)
100104
nextCnt++
101105
}
102106
if nextCnt <= 3 && used+nextWidth <= limit {
@@ -114,6 +118,10 @@ func ellipsisDisplayString(str string, limit int) (res string, offset int, trunc
114118
return str[:offset] + ellipsis, offset, true, encounterInvalid
115119
}
116120

121+
func EllipsisTruncateRunes(str string, limit int) (left, right string) {
122+
return ellipsisDisplayStringX(str, limit, func(r rune) int { return 1 })
123+
}
124+
117125
// TruncateRunes returns a truncated string with given rune limit,
118126
// it returns input string if its rune length doesn't exceed the limit.
119127
func TruncateRunes(str string, limit int) string {

routers/web/feed/branch.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@ import (
88
"time"
99

1010
"code.gitea.io/gitea/models/repo"
11+
"code.gitea.io/gitea/modules/git"
1112
"code.gitea.io/gitea/services/context"
1213

1314
"github.com/gorilla/feeds"
1415
)
1516

1617
// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed
1718
func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
18-
commits, err := ctx.Repo.Commit.CommitsByRange(0, 10, "", "", "")
19-
if err != nil {
20-
ctx.ServerError("ShowBranchFeed", err)
21-
return
19+
var commits []*git.Commit
20+
var err error
21+
if ctx.Repo.Commit != nil {
22+
commits, err = ctx.Repo.Commit.CommitsByRange(0, 10, "", "", "")
23+
if err != nil {
24+
ctx.ServerError("ShowBranchFeed", err)
25+
return
26+
}
2227
}
2328

2429
title := "Latest commits for branch " + ctx.Repo.BranchName

services/repository/files/tree.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
9191
return tree, nil
9292
}
9393
var rangeEnd int
94-
if len(entries) > perPage {
94+
rangeEnd = min(rangeStart+perPage, len(entries))
95+
if rangeEnd < len(entries) {
9596
tree.Truncated = true
9697
}
97-
rangeEnd = min(rangeStart+perPage, len(entries))
9898
tree.Entries = make([]api.GitEntry, rangeEnd-rangeStart)
9999
for e := rangeStart; e < rangeEnd; e++ {
100100
i := e - rangeStart

services/repository/push.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -402,16 +402,11 @@ func pushUpdateAddTags(ctx context.Context, repo *repo_model.Repository, gitRepo
402402
}
403403

404404
rel, has := relMap[lowerTag]
405-
406-
parts := strings.SplitN(tag.Message, "\n", 2)
407-
note := ""
408-
if len(parts) > 1 {
409-
note = parts[1]
410-
}
405+
title, note := git.SplitCommitTitleBody(tag.Message, 255)
411406
if !has {
412407
rel = &repo_model.Release{
413408
RepoID: repo.ID,
414-
Title: parts[0],
409+
Title: title,
415410
TagName: tags[i],
416411
LowerTagName: lowerTag,
417412
Target: "",
@@ -430,7 +425,7 @@ func pushUpdateAddTags(ctx context.Context, repo *repo_model.Repository, gitRepo
430425
rel.Sha1 = commit.ID.String()
431426
rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix())
432427
if rel.IsTag {
433-
rel.Title = parts[0]
428+
rel.Title = title
434429
rel.Note = note
435430
} else {
436431
rel.IsDraft = false

tests/integration/api_repo_git_trees_test.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import (
1111
repo_model "code.gitea.io/gitea/models/repo"
1212
"code.gitea.io/gitea/models/unittest"
1313
user_model "code.gitea.io/gitea/models/user"
14+
api "code.gitea.io/gitea/modules/structs"
1415
"code.gitea.io/gitea/tests"
16+
17+
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
1519
)
1620

1721
func TestAPIReposGitTrees(t *testing.T) {
@@ -32,13 +36,21 @@ func TestAPIReposGitTrees(t *testing.T) {
3236
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
3337

3438
// Test a public repo that anyone can GET the tree of
35-
for _, ref := range [...]string{
36-
"master", // Branch
37-
repo1TreeSHA, // Tree SHA
38-
} {
39-
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/trees/%s", user2.Name, repo1.Name, ref)
40-
MakeRequest(t, req, http.StatusOK)
41-
}
39+
_ = MakeRequest(t, NewRequest(t, "GET", "/api/v1/repos/user2/repo1/git/trees/master"), http.StatusOK)
40+
41+
resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/repos/user2/repo1/git/trees/62fb502a7172d4453f0322a2cc85bddffa57f07a?per_page=1"), http.StatusOK)
42+
var respGitTree api.GitTreeResponse
43+
DecodeJSON(t, resp, &respGitTree)
44+
assert.True(t, respGitTree.Truncated)
45+
require.Len(t, respGitTree.Entries, 1)
46+
assert.Equal(t, "File-WoW", respGitTree.Entries[0].Path)
47+
48+
resp = MakeRequest(t, NewRequest(t, "GET", "/api/v1/repos/user2/repo1/git/trees/62fb502a7172d4453f0322a2cc85bddffa57f07a?page=2&per_page=1"), http.StatusOK)
49+
respGitTree = api.GitTreeResponse{}
50+
DecodeJSON(t, resp, &respGitTree)
51+
assert.False(t, respGitTree.Truncated)
52+
require.Len(t, respGitTree.Entries, 1)
53+
assert.Equal(t, "README.md", respGitTree.Entries[0].Path)
4254

4355
// Tests a private repo with no token so will fail
4456
for _, ref := range [...]string{

tests/integration/empty_repo_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ func TestEmptyRepoAddFile(t *testing.T) {
7575
req = NewRequest(t, "GET", "/api/v1/repos/user30/empty/raw/main/README.md").AddTokenAuth(token)
7676
session.MakeRequest(t, req, http.StatusNotFound)
7777

78+
// test feed
79+
req = NewRequest(t, "GET", "/user30/empty/rss/branch/main/README.md").AddTokenAuth(token).SetHeader("Accept", "application/rss+xml")
80+
resp = session.MakeRequest(t, req, http.StatusOK)
81+
assert.Contains(t, resp.Body.String(), "</rss>")
82+
7883
// create a new file
7984
req = NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
8085
resp = session.MakeRequest(t, req, http.StatusOK)

0 commit comments

Comments
 (0)