Skip to content

Commit 3700af0

Browse files
authored
Merge branch 'main' into lunny/milestone_filter
2 parents b13c0ed + 0536712 commit 3700af0

Some content is hidden

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

75 files changed

+395
-433
lines changed

cmd/dump.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
112112
Name: "verbose, V",
113113
Usage: "Show process details",
114114
},
115+
cli.BoolFlag{
116+
Name: "quiet, q",
117+
Usage: "Only display warnings and errors",
118+
},
115119
cli.StringFlag{
116120
Name: "tempdir, t",
117121
Value: os.TempDir(),
@@ -192,12 +196,25 @@ func runDump(ctx *cli.Context) error {
192196
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
193197
fatal("Setting console logger to stderr failed: %v", err)
194198
}
199+
200+
// Set loglevel to Warn if quiet-mode is requested
201+
if ctx.Bool("quiet") {
202+
if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil {
203+
fatal("Setting console log-level failed: %v", err)
204+
}
205+
}
206+
195207
if !setting.InstallLock {
196208
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
197209
return fmt.Errorf("gitea is not initialized")
198210
}
199211
setting.LoadSettings() // cannot access session settings otherwise
200212

213+
verbose := ctx.Bool("verbose")
214+
if verbose && ctx.Bool("quiet") {
215+
return fmt.Errorf("--quiet and --verbose cannot both be set")
216+
}
217+
201218
stdCtx, cancel := installSignals()
202219
defer cancel()
203220

@@ -223,7 +240,6 @@ func runDump(ctx *cli.Context) error {
223240
return err
224241
}
225242

226-
verbose := ctx.Bool("verbose")
227243
var iface interface{}
228244
if fileName == "-" {
229245
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))

custom/conf/app.example.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ RUN_MODE = ; prod
186186
;; default is the system temporary directory.
187187
;SSH_KEY_TEST_PATH =
188188
;;
189-
;; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
190-
;SSH_KEYGEN_PATH = ssh-keygen
189+
;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
190+
;SSH_KEYGEN_PATH =
191191
;;
192192
;; Enable SSH Authorized Key Backup when rewriting all keys, default is true
193193
;SSH_AUTHORIZED_KEYS_BACKUP = true

