Skip to content

Commit 9754baf

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: [skip ci] Updated translations via Crowdin unset XDG_HOME_CONFIG as gitea manages configuration locations (go-gitea#33067) Refactor repo-new.ts (go-gitea#33070) Refactor pull-request compare&create page (go-gitea#33071) feat: link to nuget dependencies (go-gitea#26554) Remove some unnecessary template helpers (go-gitea#33069) Inherit submodules from template repository content (go-gitea#16237) [skip ci] Updated translations via Crowdin feat(action): issue change title notifications (go-gitea#33050) Use project's redirect url instead of composing url (go-gitea#33058) Fix unittest and repo create bug (go-gitea#33061) Fix locale type (go-gitea#33059) Refactor maven package registry (go-gitea#33049) Optimize the installation page (go-gitea#32994) [Feature] Private README.md for organization (go-gitea#32872) Make issue suggestion work for new PR page (go-gitea#33035) Add IntelliJ Gateway's .uuid to gitignore (go-gitea#33052)
2 parents 8aaec8e + 2852708 commit 9754baf

File tree

116 files changed

+1534
-980
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+1534
-980
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ _test
99

1010
# IntelliJ
1111
.idea
12+
13+
# IntelliJ Gateway
14+
.uuid
15+
1216
# Goland's output filename can not be set manually
1317
/go_build_*
1418
/gitea_*

cmd/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ func NewMainApp(appVer AppVersion) *cli.App {
165165
app.Commands = append(app.Commands, subCmdWithConfig...)
166166
app.Commands = append(app.Commands, subCmdStandalone...)
167167

168+
setting.InitGiteaEnvVars()
168169
return app
169170
}
170171

models/db/name.go

+6-13
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@ package db
55

66
import (
77
"fmt"
8-
"regexp"
98
"strings"
109
"unicode/utf8"
1110

1211
"code.gitea.io/gitea/modules/util"
1312
)
1413

15-
var (
16-
// ErrNameEmpty name is empty error
17-
ErrNameEmpty = util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument}
18-
19-
// AlphaDashDotPattern characters prohibited in a username (anything except A-Za-z0-9_.-)
20-
AlphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
21-
)
14+
var ErrNameEmpty = util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument}
2215

2316
// ErrNameReserved represents a "reserved name" error.
2417
type ErrNameReserved struct {
@@ -82,20 +75,20 @@ func (err ErrNameCharsNotAllowed) Unwrap() error {
8275

8376
// IsUsableName checks if name is reserved or pattern of name is not allowed
8477
// based on given reserved names and patterns.
85-
// Names are exact match, patterns can be prefix or suffix match with placeholder '*'.
86-
func IsUsableName(names, patterns []string, name string) error {
78+
// Names are exact match, patterns can be a prefix or suffix match with placeholder '*'.
79+
func IsUsableName(reservedNames, reservedPatterns []string, name string) error {
8780
name = strings.TrimSpace(strings.ToLower(name))
8881
if utf8.RuneCountInString(name) == 0 {
8982
return ErrNameEmpty
9083
}
9184

92-
for i := range names {
93-
if name == names[i] {
85+
for i := range reservedNames {
86+
if name == reservedNames[i] {
9487
return ErrNameReserved{name}
9588
}
9689
}
9790

98-
for _, pat := range patterns {
91+
for _, pat := range reservedPatterns {
9992
if pat[0] == '*' && strings.HasSuffix(name, pat[1:]) ||
10093
(pat[len(pat)-1] == '*' && strings.HasPrefix(name, pat[:len(pat)-1])) {
10194
return ErrNamePatternNotAllowed{pat}

models/packages/package.go

+12
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,18 @@ func GetPackageByID(ctx context.Context, packageID int64) (*Package, error) {
248248
return p, nil
249249
}
250250

251+
// UpdatePackageNameByID updates the package's name, it is only for internal usage, for example: rename some legacy packages
252+
func UpdatePackageNameByID(ctx context.Context, ownerID int64, packageType Type, packageID int64, name string) error {
253+
var cond builder.Cond = builder.Eq{
254+
"package.id": packageID,
255+
"package.owner_id": ownerID,
256+
"package.type": packageType,
257+
"package.is_internal": false,
258+
}
259+
_, err := db.GetEngine(ctx).Where(cond).Update(&Package{Name: name, LowerName: strings.ToLower(name)})
260+
return err
261+
}
262+
251263
// GetPackageByName gets a package by name
252264
func GetPackageByName(ctx context.Context, ownerID int64, packageType Type, name string) (*Package, error) {
253265
var cond builder.Cond = builder.Eq{

models/project/project.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ func (p *Project) LoadRepo(ctx context.Context) (err error) {
126126
return err
127127
}
128128

129+
func ProjectLinkForOrg(org *user_model.User, projectID int64) string { //nolint
130+
return fmt.Sprintf("%s/-/projects/%d", org.HomeLink(), projectID)
131+
}
132+
133+
func ProjectLinkForRepo(repo *repo_model.Repository, projectID int64) string { //nolint
134+
return fmt.Sprintf("%s/projects/%d", repo.Link(), projectID)
135+
}
136+
129137
// Link returns the project's relative URL.
130138
func (p *Project) Link(ctx context.Context) string {
131139
if p.OwnerID > 0 {
@@ -134,15 +142,15 @@ func (p *Project) Link(ctx context.Context) string {
134142
log.Error("LoadOwner: %v", err)
135143
return ""
136144
}
137-
return fmt.Sprintf("%s/-/projects/%d", p.Owner.HomeLink(), p.ID)
145+
return ProjectLinkForOrg(p.Owner, p.ID)
138146
}
139147
if p.RepoID > 0 {
140148
err := p.LoadRepo(ctx)
141149
if err != nil {
142150
log.Error("LoadRepo: %v", err)
143151
return ""
144152
}
145-
return fmt.Sprintf("%s/projects/%d", p.Repo.Link(), p.ID)
153+
return ProjectLinkForRepo(p.Repo, p.ID)
146154
}
147155
return ""
148156
}

models/repo/repo.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net"
1212
"net/url"
1313
"path/filepath"
14+
"regexp"
1415
"strconv"
1516
"strings"
1617

@@ -60,13 +61,15 @@ func (err ErrRepoIsArchived) Error() string {
6061
}
6162

6263
var (
63-
reservedRepoNames = []string{".", "..", "-"}
64-
reservedRepoPatterns = []string{"*.git", "*.wiki", "*.rss", "*.atom"}
64+
validRepoNamePattern = regexp.MustCompile(`[-.\w]+`)
65+
invalidRepoNamePattern = regexp.MustCompile(`[.]{2,}`)
66+
reservedRepoNames = []string{".", "..", "-"}
67+
reservedRepoPatterns = []string{"*.git", "*.wiki", "*.rss", "*.atom"}
6568
)
6669

67-
// IsUsableRepoName returns true when repository is usable
70+
// IsUsableRepoName returns true when name is usable
6871
func IsUsableRepoName(name string) error {
69-
if db.AlphaDashDotPattern.MatchString(name) {
72+
if !validRepoNamePattern.MatchString(name) || invalidRepoNamePattern.MatchString(name) {
7073
// Note: usually this error is normally caught up earlier in the UI
7174
return db.ErrNameCharsNotAllowed{Name: name}
7275
}

models/repo/repo_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,15 @@ func TestComposeSSHCloneURL(t *testing.T) {
217217
setting.SSH.Port = 123
218218
assert.Equal(t, "ssh://git@[::1]:123/user/repo.git", ComposeSSHCloneURL("user", "repo"))
219219
}
220+
221+
func TestIsUsableRepoName(t *testing.T) {
222+
assert.NoError(t, IsUsableRepoName("a"))
223+
assert.NoError(t, IsUsableRepoName("-1_."))
224+
assert.NoError(t, IsUsableRepoName(".profile"))
225+
226+
assert.Error(t, IsUsableRepoName("-"))
227+
assert.Error(t, IsUsableRepoName("🌞"))
228+
assert.Error(t, IsUsableRepoName("the..repo"))
229+
assert.Error(t, IsUsableRepoName("foo.wiki"))
230+
assert.Error(t, IsUsableRepoName("foo.git"))
231+
}

models/unittest/fscopy.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func SyncDirs(srcPath, destPath string) error {
6767
}
6868

6969
// find and delete all untracked files
70-
destFiles, err := util.StatDir(destPath, true)
70+
destFiles, err := util.ListDirRecursively(destPath, &util.ListDirOptions{IncludeDir: true})
7171
if err != nil {
7272
return err
7373
}
@@ -86,13 +86,13 @@ func SyncDirs(srcPath, destPath string) error {
8686
}
8787

8888
// sync src files to dest
89-
srcFiles, err := util.StatDir(srcPath, true)
89+
srcFiles, err := util.ListDirRecursively(srcPath, &util.ListDirOptions{IncludeDir: true})
9090
if err != nil {
9191
return err
9292
}
9393
for _, srcFile := range srcFiles {
9494
destFilePath := filepath.Join(destPath, srcFile)
95-
// util.StatDir appends a slash to the directory name
95+
// util.ListDirRecursively appends a slash to the directory name
9696
if strings.HasSuffix(srcFile, "/") {
9797
err = os.MkdirAll(destFilePath, os.ModePerm)
9898
} else {

models/unittest/testdb.go

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func InitSettings() {
5959
_ = hash.Register("dummy", hash.NewDummyHasher)
6060

6161
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
62+
setting.InitGiteaEnvVars()
6263
}
6364

6465
// TestOptions represents test options

modules/assetfs/layered.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (l *LayeredFS) ReadLayeredFile(elems ...string) ([]byte, string, error) {
103103
}
104104

105105
func shouldInclude(info fs.FileInfo, fileMode ...bool) bool {
106-
if util.CommonSkip(info.Name()) {
106+
if util.IsCommonHiddenFileName(info.Name()) {
107107
return false
108108
}
109109
if len(fileMode) == 0 {

modules/git/batch_reader.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,15 @@ func BinToHex(objectFormat ObjectFormat, sha, out []byte) []byte {
242242
return out
243243
}
244244

245-
// ParseTreeLine reads an entry from a tree in a cat-file --batch stream
245+
// ParseCatFileTreeLine reads an entry from a tree in a cat-file --batch stream
246246
// This carefully avoids allocations - except where fnameBuf is too small.
247247
// It is recommended therefore to pass in an fnameBuf large enough to avoid almost all allocations
248248
//
249249
// Each line is composed of:
250250
// <mode-in-ascii-dropping-initial-zeros> SP <fname> NUL <binary HASH>
251251
//
252252
// We don't attempt to convert the raw HASH to save a lot of time
253-
func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fname, sha []byte, n int, err error) {
253+
func ParseCatFileTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fname, sha []byte, n int, err error) {
254254
var readBytes []byte
255255

256256
// Read the Mode & fname
@@ -260,7 +260,7 @@ func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBu
260260
}
261261
idx := bytes.IndexByte(readBytes, ' ')
262262
if idx < 0 {
263-
log.Debug("missing space in readBytes ParseTreeLine: %s", readBytes)
263+
log.Debug("missing space in readBytes ParseCatFileTreeLine: %s", readBytes)
264264
return mode, fname, sha, n, &ErrNotExist{}
265265
}
266266

modules/git/parse.go

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"bytes"
8+
"fmt"
9+
"strconv"
10+
"strings"
11+
12+
"code.gitea.io/gitea/modules/optional"
13+
)
14+
15+
var sepSpace = []byte{' '}
16+
17+
type LsTreeEntry struct {
18+
ID ObjectID
19+
EntryMode EntryMode
20+
Name string
21+
Size optional.Option[int64]
22+
}
23+
24+
func parseLsTreeLine(line []byte) (*LsTreeEntry, error) {
25+
// expect line to be of the form:
26+
// <mode> <type> <sha> <space-padded-size>\t<filename>
27+
// <mode> <type> <sha>\t<filename>
28+
29+
var err error
30+
posTab := bytes.IndexByte(line, '\t')
31+
if posTab == -1 {
32+
return nil, fmt.Errorf("invalid ls-tree output (no tab): %q", line)
33+
}
34+
35+
entry := new(LsTreeEntry)
36+
37+
entryAttrs := line[:posTab]
38+
entryName := line[posTab+1:]
39+
40+
entryMode, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
41+
_ /* entryType */, entryAttrs, _ = bytes.Cut(entryAttrs, sepSpace) // the type is not used, the mode is enough to determine the type
42+
entryObjectID, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
43+
if len(entryAttrs) > 0 {
44+
entrySize := entryAttrs // the last field is the space-padded-size
45+
size, _ := strconv.ParseInt(strings.TrimSpace(string(entrySize)), 10, 64)
46+
entry.Size = optional.Some(size)
47+
}
48+
49+
switch string(entryMode) {
50+
case "100644":
51+
entry.EntryMode = EntryModeBlob
52+
case "100755":
53+
entry.EntryMode = EntryModeExec
54+
case "120000":
55+
entry.EntryMode = EntryModeSymlink
56+
case "160000":
57+
entry.EntryMode = EntryModeCommit
58+
case "040000", "040755": // git uses 040000 for tree object, but some users may get 040755 for unknown reasons
59+
entry.EntryMode = EntryModeTree
60+
default:
61+
return nil, fmt.Errorf("unknown type: %v", string(entryMode))
62+
}
63+
64+
entry.ID, err = NewIDFromString(string(entryObjectID))
65+
if err != nil {
66+
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
67+
}
68+
69+
if len(entryName) > 0 && entryName[0] == '"' {
70+
entry.Name, err = strconv.Unquote(string(entryName))
71+
if err != nil {
72+
return nil, fmt.Errorf("invalid ls-tree output (invalid name): %q, err: %w", line, err)
73+
}
74+
} else {
75+
entry.Name = string(entryName)
76+
}
77+
return entry, nil
78+
}

0 commit comments

Comments
 (0)