docs/content/doc/administration/config-cheat-sheet.en-us.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
345345
- `SSH_SERVER_MACS`: **[email protected], hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
346346
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you.
347347
- `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory.
348-
- `SSH_KEYGEN_PATH`: **ssh-keygen**: Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
348+
- `SSH_KEYGEN_PATH`: **\<empty\>**: Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
349349
- `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false.
350350
- `SSH_PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the SSH connections. (Set to
351351
-1 to disable all timeouts.)

docs/content/doc/help/faq.en-us.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ The correct path for the template(s) will be relative to the `CustomPath`
118118
2. If you are still unable to find a path, the default can be [calculated above](#where-does-gitea-store-what-file)
119119
3. Once you have figured out the correct custom path, you can refer to the [customizing Gitea]({{< relref "doc/administration/customizing-gitea.en-us.md" >}}) page to add your template to the correct location.
120120

121+
## Does Gitea have a "GitHub/GitLab pages" feature?
122+
123+
Gitea doesn't provide a built-in Pages server. You need a dedicated domain to serve static pages to avoid CSRF security risks.
124+
125+
For simple usage, you can use a reverse proxy to rewrite & serve static contents from Gitea's raw file URLs.
126+
127+
And there are already available third-party services, like a standalone [pages server](https://codeberg.org/Codeberg/pages-server) or a [caddy plugin](https://github.com/42wim/caddy-gitea), that can provide the required functionality.
128+
121129
## Active user vs login prohibited user
122130

123131
In Gitea, an "active" user refers to a user that has activated their account via email.

docs/content/doc/installation/comparison.en-us.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ _Symbols used in table:_
3131

3232
- _✘ - unsupported_
3333

34+
- _⚙️ - supported through third-party software_
35+
3436
## General Features
3537

3638
| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
@@ -51,7 +53,7 @@ _Symbols used in table:_
5153
| Custom Theme Support ||||||||
5254
| Markdown support ||||||||
5355
| CSV support ||||||| ? |
54-
| 'GitHub / GitLab pages' | [](https://github.com/go-gitea/gitea/issues/302) |||||||
56+
| 'GitHub / GitLab pages' | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] |||||||
5557
| Repo-specific wiki (as a repo itself) |||||| / ||
5658
| Deploy Tokens ||||||||
5759
| Repository Tokens with write rights ||||||||
@@ -144,3 +146,6 @@ _Symbols used in table:_
144146
| Two factor authentication (2FA) ||||||||
145147
| Integration with the most common services || / ||||||
146148
| Incorporate external CI/CD ||||||||
149+
150+
[gitea-caddy-plugin]: https://github.com/42wim/caddy-gitea
151+
[gitea-pages-server]: https://codeberg.org/Codeberg/pages-server

docs/content/doc/installation/comparison.zh-cn.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ _表格中的符号含义:_
2929

3030
* _? - 不确定_
3131

32+
* _⚙️ - 由第三方服务或插件支持_
33+
3234
#### 主要特性
3335

3436
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
@@ -42,7 +44,7 @@ _表格中的符号含义:_
4244
| 支持 Orgmode ||||||| ? |
4345
| 支持 CSV ||||||| ? |
4446
| 支持第三方渲染工具 ||||||| ? |
45-
| Git 驱动的静态 pages | [](https://github.com/go-gitea/gitea/issues/302) |||||||
47+
| Git 驱动的静态 pages | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] |||||||
4648
| Git 驱动的集成化 wiki |||||| ✓ (cloud only) ||
4749
| 部署令牌 ||||||||
4850
| 仓库写权限令牌 ||||||||
@@ -129,3 +131,6 @@ _表格中的符号含义:_
129131
| 集成 Discord ||||||||
130132
| 集成 Microsoft Teams ||||||||
131133
| 显示外部 CI/CD 的状态 ||||||||
134+
135+
[gitea-caddy-plugin]: https://github.com/42wim/caddy-gitea
136+
[gitea-pages-server]: https://codeberg.org/Codeberg/pages-server

docs/content/doc/installation/comparison.zh-tw.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ menu:
3131

3232
- ✘ - 不支援
3333

34+
- _⚙️ - 由第三方服務或外掛程式支援_
35+
3436
## 一般功能
3537

3638
| 功能 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
@@ -44,7 +46,7 @@ menu:
4446
| 支援 Orgmode ||||||| ? |
4547
| 支援 CSV ||||||| ? |
4648
| 支援第三方渲染工具 ||||||| ? |
47-
| Git 驅動的靜態頁面 | [](https://github.com/go-gitea/gitea/issues/302) |||||||
49+
| Git 驅動的靜態頁面 | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] |||||||
4850
| Git 驅動的整合 wiki ||||||||
4951
| 部署 Token ||||||||
5052
| 有寫入權限的儲存庫 Token ||||||||
@@ -130,3 +132,6 @@ menu:
130132
| 整合 Discord ||||||||
131133
| 整合 Microsoft Teams ||||||||
132134
| 顯示外部 CI/CD 狀態 ||||||||
135+
136+
[gitea-caddy-plugin]: https://github.com/42wim/caddy-gitea
137+
[gitea-pages-server]: https://codeberg.org/Codeberg/pages-server

models/asymkey/ssh_key_parse.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"strconv"
1717
"strings"
1818

19-
"code.gitea.io/gitea/models/db"
2019
"code.gitea.io/gitea/modules/log"
2120
"code.gitea.io/gitea/modules/process"
2221
"code.gitea.io/gitea/modules/setting"
@@ -158,10 +157,6 @@ func parseKeyString(content string) (string, error) {
158157
// CheckPublicKeyString checks if the given public key string is recognized by SSH.
159158
// It returns the actual public key line on success.
160159
func CheckPublicKeyString(content string) (_ string, err error) {
161-
if setting.SSH.Disabled {
162-
return "", db.ErrSSHDisabled{}
163-
}
164-
165160
content, err = parseKeyString(content)
166161
if err != nil {
167162
return "", err
@@ -184,7 +179,7 @@ func CheckPublicKeyString(content string) (_ string, err error) {
184179
keyType string
185180
length int
186181
)
187-
if setting.SSH.StartBuiltinServer {
182+
if len(setting.SSH.KeygenPath) == 0 {
188183
fnName = "SSHNativeParsePublicKey"
189184
keyType, length, err = SSHNativeParsePublicKey(content)
190185
} else {
@@ -290,7 +285,12 @@ func SSHKeyGenParsePublicKey(key string) (string, int, error) {
290285
}
291286
}()
292287

293-
stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName)
288+
keygenPath := setting.SSH.KeygenPath
289+
if len(keygenPath) == 0 {
290+
keygenPath = "ssh-keygen"
291+
}
292+
293+
stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", keygenPath, "-lf", tmpName)
294294
if err != nil {
295295
return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr)
296296
}

models/asymkey/ssh_key_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ func Test_SSHParsePublicKey(t *testing.T) {
5757
assert.Equal(t, tc.keyType, keyTypeK)
5858
assert.EqualValues(t, tc.length, lengthK)
5959
})
60+
t.Run("SSHParseKeyNative", func(t *testing.T) {
61+
keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content)
62+
if err != nil {
63+
assert.Fail(t, "%v", err)
64+
}
65+
assert.Equal(t, tc.keyType, keyTypeK)
66+
assert.EqualValues(t, tc.length, lengthK)
67+
})
6068
})
6169
}
6270
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestBranchRuleMatchPriority(t *testing.T) {
14+
kases := []struct {
15+
Rules []string
16+
BranchName string
17+
ExpectedMatchIdx int
18+
}{
19+
{
20+
Rules: []string{"release/*", "release/v1.17"},
21+
BranchName: "release/v1.17",
22+
ExpectedMatchIdx: 1,
23+
},
24+
{
25+
Rules: []string{"release/v1.17", "release/*"},
26+
BranchName: "release/v1.17",
27+
ExpectedMatchIdx: 0,
28+
},
29+
{
30+
Rules: []string{"release/**/v1.17", "release/test/v1.17"},
31+
BranchName: "release/test/v1.17",
32+
ExpectedMatchIdx: 1,
33+
},
34+
{
35+
Rules: []string{"release/test/v1.17", "release/**/v1.17"},
36+
BranchName: "release/test/v1.17",
37+
ExpectedMatchIdx: 0,
38+
},
39+
{
40+
Rules: []string{"release/**", "release/v1.0.0"},
41+
BranchName: "release/v1.0.0",
42+
ExpectedMatchIdx: 1,
43+
},
44+
{
45+
Rules: []string{"release/v1.0.0", "release/**"},
46+
BranchName: "release/v1.0.0",
47+
ExpectedMatchIdx: 0,
48+
},
49+
{
50+
Rules: []string{"release/**", "release/v1.0.0"},
51+
BranchName: "release/v2.0.0",
52+
ExpectedMatchIdx: 0,
53+
},
54+
{
55+
Rules: []string{"release/*", "release/v1.0.0"},
56+
BranchName: "release/1/v2.0.0",
57+
ExpectedMatchIdx: -1,
58+
},
59+
}
60+
61+
for _, kase := range kases {
62+
var pbs ProtectedBranchRules
63+
for _, rule := range kase.Rules {
64+
pbs = append(pbs, &ProtectedBranch{RuleName: rule})
65+
}
66+
pbs.sort()
67+
matchedPB := pbs.GetFirstMatched(kase.BranchName)
68+
if matchedPB == nil {
69+
if kase.ExpectedMatchIdx >= 0 {
70+
assert.Error(t, fmt.Errorf("no matched rules but expected %s[%d]", kase.Rules[kase.ExpectedMatchIdx], kase.ExpectedMatchIdx))
71+
}
72+
} else {
73+
assert.EqualValues(t, kase.Rules[kase.ExpectedMatchIdx], matchedPB.RuleName)
74+
}
75+
}
76+
}

models/git/protected_branch_list.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,8 @@ func (rules ProtectedBranchRules) sort() {
2828
sort.Slice(rules, func(i, j int) bool {
2929
rules[i].loadGlob()
3030
rules[j].loadGlob()
31-
if rules[i].isPlainName {
32-
if !rules[j].isPlainName {
33-
return true
34-
}
35-
} else if rules[j].isPlainName {
36-
return true
31+
if rules[i].isPlainName != rules[j].isPlainName {
32+
return rules[i].isPlainName // plain name comes first, so plain name means "less"
3733
}
3834
return rules[i].CreatedUnix < rules[j].CreatedUnix
3935
})
@@ -46,7 +42,7 @@ func FindRepoProtectedBranchRules(ctx context.Context, repoID int64) (ProtectedB
4642
if err != nil {
4743
return nil, err
4844
}
49-
rules.sort()
45+
rules.sort() // to make non-glob rules have higher priority, and for same glob/non-glob rules, first created rules have higher priority
5046
return rules, nil
5147
}
5248

models/user/user.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,8 @@ var (
537537
"gitea-actions",
538538
}
539539

540-
reservedUserPatterns = []string{"*.keys", "*.gpg", "*.rss", "*.atom"}
540+
// DON'T ADD ANY NEW STUFF, WE SOLVE THIS WITH `/user/{obj}` PATHS!
541+
reservedUserPatterns = []string{"*.keys", "*.gpg", "*.rss", "*.atom", "*.png"}
541542
)
542543

543544
// IsUsableUsername returns an error when a username is reserved

modules/setting/ssh.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ var SSH = struct {
5858
ServerCiphers: []string{"[email protected]", "aes128-ctr", "aes192-ctr", "aes256-ctr", "[email protected]", "[email protected]"},
5959
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
6060
ServerMACs: []string{"[email protected]", "hmac-sha2-256", "hmac-sha1"},
61-
KeygenPath: "ssh-keygen",
61+
KeygenPath: "",
6262
MinimumKeySizeCheck: true,
6363
MinimumKeySizes: map[string]int{"ed25519": 256, "ed25519-sk": 256, "ecdsa": 256, "ecdsa-sk": 256, "rsa": 2047},
6464
ServerHostKeys: []string{"ssh/gitea.rsa", "ssh/gogs.rsa"},
@@ -134,7 +134,7 @@ func loadSSHFrom(rootCfg ConfigProvider) {
134134
}
135135
}
136136

137-
SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").MustString("ssh-keygen")
137+
SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").String()
138138
SSH.Port = sec.Key("SSH_PORT").MustInt(22)
139139
SSH.ListenPort = sec.Key("SSH_LISTEN_PORT").MustInt(SSH.Port)
140140
SSH.UseProxyProtocol = sec.Key("SSH_SERVER_USE_PROXY_PROTOCOL").MustBool(false)

modules/templates/helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func NewFuncMap() []template.FuncMap {
138138
"TimeSinceUnix": timeutil.TimeSinceUnix,
139139
"Sec2Time": util.SecToTime,
140140
"DateFmtLong": func(t time.Time) string {
141-
return t.Format(time.RFC1123Z)
141+
return t.Format(time.RFC3339)
142142
},
143143
"LoadTimes": func(startTime time.Time) string {
144144
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"

0 commit comments

Comments
 (0)