0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-07-17 17:32:56 +02:00

Merge branch 'main' into prometheus-reorganization

This commit is contained in:
TheFox0x7 2025-07-08 13:53:52 +02:00
commit ac9d6afe00
No known key found for this signature in database
GPG Key ID: 6CA33903484AF7C2
240 changed files with 2991 additions and 2738 deletions

View File

@ -91,6 +91,7 @@ module.exports = {
plugins: ['@vitest/eslint-plugin'], plugins: ['@vitest/eslint-plugin'],
globals: vitestPlugin.environments.env.globals, globals: vitestPlugin.environments.env.globals,
rules: { rules: {
'github/unescaped-html-literal': [0],
'@vitest/consistent-test-filename': [0], '@vitest/consistent-test-filename': [0],
'@vitest/consistent-test-it': [0], '@vitest/consistent-test-it': [0],
'@vitest/expect-expect': [0], '@vitest/expect-expect': [0],
@ -423,7 +424,7 @@ module.exports = {
'github/no-useless-passive': [2], 'github/no-useless-passive': [2],
'github/prefer-observers': [2], 'github/prefer-observers': [2],
'github/require-passive-events': [2], 'github/require-passive-events': [2],
'github/unescaped-html-literal': [0], 'github/unescaped-html-literal': [2],
'grouped-accessor-pairs': [2], 'grouped-accessor-pairs': [2],
'guard-for-in': [0], 'guard-for-in': [0],
'id-blacklist': [0], 'id-blacklist': [0],

View File

@ -50,6 +50,8 @@ linters:
require-explanation: true require-explanation: true
require-specific: true require-specific: true
gocritic: gocritic:
enabled-checks:
- equalFold
disabled-checks: disabled-checks:
- ifElseChain - ifElseChain
- singleCaseSwitch # Every time this occurred in the code, there was no other way. - singleCaseSwitch # Every time this occurred in the code, there was no other way.

View File

@ -30,7 +30,7 @@ These are the values to which people in the Gitea community should aspire.
- **Be constructive.** - **Be constructive.**
- Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation. - Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
- Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved. - Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
- Avoid snarking (pithy, unproductive, sniping comments) - Avoid snarking (pithy, unproductive, sniping comments).
- Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict. - Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
- Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group). - Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
- **Be responsible.** - **Be responsible.**
@ -42,7 +42,7 @@ People are complicated. You should expect to be misunderstood and to misundersta
### Our Pledge ### Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
### Our Standards ### Our Standards

View File

@ -80,9 +80,9 @@ Expected workflow is: Fork -> Patch -> Push -> Pull Request
[![Crowdin](https://badges.crowdin.net/gitea/localized.svg)](https://translate.gitea.com) [![Crowdin](https://badges.crowdin.net/gitea/localized.svg)](https://translate.gitea.com)
Translations are done through [Crowdin](https://translate.gitea.com). If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there. Translations are done through [Crowdin](https://translate.gitea.com). If you want to translate to a new language, ask one of the managers in the Crowdin project to add a new language there.
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up. You can also just create an issue for adding a language or ask on Discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty, but we hope to fill it as questions pop up.
Get more information from [documentation](https://docs.gitea.com/contributing/localization). Get more information from [documentation](https://docs.gitea.com/contributing/localization).

View File

@ -14,12 +14,12 @@ Please **DO NOT** file a public issue, instead send your report privately to `se
Due to the sensitive nature of security information, you can use the below GPG public key to encrypt your mail body. Due to the sensitive nature of security information, you can use the below GPG public key to encrypt your mail body.
The PGP key is valid until July 9, 2025. The PGP key is valid until July 4, 2026.
``` ```
Key ID: 6FCD2D5B Key ID: 6FCD2D5B
Key Type: RSA Key Type: RSA
Expires: 7/9/2025 Expires: 7/4/2026
Key Size: 4096/4096 Key Size: 4096/4096
Fingerprint: 3DE0 3D1E 144A 7F06 9359 99DC AAFD 2381 6FCD 2D5B Fingerprint: 3DE0 3D1E 144A 7F06 9359 99DC AAFD 2381 6FCD 2D5B
``` ```
@ -42,18 +42,18 @@ lzpAjnN9/KLtQroutrm+Ft0mdjDiJUeFVl1cOHDhoyfCsQh62HumoyZoZvqzQd6e
AbN11nq6aViMe2Q3je1AbiBnRnQSHxt1Tc8X4IshO3MQK1Sk7oPI6LA5oQARAQAB AbN11nq6aViMe2Q3je1AbiBnRnQSHxt1Tc8X4IshO3MQK1Sk7oPI6LA5oQARAQAB
tCJHaXRlYSBTZWN1cml0eSA8c2VjdXJpdHlAZ2l0ZWEuaW8+iQJXBBMBCABBAhsD tCJHaXRlYSBTZWN1cml0eSA8c2VjdXJpdHlAZ2l0ZWEuaW8+iQJXBBMBCABBAhsD
BQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAFiEEPeA9HhRKfwaTWZncqv0jgW/N BQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAFiEEPeA9HhRKfwaTWZncqv0jgW/N
LVsFAmaMse0FCQW4fW8ACgkQqv0jgW/NLVtXLg/+PF4G9Jhlui15BTNlEBJAV2P/ LVsFAmhoHmkFCQeT6esACgkQqv0jgW/NLVuFLRAAmjBQSKRAgs2bFIEj7HLAbDp4
1QlAV2krk0fP7tykn0FR9RfGIfVV/kwC1f+ouosYPQDDevl9LWdUIM+g94DtNo2o f+XkdH+GsT3jRPOZ9QZgmtM+TfoE4yNgIVfOl+s4RdjM/W4QzqZuPQ55hbEHd056
7ACpcL3morvt5lVGpIZHL8TbX0qmFRXL/pB/cB+K6IwYvh2mrbp2zH+r4SCRyFYq cJmm7B+6GsHFcdrPmh65sOCEIyh4+t45dUfeWpFsDPqm9j1UHXAJQIpB8vDEVAPH
BjgXYFTI1MylJ1ShAjU6Z+m3oJ+2xs5LzHS0X6zkTjzA2Zl4zQzciQ9T+wJcE7Zi t+3wLCk8GMPJs1o5tIyMmaO23ngvkwn8eG7KgY+rp2PzObrb5g7ppci0ILzILkrp
HXdM1+YMF8KGNP8J9Rpug5oNDJ98lgZirRY7c3A/1xmYBiPnULwuuymdqEZO7l70 HVjZsEfUWRgSVF7LuU5ppqDKrlcqwUpQq6n3kGMZcLrCp6ACKP04TBmTfUxNwdL7
SeAlE1RWYX8kbOBnBb/KY4XwE3Vic1oEzc9DiPWVH1ElX86WNNsFzuyULiwoBoWg I0N7apI2Pbct9T1Gv/lYAUFWyU2c3gh/EBLbO6BukaLOFRQHrtNfdJV/YnMPlcXr
pqZGhL9x1p5+46RGQSDczsHM7YGVtfYOiDo2PAVrmwsT0BnXnK8Oe3YIkvmUPEJu LUJjK9K4eAH9DsrZqrisz/LthsC2BaNIN3KRMTk5YTYgmIh8GXzSgihORmtDFELC
OkLt0Z6A5n8pz8zhQzuApwBsK4ncJ8zTCpvz/pfKKqZC/Vnoh3gKGhDGvOZ+b5IJ RroID3pTuS0zjXh+wpY9GuPTh7UW23p42Daxca4fAT4k5EclvDRUrL21xMopPMiL
0kUTe2JsbnwFixDUMDtacQ1op8XOyLoLVmgqLn0+Pws4XPBlMof2bioFir3yHKnP HuNdELz4FVchRTy05PjzKVyjVInDNojE2KUxnjxZDzYJ6aT/g+coD5yfntYm8BEj
gNchsF1agrlSIo5GA8u4ga+IlCSfvFIKrl7+cxacKcJYt/vbOU5KcvVJI5EtHKCG +ZzL0ndZES54hzKLpv7zwBQwFzam68clZYmDPILOPTflQDfpGEWmJK4undFU5obz
xfHjHY2ah1Qww7SxW6IXiRZZzPpsL2mBM2CD7N3qh9bV2s27wxYCdUodsIZbiyHe ZsQRz0R3ulspChATbZxO0d5LX2obLpKO9X3b5VoO1KF+R8Vjw1Y0KxrNZ6rIcfqH
oWPzfBnkmiAN8KlZxHm5Ag0EYrVn/gEQALrFLQjCR3GjuHSindz0rd3Fnx/t7Sen Z50QVQKSe9dm08K0ON+5Ag0EYrVn/gEQALrFLQjCR3GjuHSindz0rd3Fnx/t7Sen
T+p07yCSSoSlmnJHCQmwh4vfg1blyz0zZ4vkIhtpHsEgc+ZAG+WQXSsJ2iRz+eSN T+p07yCSSoSlmnJHCQmwh4vfg1blyz0zZ4vkIhtpHsEgc+ZAG+WQXSsJ2iRz+eSN
GwoOQl4XC3n+QWkc1ws+btr48+6UqXIQU+F8TPQyx/PIgi2nZXJB7f5+mjCqsk46 GwoOQl4XC3n+QWkc1ws+btr48+6UqXIQU+F8TPQyx/PIgi2nZXJB7f5+mjCqsk46
XvH4nTr4kJjuqMSR/++wvre2qNQRa/q/dTsK0OaN/mJsdX6Oi+aGNaQJUhIG7F+E XvH4nTr4kJjuqMSR/++wvre2qNQRa/q/dTsK0OaN/mJsdX6Oi+aGNaQJUhIG7F+E
@ -65,19 +65,19 @@ s+GsP9I3cmWWQcKYxWHtE8xTXnNCVPFZQj2nwhJzae8ypfOtulBRA3dUKWGKuDH/
axFENhUsT397aOU3qkP/od4a64JyNIEo4CTTSPVeWd7njsGqli2U3A4xL2CcyYvt axFENhUsT397aOU3qkP/od4a64JyNIEo4CTTSPVeWd7njsGqli2U3A4xL2CcyYvt
D/MWcMBGEoLSNTswwKdom4FaJpn5KThnK/T0bQcmJblJhoCtppXisbexZnCpuS0x D/MWcMBGEoLSNTswwKdom4FaJpn5KThnK/T0bQcmJblJhoCtppXisbexZnCpuS0x
Zdlm2T14KJ3LABEBAAGJAjwEGAEIACYCGwwWIQQ94D0eFEp/BpNZmdyq/SOBb80t Zdlm2T14KJ3LABEBAAGJAjwEGAEIACYCGwwWIQQ94D0eFEp/BpNZmdyq/SOBb80t
WwUCZoyyjQUJBbh+DwAKCRCq/SOBb80tW18XD/9MXztmf01MT+1kZdBouZ/7Rp/7 WwUCaGgeJAUJB5PppgAKCRCq/SOBb80tW/NWEACB6Jrf0gWlk7e+hNCdnbM0ZVWU
9kuqo//B1G+RXau4oFtPqb67kNe2WaIc3u5B73PUHsMf3i6z4ib2KbMhZZerLn0O f2sHNFfXxxsdhpcDgKbNHtkZb8nZgv8AX+5fTtUwMVa3vKcdw30xFiIM5N7cCIPV
dRglcuPeNWmsASY3dH/XVG0cT0zvvWegagd12TJEl3Vs+7XNrOw4cwDj9L1+GH9m vg/5z5BtfEaitnabEUG2iiVDIy8IHXIcK10rX+7BosA3QDl2PsiBHwyi5G13lRk8
kSt4uaANWn/6a3RvMRhiVEYuNwhAzcKaactPmYqrLJgoVLbRSDkgyHaMQ2jKgLxk zGTSNDuOalug33h5/lr2dPigamkq74Aoy29q8Rjad6GfWHipL2bFimgtY+Zdi0BH
ifS/fvluGV0ub2Po6DJiqfRpd1tDvPhe9y1+r1WFDZsOcvTcZUfSt/7dXMGfqGu0 NLk4EJXxj1SgVx5dtkQzWJReBA5M+FQ4QYQZBO+f4TDoOLmjui152uhkoLBQbGAa
2daVFlfeSXSALrDE5uc0UxodHCpP3sqRYDZevGLBRaaTkIjYXG/+N898+7K5WJF4 WWJFTVxm0bG5MXloEL3gA8DfU7XDwuW/sHJC5pBko8RpQViooOhckMepZV3Y83DK
xXOLWxM2cwGkG7eC9pugcDnBp9XlF7O+GBiZ05JUe5flXDQFZ+h3exjopu6KHF1B bwLYa3JmPgj2rEv4993dvrJbQhpGd082HOxOsllCs8pgNq1SnXpWYfcGTgGKC3ts
RnzNy8LC0UKb+AuvRIOLV92a9Q9wGWU/jaVDu6nZ0umAeuSzxiHoDsonm0Fl9QAz U8YZUUJUQ7mi2L8Tv3ix20c9EiGmA30JAmA8eZTC3cWup91ZkkVBFRml2czTXajd
2/xCokebuoeLrEK7R2af3X86mqq3sVO4ax+HPYChzOaVQBiHUW/TAldWcldYYphR RWZ6GbHV5503ueDQcB8yBVgF3CSixs67+dGSbD3p86OqGrjAcJzM5TFbNKcnGLdE
/e2WsbmQfvCRtz/bZfo+aUVnrHNjzVMtF2SszdVmA/04Y8pS28MqtuRqhm5DPOOd kGbZpNwAISy750lXzXKmyrh5RTCeTOQerbwCMBvHZO+HAevA/LXDTw2OAiSIQlP5
g1YeUywK5jRZ1twyo1kzJEFPLaoeaXaycsR1PMVBW0Urik5mrR/pOWq7PPoZoKb2 sYA4sFYLQ30OAkgJcmdp/pSgVj/erNtSN07ClrOpDb/uFpQymO6K2h0Pst3feNVK
lXYLE8bwkuQTmsyL1g== 9M2VbqL9C51z/wyHLg==
=9i7d =SfZA
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
``` ```

View File

@ -715,7 +715,8 @@ func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository
return nil return nil
} }
func (c *Comment) loadReview(ctx context.Context) (err error) { // LoadReview loads the associated review
func (c *Comment) LoadReview(ctx context.Context) (err error) {
if c.ReviewID == 0 { if c.ReviewID == 0 {
return nil return nil
} }
@ -732,11 +733,6 @@ func (c *Comment) loadReview(ctx context.Context) (err error) {
return nil return nil
} }
// LoadReview loads the associated review
func (c *Comment) LoadReview(ctx context.Context) error {
return c.loadReview(ctx)
}
// DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes. // DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes.
func (c *Comment) DiffSide() string { func (c *Comment) DiffSide() string {
if c.Line < 0 { if c.Line < 0 {
@ -856,7 +852,7 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
} }
if comment.ReviewID != 0 { if comment.ReviewID != 0 {
if comment.Review == nil { if comment.Review == nil {
if err := comment.loadReview(ctx); err != nil { if err := comment.LoadReview(ctx); err != nil {
return err return err
} }
} }

View File

@ -37,6 +37,14 @@ type PackageVersion struct {
DownloadCount int64 `xorm:"NOT NULL DEFAULT 0"` DownloadCount int64 `xorm:"NOT NULL DEFAULT 0"`
} }
// IsPrerelease checks if the version is a prerelease version according to semantic versioning
func (pv *PackageVersion) IsPrerelease() bool {
if pv == nil || pv.Version == "" {
return false
}
return strings.Contains(pv.Version, "-")
}
// GetOrInsertVersion inserts a version. If the same version exist already ErrDuplicatePackageVersion is returned // GetOrInsertVersion inserts a version. If the same version exist already ErrDuplicatePackageVersion is returned
func GetOrInsertVersion(ctx context.Context, pv *PackageVersion) (*PackageVersion, error) { func GetOrInsertVersion(ctx context.Context, pv *PackageVersion) (*PackageVersion, error) {
e := db.GetEngine(ctx) e := db.GetEngine(ctx)

View File

@ -157,18 +157,17 @@ func UpdateLanguageStats(ctx context.Context, repo *Repository, commitID string,
for lang, size := range stats { for lang, size := range stats {
if size > s { if size > s {
s = size s = size
topLang = strings.ToLower(lang) topLang = lang
} }
} }
for lang, size := range stats { for lang, size := range stats {
upd := false upd := false
llang := strings.ToLower(lang)
for _, s := range oldstats { for _, s := range oldstats {
// Update already existing language // Update already existing language
if strings.ToLower(s.Language) == llang { if strings.EqualFold(s.Language, lang) {
s.CommitID = commitID s.CommitID = commitID
s.IsPrimary = llang == topLang s.IsPrimary = lang == topLang
s.Size = size s.Size = size
if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil { if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
return err return err
@ -182,7 +181,7 @@ func UpdateLanguageStats(ctx context.Context, repo *Repository, commitID string,
if err := db.Insert(ctx, &LanguageStat{ if err := db.Insert(ctx, &LanguageStat{
RepoID: repo.ID, RepoID: repo.ID,
CommitID: commitID, CommitID: commitID,
IsPrimary: llang == topLang, IsPrimary: lang == topLang,
Language: lang, Language: lang,
Size: size, Size: size,
}); err != nil { }); err != nil {

View File

@ -0,0 +1,47 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package httpauth
import (
"encoding/base64"
"strings"
"code.gitea.io/gitea/modules/util"
)
type BasicAuth struct {
Username, Password string
}
type BearerToken struct {
Token string
}
type ParsedAuthorizationHeader struct {
BasicAuth *BasicAuth
BearerToken *BearerToken
}
func ParseAuthorizationHeader(header string) (ret ParsedAuthorizationHeader, _ bool) {
parts := strings.Fields(header)
if len(parts) != 2 {
return ret, false
}
if util.AsciiEqualFold(parts[0], "basic") {
s, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return ret, false
}
u, p, ok := strings.Cut(string(s), ":")
if !ok {
return ret, false
}
ret.BasicAuth = &BasicAuth{Username: u, Password: p}
return ret, true
} else if util.AsciiEqualFold(parts[0], "token") || util.AsciiEqualFold(parts[0], "bearer") {
ret.BearerToken = &BearerToken{Token: parts[1]}
return ret, true
}
return ret, false
}

View File

@ -0,0 +1,43 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package httpauth
import (
"encoding/base64"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseAuthorizationHeader(t *testing.T) {
type parsed = ParsedAuthorizationHeader
type basic = BasicAuth
type bearer = BearerToken
cases := []struct {
headerValue string
expected parsed
ok bool
}{
{"", parsed{}, false},
{"?", parsed{}, false},
{"foo", parsed{}, false},
{"any value", parsed{}, false},
{"Basic ?", parsed{}, false},
{"Basic " + base64.StdEncoding.EncodeToString([]byte("foo")), parsed{}, false},
{"Basic " + base64.StdEncoding.EncodeToString([]byte("foo:bar")), parsed{BasicAuth: &basic{"foo", "bar"}}, true},
{"basic " + base64.StdEncoding.EncodeToString([]byte("foo:bar")), parsed{BasicAuth: &basic{"foo", "bar"}}, true},
{"token value", parsed{BearerToken: &bearer{"value"}}, true},
{"Token value", parsed{BearerToken: &bearer{"value"}}, true},
{"bearer value", parsed{BearerToken: &bearer{"value"}}, true},
{"Bearer value", parsed{BearerToken: &bearer{"value"}}, true},
{"Bearer wrong value", parsed{}, false},
}
for _, c := range cases {
ret, ok := ParseAuthorizationHeader(c.headerValue)
assert.Equal(t, c.ok, ok, "header %q", c.headerValue)
assert.Equal(t, c.expected, ret, "header %q", c.headerValue)
}
}

View File

@ -8,13 +8,10 @@ import (
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/subtle" "crypto/subtle"
"encoding/base64"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"hash" "hash"
"strconv" "strconv"
"strings"
"time" "time"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -36,19 +33,6 @@ func ShortSha(sha1 string) string {
return util.TruncateRunes(sha1, 10) return util.TruncateRunes(sha1, 10)
} }
// BasicAuthDecode decode basic auth string
func BasicAuthDecode(encoded string) (string, string, error) {
s, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return "", "", err
}
if username, password, ok := strings.Cut(string(s), ":"); ok {
return username, password, nil
}
return "", "", errors.New("invalid basic authentication")
}
// VerifyTimeLimitCode verify time limit code // VerifyTimeLimitCode verify time limit code
func VerifyTimeLimitCode(now time.Time, data string, minutes int, code string) bool { func VerifyTimeLimitCode(now time.Time, data string, minutes int, code string) bool {
if len(code) <= 18 { if len(code) <= 18 {

View File

@ -26,25 +26,6 @@ func TestShortSha(t *testing.T) {
assert.Equal(t, "veryverylo", ShortSha("veryverylong")) assert.Equal(t, "veryverylo", ShortSha("veryverylong"))
} }
func TestBasicAuthDecode(t *testing.T) {
_, _, err := BasicAuthDecode("?")
assert.Equal(t, "illegal base64 data at input byte 0", err.Error())
user, pass, err := BasicAuthDecode("Zm9vOmJhcg==")
assert.NoError(t, err)
assert.Equal(t, "foo", user)
assert.Equal(t, "bar", pass)
_, _, err = BasicAuthDecode("aW52YWxpZA==")
assert.Error(t, err)
_, _, err = BasicAuthDecode("invalid")
assert.Error(t, err)
_, _, err = BasicAuthDecode("YWxpY2U=") // "alice", no colon
assert.Error(t, err)
}
func TestVerifyTimeLimitCode(t *testing.T) { func TestVerifyTimeLimitCode(t *testing.T) {
defer test.MockVariableValue(&setting.InstallLock, true)() defer test.MockVariableValue(&setting.InstallLock, true)()
initGeneralSecret := func(secret string) { initGeneralSecret := func(secret string) {

View File

@ -6,17 +6,17 @@ package fileicon
import "code.gitea.io/gitea/modules/git" import "code.gitea.io/gitea/modules/git"
type EntryInfo struct { type EntryInfo struct {
FullName string BaseName string
EntryMode git.EntryMode EntryMode git.EntryMode
SymlinkToMode git.EntryMode SymlinkToMode git.EntryMode
IsOpen bool IsOpen bool
} }
func EntryInfoFromGitTreeEntry(gitEntry *git.TreeEntry) *EntryInfo { func EntryInfoFromGitTreeEntry(commit *git.Commit, fullPath string, gitEntry *git.TreeEntry) *EntryInfo {
ret := &EntryInfo{FullName: gitEntry.Name(), EntryMode: gitEntry.Mode()} ret := &EntryInfo{BaseName: gitEntry.Name(), EntryMode: gitEntry.Mode()}
if gitEntry.IsLink() { if gitEntry.IsLink() {
if te, err := gitEntry.FollowLink(); err == nil && te.IsDir() { if res, err := git.EntryFollowLink(commit, fullPath, gitEntry); err == nil && res.TargetEntry.IsDir() {
ret.SymlinkToMode = te.Mode() ret.SymlinkToMode = res.TargetEntry.Mode()
} }
} }
return ret return ret

View File

@ -5,7 +5,6 @@ package fileicon
import ( import (
"html/template" "html/template"
"path"
"strings" "strings"
"sync" "sync"
@ -134,7 +133,7 @@ func (m *MaterialIconProvider) FindIconName(entry *EntryInfo) string {
return "folder-git" return "folder-git"
} }
fileNameLower := strings.ToLower(path.Base(entry.FullName)) fileNameLower := strings.ToLower(entry.BaseName)
if entry.EntryMode.IsDir() { if entry.EntryMode.IsDir() {
if s, ok := m.rules.FolderNames[fileNameLower]; ok { if s, ok := m.rules.FolderNames[fileNameLower]; ok {
return s return s

View File

@ -20,8 +20,8 @@ func TestMain(m *testing.M) {
func TestFindIconName(t *testing.T) { func TestFindIconName(t *testing.T) {
unittest.PrepareTestEnv(t) unittest.PrepareTestEnv(t)
p := fileicon.DefaultMaterialIconProvider() p := fileicon.DefaultMaterialIconProvider()
assert.Equal(t, "php", p.FindIconName(&fileicon.EntryInfo{FullName: "foo.php", EntryMode: git.EntryModeBlob})) assert.Equal(t, "php", p.FindIconName(&fileicon.EntryInfo{BaseName: "foo.php", EntryMode: git.EntryModeBlob}))
assert.Equal(t, "php", p.FindIconName(&fileicon.EntryInfo{FullName: "foo.PHP", EntryMode: git.EntryModeBlob})) assert.Equal(t, "php", p.FindIconName(&fileicon.EntryInfo{BaseName: "foo.PHP", EntryMode: git.EntryModeBlob}))
assert.Equal(t, "javascript", p.FindIconName(&fileicon.EntryInfo{FullName: "foo.js", EntryMode: git.EntryModeBlob})) assert.Equal(t, "javascript", p.FindIconName(&fileicon.EntryInfo{BaseName: "foo.js", EntryMode: git.EntryModeBlob}))
assert.Equal(t, "visualstudio", p.FindIconName(&fileicon.EntryInfo{FullName: "foo.vba", EntryMode: git.EntryModeBlob})) assert.Equal(t, "visualstudio", p.FindIconName(&fileicon.EntryInfo{BaseName: "foo.vba", EntryMode: git.EntryModeBlob}))
} }

View File

@ -20,7 +20,8 @@ import (
// Commit represents a git commit. // Commit represents a git commit.
type Commit struct { type Commit struct {
Tree Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache"
ID ObjectID // The ID of this commit object ID ObjectID // The ID of this commit object
Author *Signature Author *Signature
Committer *Signature Committer *Signature

View File

@ -32,22 +32,6 @@ func (err ErrNotExist) Unwrap() error {
return util.ErrNotExist return util.ErrNotExist
} }
// ErrSymlinkUnresolved entry.FollowLink error
type ErrSymlinkUnresolved struct {
Name string
Message string
}
func (err ErrSymlinkUnresolved) Error() string {
return fmt.Sprintf("%s: %s", err.Name, err.Message)
}
// IsErrSymlinkUnresolved if some error is ErrSymlinkUnresolved
func IsErrSymlinkUnresolved(err error) bool {
_, ok := err.(ErrSymlinkUnresolved)
return ok
}
// ErrBranchNotExist represents a "BranchNotExist" kind of error. // ErrBranchNotExist represents a "BranchNotExist" kind of error.
type ErrBranchNotExist struct { type ErrBranchNotExist struct {
Name string Name string

View File

@ -11,7 +11,7 @@ import (
) )
// GetTreeEntryByPath get the tree entries according the sub dir // GetTreeEntryByPath get the tree entries according the sub dir
func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { func (t *Tree) GetTreeEntryByPath(relpath string) (_ *TreeEntry, err error) {
if len(relpath) == 0 { if len(relpath) == 0 {
return &TreeEntry{ return &TreeEntry{
ptree: t, ptree: t,
@ -21,27 +21,25 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
}, nil }, nil
} }
// FIXME: This should probably use git cat-file --batch to be a bit more efficient
relpath = path.Clean(relpath) relpath = path.Clean(relpath)
parts := strings.Split(relpath, "/") parts := strings.Split(relpath, "/")
var err error
tree := t tree := t
for i, name := range parts { for _, name := range parts[:len(parts)-1] {
if i == len(parts)-1 { tree, err = tree.SubTree(name)
entries, err := tree.ListEntries() if err != nil {
if err != nil { return nil, err
return nil, err }
} }
for _, v := range entries {
if v.Name() == name { name := parts[len(parts)-1]
return v, nil entries, err := tree.ListEntries()
} if err != nil {
} return nil, err
} else { }
tree, err = tree.SubTree(name) for _, v := range entries {
if err != nil { if v.Name() == name {
return nil, err return v, nil
}
} }
} }
return nil, ErrNotExist{"", relpath} return nil, ErrNotExist{"", relpath}

View File

@ -5,7 +5,7 @@
package git package git
import ( import (
"io" "path"
"sort" "sort"
"strings" "strings"
@ -24,77 +24,57 @@ func (te *TreeEntry) Type() string {
} }
} }
// FollowLink returns the entry pointed to by a symlink type EntryFollowResult struct {
func (te *TreeEntry) FollowLink() (*TreeEntry, error) { SymlinkContent string
if !te.IsLink() { TargetFullPath string
return nil, ErrSymlinkUnresolved{te.Name(), "not a symlink"} TargetEntry *TreeEntry
}
// read the link
r, err := te.Blob().DataAsync()
if err != nil {
return nil, err
}
closed := false
defer func() {
if !closed {
_ = r.Close()
}
}()
buf := make([]byte, te.Size())
_, err = io.ReadFull(r, buf)
if err != nil {
return nil, err
}
_ = r.Close()
closed = true
lnk := string(buf)
t := te.ptree
// traverse up directories
for ; t != nil && strings.HasPrefix(lnk, "../"); lnk = lnk[3:] {
t = t.ptree
}
if t == nil {
return nil, ErrSymlinkUnresolved{te.Name(), "points outside of repo"}
}
target, err := t.GetTreeEntryByPath(lnk)
if err != nil {
if IsErrNotExist(err) {
return nil, ErrSymlinkUnresolved{te.Name(), "broken link"}
}
return nil, err
}
return target, nil
} }
// FollowLinks returns the entry ultimately pointed to by a symlink func EntryFollowLink(commit *Commit, fullPath string, te *TreeEntry) (*EntryFollowResult, error) {
func (te *TreeEntry) FollowLinks(optLimit ...int) (*TreeEntry, error) {
if !te.IsLink() { if !te.IsLink() {
return nil, ErrSymlinkUnresolved{te.Name(), "not a symlink"} return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q is not a symlink", fullPath)
} }
// git's filename max length is 4096, hopefully a link won't be longer than multiple of that
const maxSymlinkSize = 20 * 4096
if te.Blob().Size() > maxSymlinkSize {
return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q content exceeds symlink limit", fullPath)
}
link, err := te.Blob().GetBlobContent(maxSymlinkSize)
if err != nil {
return nil, err
}
if strings.HasPrefix(link, "/") {
// It's said that absolute path will be stored as is in Git
return &EntryFollowResult{SymlinkContent: link}, util.ErrorWrap(util.ErrUnprocessableContent, "%q is an absolute symlink", fullPath)
}
targetFullPath := path.Join(path.Dir(fullPath), link)
targetEntry, err := commit.GetTreeEntryByPath(targetFullPath)
if err != nil {
return &EntryFollowResult{SymlinkContent: link}, err
}
return &EntryFollowResult{SymlinkContent: link, TargetFullPath: targetFullPath, TargetEntry: targetEntry}, nil
}
func EntryFollowLinks(commit *Commit, firstFullPath string, firstTreeEntry *TreeEntry, optLimit ...int) (res *EntryFollowResult, err error) {
limit := util.OptionalArg(optLimit, 10) limit := util.OptionalArg(optLimit, 10)
entry := te treeEntry, fullPath := firstTreeEntry, firstFullPath
for range limit { for range limit {
if !entry.IsLink() { res, err = EntryFollowLink(commit, fullPath, treeEntry)
if err != nil {
return res, err
}
treeEntry, fullPath = res.TargetEntry, res.TargetFullPath
if !treeEntry.IsLink() {
break break
} }
next, err := entry.FollowLink()
if err != nil {
return nil, err
}
if next.ID == entry.ID {
return nil, ErrSymlinkUnresolved{entry.Name(), "recursive link"}
}
entry = next
} }
if entry.IsLink() { if treeEntry.IsLink() {
return nil, ErrSymlinkUnresolved{te.Name(), "too many levels of symbolic links"} return res, util.ErrorWrap(util.ErrUnprocessableContent, "%q has too many links", firstFullPath)
} }
return entry, nil return res, nil
} }
// returns the Tree pointed to by this TreeEntry, or nil if this is not a tree // returns the Tree pointed to by this TreeEntry, or nil if this is not a tree

View File

@ -0,0 +1,76 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"testing"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFollowLink(t *testing.T) {
r, err := openRepositoryWithDefaultContext("tests/repos/repo1_bare")
require.NoError(t, err)
defer r.Close()
commit, err := r.GetCommit("37991dec2c8e592043f47155ce4808d4580f9123")
require.NoError(t, err)
// get the symlink
{
lnkFullPath := "foo/bar/link_to_hello"
lnk, err := commit.Tree.GetTreeEntryByPath("foo/bar/link_to_hello")
require.NoError(t, err)
assert.True(t, lnk.IsLink())
// should be able to dereference to target
res, err := EntryFollowLink(commit, lnkFullPath, lnk)
require.NoError(t, err)
assert.Equal(t, "hello", res.TargetEntry.Name())
assert.Equal(t, "foo/nar/hello", res.TargetFullPath)
assert.False(t, res.TargetEntry.IsLink())
assert.Equal(t, "b14df6442ea5a1b382985a6549b85d435376c351", res.TargetEntry.ID.String())
}
{
// should error when called on a normal file
entry, err := commit.Tree.GetTreeEntryByPath("file1.txt")
require.NoError(t, err)
res, err := EntryFollowLink(commit, "file1.txt", entry)
assert.ErrorIs(t, err, util.ErrUnprocessableContent)
assert.Nil(t, res)
}
{
// should error for broken links
entry, err := commit.Tree.GetTreeEntryByPath("foo/broken_link")
require.NoError(t, err)
assert.True(t, entry.IsLink())
res, err := EntryFollowLink(commit, "foo/broken_link", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "nar/broken_link", res.SymlinkContent)
}
{
// should error for external links
entry, err := commit.Tree.GetTreeEntryByPath("foo/outside_repo")
require.NoError(t, err)
assert.True(t, entry.IsLink())
res, err := EntryFollowLink(commit, "foo/outside_repo", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "../../outside_repo", res.SymlinkContent)
}
{
// testing fix for short link bug
entry, err := commit.Tree.GetTreeEntryByPath("foo/link_short")
require.NoError(t, err)
res, err := EntryFollowLink(commit, "foo/link_short", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "a", res.SymlinkContent)
}
}

View File

@ -19,16 +19,12 @@ type TreeEntry struct {
gogitTreeEntry *object.TreeEntry gogitTreeEntry *object.TreeEntry
ptree *Tree ptree *Tree
size int64 size int64
sized bool sized bool
fullName string
} }
// Name returns the name of the entry // Name returns the name of the entry
func (te *TreeEntry) Name() string { func (te *TreeEntry) Name() string {
if te.fullName != "" {
return te.fullName
}
return te.gogitTreeEntry.Name return te.gogitTreeEntry.Name
} }
@ -55,7 +51,7 @@ func (te *TreeEntry) Size() int64 {
return te.size return te.size
} }
// IsSubModule if the entry is a sub module // IsSubModule if the entry is a submodule
func (te *TreeEntry) IsSubModule() bool { func (te *TreeEntry) IsSubModule() bool {
return te.gogitTreeEntry.Mode == filemode.Submodule return te.gogitTreeEntry.Mode == filemode.Submodule
} }

View File

@ -15,7 +15,7 @@ type EntryMode int
// one of these. // one of these.
const ( const (
// EntryModeNoEntry is possible if the file was added or removed in a commit. In the case of // EntryModeNoEntry is possible if the file was added or removed in a commit. In the case of
// added the base commit will not have the file in its tree so a mode of 0o000000 is used. // when adding the base commit doesn't have the file in its tree, a mode of 0o000000 is used.
EntryModeNoEntry EntryMode = 0o000000 EntryModeNoEntry EntryMode = 0o000000
EntryModeBlob EntryMode = 0o100644 EntryModeBlob EntryMode = 0o100644
@ -30,7 +30,7 @@ func (e EntryMode) String() string {
return strconv.FormatInt(int64(e), 8) return strconv.FormatInt(int64(e), 8)
} }
// IsSubModule if the entry is a sub module // IsSubModule if the entry is a submodule
func (e EntryMode) IsSubModule() bool { func (e EntryMode) IsSubModule() bool {
return e == EntryModeCommit return e == EntryModeCommit
} }

View File

@ -57,7 +57,7 @@ func (te *TreeEntry) Size() int64 {
return te.size return te.size
} }
// IsSubModule if the entry is a sub module // IsSubModule if the entry is a submodule
func (te *TreeEntry) IsSubModule() bool { func (te *TreeEntry) IsSubModule() bool {
return te.entryMode.IsSubModule() return te.entryMode.IsSubModule()
} }

View File

@ -53,50 +53,3 @@ func TestEntriesCustomSort(t *testing.T) {
assert.Equal(t, "bcd", entries[6].Name()) assert.Equal(t, "bcd", entries[6].Name())
assert.Equal(t, "abc", entries[7].Name()) assert.Equal(t, "abc", entries[7].Name())
} }
func TestFollowLink(t *testing.T) {
r, err := openRepositoryWithDefaultContext("tests/repos/repo1_bare")
assert.NoError(t, err)
defer r.Close()
commit, err := r.GetCommit("37991dec2c8e592043f47155ce4808d4580f9123")
assert.NoError(t, err)
// get the symlink
lnk, err := commit.Tree.GetTreeEntryByPath("foo/bar/link_to_hello")
assert.NoError(t, err)
assert.True(t, lnk.IsLink())
// should be able to dereference to target
target, err := lnk.FollowLink()
assert.NoError(t, err)
assert.Equal(t, "hello", target.Name())
assert.False(t, target.IsLink())
assert.Equal(t, "b14df6442ea5a1b382985a6549b85d435376c351", target.ID.String())
// should error when called on normal file
target, err = commit.Tree.GetTreeEntryByPath("file1.txt")
assert.NoError(t, err)
_, err = target.FollowLink()
assert.EqualError(t, err, "file1.txt: not a symlink")
// should error for broken links
target, err = commit.Tree.GetTreeEntryByPath("foo/broken_link")
assert.NoError(t, err)
assert.True(t, target.IsLink())
_, err = target.FollowLink()
assert.EqualError(t, err, "broken_link: broken link")
// should error for external links
target, err = commit.Tree.GetTreeEntryByPath("foo/outside_repo")
assert.NoError(t, err)
assert.True(t, target.IsLink())
_, err = target.FollowLink()
assert.EqualError(t, err, "outside_repo: points outside of repo")
// testing fix for short link bug
target, err = commit.Tree.GetTreeEntryByPath("foo/link_short")
assert.NoError(t, err)
_, err = target.FollowLink()
assert.EqualError(t, err, "link_short: broken link")
}

View File

@ -69,7 +69,7 @@ func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) {
seen := map[plumbing.Hash]bool{} seen := map[plumbing.Hash]bool{}
walker := object.NewTreeWalker(t.gogitTree, true, seen) walker := object.NewTreeWalker(t.gogitTree, true, seen)
for { for {
fullName, entry, err := walker.Next() _, entry, err := walker.Next()
if err == io.EOF { if err == io.EOF {
break break
} }
@ -84,7 +84,6 @@ func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) {
ID: ParseGogitHash(entry.Hash), ID: ParseGogitHash(entry.Hash),
gogitTreeEntry: &entry, gogitTreeEntry: &entry,
ptree: t, ptree: t,
fullName: fullName,
} }
entries = append(entries, convertedEntry) entries = append(entries, convertedEntry)
} }

View File

@ -91,8 +91,7 @@ func (r *stripRenderer) processAutoLink(w io.Writer, link []byte) {
} }
// Note: we're not attempting to match the URL scheme (http/https) // Note: we're not attempting to match the URL scheme (http/https)
host := strings.ToLower(u.Host) if u.Host != "" && !strings.EqualFold(u.Host, r.localhost.Host) {
if host != "" && host != strings.ToLower(r.localhost.Host) {
// Process out of band // Process out of band
r.links = append(r.links, linkStr) r.links = append(r.links, linkStr)
return return

View File

@ -71,6 +71,7 @@ type Metadata struct {
ReleaseNotes string `json:"release_notes,omitempty"` ReleaseNotes string `json:"release_notes,omitempty"`
RepositoryURL string `json:"repository_url,omitempty"` RepositoryURL string `json:"repository_url,omitempty"`
RequireLicenseAcceptance bool `json:"require_license_acceptance"` RequireLicenseAcceptance bool `json:"require_license_acceptance"`
Summary string `json:"summary,omitempty"`
Tags string `json:"tags,omitempty"` Tags string `json:"tags,omitempty"`
Title string `json:"title,omitempty"` Title string `json:"title,omitempty"`
@ -105,6 +106,7 @@ type nuspecPackage struct {
Readme string `xml:"readme"` Readme string `xml:"readme"`
ReleaseNotes string `xml:"releaseNotes"` ReleaseNotes string `xml:"releaseNotes"`
RequireLicenseAcceptance bool `xml:"requireLicenseAcceptance"` RequireLicenseAcceptance bool `xml:"requireLicenseAcceptance"`
Summary string `xml:"summary"`
Tags string `xml:"tags"` Tags string `xml:"tags"`
Title string `xml:"title"` Title string `xml:"title"`
@ -204,6 +206,7 @@ func ParseNuspecMetaData(archive *zip.Reader, r io.Reader) (*Package, error) {
ReleaseNotes: p.Metadata.ReleaseNotes, ReleaseNotes: p.Metadata.ReleaseNotes,
RepositoryURL: p.Metadata.Repository.URL, RepositoryURL: p.Metadata.Repository.URL,
RequireLicenseAcceptance: p.Metadata.RequireLicenseAcceptance, RequireLicenseAcceptance: p.Metadata.RequireLicenseAcceptance,
Summary: p.Metadata.Summary,
Tags: p.Metadata.Tags, Tags: p.Metadata.Tags,
Title: p.Metadata.Title, Title: p.Metadata.Title,

View File

@ -88,7 +88,7 @@ func ParsePackage(r io.Reader) (*Package, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else if strings.ToLower(hd.Name) == "readme.md" { } else if strings.EqualFold(hd.Name, "readme.md") {
data, err := io.ReadAll(tr) data, err := io.ReadAll(tr)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -62,11 +62,11 @@ func (c logCompression) IsValid() bool {
} }
func (c logCompression) IsNone() bool { func (c logCompression) IsNone() bool {
return strings.ToLower(string(c)) == "none" return string(c) == "none"
} }
func (c logCompression) IsZstd() bool { func (c logCompression) IsZstd() bool {
return c == "" || strings.ToLower(string(c)) == "zstd" return c == "" || string(c) == "zstd"
} }
func loadActionsFrom(rootCfg ConfigProvider) error { func loadActionsFrom(rootCfg ConfigProvider) error {

View File

@ -116,14 +116,17 @@ type ContentsExtResponse struct {
// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content // ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
type ContentsResponse struct { type ContentsResponse struct {
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path"` Path string `json:"path"`
SHA string `json:"sha"` SHA string `json:"sha"`
LastCommitSHA string `json:"last_commit_sha"`
LastCommitSHA *string `json:"last_commit_sha,omitempty"`
// swagger:strfmt date-time // swagger:strfmt date-time
LastCommitterDate time.Time `json:"last_committer_date"` LastCommitterDate *time.Time `json:"last_committer_date,omitempty"`
// swagger:strfmt date-time // swagger:strfmt date-time
LastAuthorDate time.Time `json:"last_author_date"` LastAuthorDate *time.Time `json:"last_author_date,omitempty"`
LastCommitMessage *string `json:"last_commit_message,omitempty"`
// `type` will be `file`, `dir`, `symlink`, or `submodule` // `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"` Type string `json:"type"`
Size int64 `json:"size"` Size int64 `json:"size"`
@ -141,8 +144,8 @@ type ContentsResponse struct {
SubmoduleGitURL *string `json:"submodule_git_url"` SubmoduleGitURL *string `json:"submodule_git_url"`
Links *FileLinksResponse `json:"_links"` Links *FileLinksResponse `json:"_links"`
LfsOid *string `json:"lfs_oid"` LfsOid *string `json:"lfs_oid,omitempty"`
LfsSize *int64 `json:"lfs_size"` LfsSize *int64 `json:"lfs_size,omitempty"`
} }
// FileCommitResponse contains information generated from a Git commit for a repo's file. // FileCommitResponse contains information generated from a Git commit for a repo's file.

View File

@ -40,7 +40,6 @@ func NewFuncMap() template.FuncMap {
"HTMLFormat": htmlFormat, "HTMLFormat": htmlFormat,
"QueryEscape": queryEscape, "QueryEscape": queryEscape,
"QueryBuild": QueryBuild, "QueryBuild": QueryBuild,
"JSEscape": jsEscapeSafe,
"SanitizeHTML": SanitizeHTML, "SanitizeHTML": SanitizeHTML,
"URLJoin": util.URLJoin, "URLJoin": util.URLJoin,
"DotEscape": dotEscape, "DotEscape": dotEscape,
@ -181,10 +180,6 @@ func htmlFormat(s any, args ...any) template.HTML {
panic(fmt.Sprintf("unexpected type %T", s)) panic(fmt.Sprintf("unexpected type %T", s))
} }
func jsEscapeSafe(s string) template.HTML {
return template.HTML(template.JSEscapeString(s))
}
func queryEscape(s string) template.URL { func queryEscape(s string) template.URL {
return template.URL(url.QueryEscape(s)) return template.URL(url.QueryEscape(s))
} }

View File

@ -57,10 +57,6 @@ func TestSubjectBodySeparator(t *testing.T) {
"Insufficient\n--\nSeparators") "Insufficient\n--\nSeparators")
} }
func TestJSEscapeSafe(t *testing.T) {
assert.EqualValues(t, `\u0026\u003C\u003E\'\"`, jsEscapeSafe(`&<>'"`))
}
func TestSanitizeHTML(t *testing.T) { func TestSanitizeHTML(t *testing.T) {
assert.Equal(t, template.HTML(`<a href="/" rel="nofollow">link</a> xss <div>inline</div>`), SanitizeHTML(`<a href="/">link</a> <a href="javascript:">xss</a> <div style="dangerous">inline</div>`)) assert.Equal(t, template.HTML(`<a href="/" rel="nofollow">link</a> xss <div>inline</div>`), SanitizeHTML(`<a href="/">link</a> <a href="javascript:">xss</a> <div style="dangerous">inline</div>`))
} }

View File

@ -17,8 +17,8 @@ var (
ErrNotExist = errors.New("resource does not exist") // also implies HTTP 404 ErrNotExist = errors.New("resource does not exist") // also implies HTTP 404
ErrAlreadyExist = errors.New("resource already exists") // also implies HTTP 409 ErrAlreadyExist = errors.New("resource already exists") // also implies HTTP 409
// ErrUnprocessableContent implies HTTP 422, syntax of the request content was correct, // ErrUnprocessableContent implies HTTP 422, the syntax of the request content is correct,
// but server was unable to process the contained instructions // but the server is unable to process the contained instructions
ErrUnprocessableContent = errors.New("unprocessable content") ErrUnprocessableContent = errors.New("unprocessable content")
) )

View File

@ -12,8 +12,7 @@ import (
// SliceContainsString sequential searches if string exists in slice. // SliceContainsString sequential searches if string exists in slice.
func SliceContainsString(slice []string, target string, insensitive ...bool) bool { func SliceContainsString(slice []string, target string, insensitive ...bool) bool {
if len(insensitive) != 0 && insensitive[0] { if len(insensitive) != 0 && insensitive[0] {
target = strings.ToLower(target) return slices.ContainsFunc(slice, func(t string) bool { return strings.EqualFold(t, target) })
return slices.ContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target })
} }
return slices.Contains(slice, target) return slices.Contains(slice, target)

View File

@ -110,3 +110,24 @@ func SplitTrimSpace(input, sep string) []string {
} }
return stringList return stringList
} }
func asciiLower(b byte) byte {
if 'A' <= b && b <= 'Z' {
return b + ('a' - 'A')
}
return b
}
// AsciiEqualFold is from Golang https://cs.opensource.google/go/go/+/refs/tags/go1.24.4:src/net/http/internal/ascii/print.go
// ASCII only. In most cases for protocols, we should only use this but not [strings.EqualFold]
func AsciiEqualFold(s, t string) bool { //nolint:revive // PascalCase
if len(s) != len(t) {
return false
}
for i := 0; i < len(s); i++ {
if asciiLower(s[i]) != asciiLower(t[i]) {
return false
}
}
return true
}

View File

@ -59,7 +59,7 @@ func TimeEstimateParse(timeStr string) (int64, error) {
unit := timeStr[match[4]:match[5]] unit := timeStr[match[4]:match[5]]
found := false found := false
for _, u := range timeStrGlobalVars().units { for _, u := range timeStrGlobalVars().units {
if strings.ToLower(unit) == u.name { if strings.EqualFold(unit, u.name) {
total += amount * u.num total += amount * u.num
found = true found = true
break break

View File

@ -26,6 +26,7 @@ func (g *RouterPathGroup) ServeHTTP(resp http.ResponseWriter, req *http.Request)
path := chiCtx.URLParam(g.pathParam) path := chiCtx.URLParam(g.pathParam)
for _, m := range g.matchers { for _, m := range g.matchers {
if m.matchPath(chiCtx, path) { if m.matchPath(chiCtx, path) {
chiCtx.RoutePatterns = append(chiCtx.RoutePatterns, m.pattern)
handler := m.handlerFunc handler := m.handlerFunc
for i := len(m.middlewares) - 1; i >= 0; i-- { for i := len(m.middlewares) - 1; i >= 0; i-- {
handler = m.middlewares[i](handler).ServeHTTP handler = m.middlewares[i](handler).ServeHTTP
@ -38,6 +39,7 @@ func (g *RouterPathGroup) ServeHTTP(resp http.ResponseWriter, req *http.Request)
} }
type RouterPathGroupPattern struct { type RouterPathGroupPattern struct {
pattern string
re *regexp.Regexp re *regexp.Regexp
params []routerPathParam params []routerPathParam
middlewares []any middlewares []any
@ -62,6 +64,7 @@ type routerPathParam struct {
type routerPathMatcher struct { type routerPathMatcher struct {
methods container.Set[string] methods container.Set[string]
pattern string
re *regexp.Regexp re *regexp.Regexp
params []routerPathParam params []routerPathParam
middlewares []func(http.Handler) http.Handler middlewares []func(http.Handler) http.Handler
@ -117,7 +120,7 @@ func newRouterPathMatcher(methods string, patternRegexp *RouterPathGroupPattern,
} }
p.methods.Add(method) p.methods.Add(method)
} }
p.re, p.params = patternRegexp.re, patternRegexp.params p.pattern, p.re, p.params = patternRegexp.pattern, patternRegexp.re, patternRegexp.params
return p return p
} }
@ -157,7 +160,7 @@ func patternRegexp(pattern string, h ...any) *RouterPathGroupPattern {
p.params = append(p.params, param) p.params = append(p.params, param)
} }
re = append(re, '$') re = append(re, '$')
p.re = regexp.MustCompile(string(re)) p.pattern, p.re = pattern, regexp.MustCompile(string(re))
return p return p
} }

View File

@ -56,17 +56,20 @@ func TestRouter(t *testing.T) {
recorder.Body = buff recorder.Body = buff
type resultStruct struct { type resultStruct struct {
method string method string
pathParams map[string]string pathParams map[string]string
handlerMarks []string handlerMarks []string
chiRoutePattern *string
} }
var res resultStruct var res resultStruct
h := func(optMark ...string) func(resp http.ResponseWriter, req *http.Request) { h := func(optMark ...string) func(resp http.ResponseWriter, req *http.Request) {
mark := util.OptionalArg(optMark, "") mark := util.OptionalArg(optMark, "")
return func(resp http.ResponseWriter, req *http.Request) { return func(resp http.ResponseWriter, req *http.Request) {
chiCtx := chi.RouteContext(req.Context())
res.method = req.Method res.method = req.Method
res.pathParams = chiURLParamsToMap(chi.RouteContext(req.Context())) res.pathParams = chiURLParamsToMap(chiCtx)
res.chiRoutePattern = util.ToPointer(chiCtx.RoutePattern())
if mark != "" { if mark != "" {
res.handlerMarks = append(res.handlerMarks, mark) res.handlerMarks = append(res.handlerMarks, mark)
} }
@ -125,21 +128,29 @@ func TestRouter(t *testing.T) {
req, err := http.NewRequest(methodPathFields[0], methodPathFields[1], nil) req, err := http.NewRequest(methodPathFields[0], methodPathFields[1], nil)
assert.NoError(t, err) assert.NoError(t, err)
r.ServeHTTP(recorder, req) r.ServeHTTP(recorder, req)
if expected.chiRoutePattern == nil {
res.chiRoutePattern = nil
}
assert.Equal(t, expected, res) assert.Equal(t, expected, res)
}) })
} }
t.Run("RootRouter", func(t *testing.T) { t.Run("RootRouter", func(t *testing.T) {
testRoute(t, "GET /the-user/the-repo/other", resultStruct{method: "GET", handlerMarks: []string{"not-found:/"}}) testRoute(t, "GET /the-user/the-repo/other", resultStruct{
method: "GET",
handlerMarks: []string{"not-found:/"},
chiRoutePattern: util.ToPointer(""),
})
testRoute(t, "GET /the-user/the-repo/pulls", resultStruct{ testRoute(t, "GET /the-user/the-repo/pulls", resultStruct{
method: "GET", method: "GET",
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "type": "pulls"}, pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "type": "pulls"},
handlerMarks: []string{"list-issues-b"}, handlerMarks: []string{"list-issues-b"},
}) })
testRoute(t, "GET /the-user/the-repo/issues/123", resultStruct{ testRoute(t, "GET /the-user/the-repo/issues/123", resultStruct{
method: "GET", method: "GET",
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "type": "issues", "index": "123"}, pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "type": "issues", "index": "123"},
handlerMarks: []string{"view-issue"}, handlerMarks: []string{"view-issue"},
chiRoutePattern: util.ToPointer("/{username}/{reponame}/{type:issues|pulls}/{index}"),
}) })
testRoute(t, "GET /the-user/the-repo/issues/123?stop=hijack", resultStruct{ testRoute(t, "GET /the-user/the-repo/issues/123?stop=hijack", resultStruct{
method: "GET", method: "GET",
@ -154,7 +165,10 @@ func TestRouter(t *testing.T) {
}) })
t.Run("Sub Router", func(t *testing.T) { t.Run("Sub Router", func(t *testing.T) {
testRoute(t, "GET /api/v1/other", resultStruct{method: "GET", handlerMarks: []string{"not-found:/api/v1"}}) testRoute(t, "GET /api/v1/other", resultStruct{
method: "GET",
handlerMarks: []string{"not-found:/api/v1"},
})
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches", resultStruct{ testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches", resultStruct{
method: "GET", method: "GET",
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo"}, pathParams: map[string]string{"username": "the-user", "reponame": "the-repo"},
@ -211,9 +225,10 @@ func TestRouter(t *testing.T) {
}) })
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches/d1/d2/fn?stop=s3", resultStruct{ testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches/d1/d2/fn?stop=s3", resultStruct{
method: "GET", method: "GET",
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "*": "d1/d2/fn", "dir": "d1/d2", "file": "fn"}, pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "*": "d1/d2/fn", "dir": "d1/d2", "file": "fn"},
handlerMarks: []string{"s1", "s2", "s3"}, handlerMarks: []string{"s1", "s2", "s3"},
chiRoutePattern: util.ToPointer("/api/v1/repos/{username}/{reponame}/branches/<dir:*>/<file:[a-z]{1,2}>"),
}) })
}) })
} }

View File

@ -3131,6 +3131,34 @@
".links": "folder-link", ".links": "folder-link",
"_links": "folder-link", "_links": "folder-link",
"__links__": "folder-link", "__links__": "folder-link",
"pytorch": "folder-pytorch",
".pytorch": "folder-pytorch",
"_pytorch": "folder-pytorch",
"__pytorch__": "folder-pytorch",
"torch": "folder-pytorch",
".torch": "folder-pytorch",
"_torch": "folder-pytorch",
"__torch__": "folder-pytorch",
"blender": "folder-blender",
".blender": "folder-blender",
"_blender": "folder-blender",
"__blender__": "folder-blender",
"blender-assets": "folder-blender",
".blender-assets": "folder-blender",
"_blender-assets": "folder-blender",
"__blender-assets__": "folder-blender",
"blender-files": "folder-blender",
".blender-files": "folder-blender",
"_blender-files": "folder-blender",
"__blender-files__": "folder-blender",
"blender-project": "folder-blender",
".blender-project": "folder-blender",
"_blender-project": "folder-blender",
"__blender-project__": "folder-blender",
"blender-models": "folder-blender",
".blender-models": "folder-blender",
"_blender-models": "folder-blender",
"__blender-models__": "folder-blender",
"meta-inf": "folder-config", "meta-inf": "folder-config",
".meta-inf": "folder-config", ".meta-inf": "folder-config",
"_meta-inf": "folder-config", "_meta-inf": "folder-config",
@ -6291,7 +6319,35 @@
"links": "folder-link-open", "links": "folder-link-open",
".links": "folder-link-open", ".links": "folder-link-open",
"_links": "folder-link-open", "_links": "folder-link-open",
"__links__": "folder-link-open" "__links__": "folder-link-open",
"pytorch": "folder-pytorch-open",
".pytorch": "folder-pytorch-open",
"_pytorch": "folder-pytorch-open",
"__pytorch__": "folder-pytorch-open",
"torch": "folder-pytorch-open",
".torch": "folder-pytorch-open",
"_torch": "folder-pytorch-open",
"__torch__": "folder-pytorch-open",
"blender": "folder-blender-open",
".blender": "folder-blender-open",
"_blender": "folder-blender-open",
"__blender__": "folder-blender-open",
"blender-assets": "folder-blender-open",
".blender-assets": "folder-blender-open",
"_blender-assets": "folder-blender-open",
"__blender-assets__": "folder-blender-open",
"blender-files": "folder-blender-open",
".blender-files": "folder-blender-open",
"_blender-files": "folder-blender-open",
"__blender-files__": "folder-blender-open",
"blender-project": "folder-blender-open",
".blender-project": "folder-blender-open",
"_blender-project": "folder-blender-open",
"__blender-project__": "folder-blender-open",
"blender-models": "folder-blender-open",
".blender-models": "folder-blender-open",
"_blender-models": "folder-blender-open",
"__blender-models__": "folder-blender-open"
}, },
"rootFolderNames": {}, "rootFolderNames": {},
"rootFolderNamesExpanded": {}, "rootFolderNamesExpanded": {},
@ -7099,10 +7155,10 @@
"fast": "lisp", "fast": "lisp",
"stl": "3d", "stl": "3d",
"stp": "3d", "stp": "3d",
"step": "3d",
"obj": "3d", "obj": "3d",
"o": "3d", "o": "3d",
"ac": "3d", "ac": "3d",
"blend": "3d",
"dxf": "3d", "dxf": "3d",
"fbx": "3d", "fbx": "3d",
"mesh": "3d", "mesh": "3d",
@ -7115,6 +7171,12 @@
"vox": "3d", "vox": "3d",
"gltf": "3d", "gltf": "3d",
"glb": "3d", "glb": "3d",
"3ds": "3d",
"dae": "3d",
"ply": "3d",
"wrl": "3d",
"usd": "3d",
"usdz": "3d",
"svg": "svg", "svg": "svg",
"ai": "adobe-illustrator", "ai": "adobe-illustrator",
"ait": "adobe-illustrator", "ait": "adobe-illustrator",
@ -7382,6 +7444,12 @@
"snakemake": "snakemake", "snakemake": "snakemake",
"cpn": "coloredpetrinets", "cpn": "coloredpetrinets",
"pnml": "coloredpetrinets", "pnml": "coloredpetrinets",
"pt": "pytorch",
"pth": "pytorch",
"pwf": "pytorch",
"blend": "blender",
"blend1": "blender",
"blend2": "blender",
"yaml-tmlanguage": "yaml", "yaml-tmlanguage": "yaml",
"tmlanguage": "xml", "tmlanguage": "xml",
"cljx": "clojure", "cljx": "clojure",
@ -7545,7 +7613,6 @@
"opml": "xml", "opml": "xml",
"owl": "xml", "owl": "xml",
"proj": "xml", "proj": "xml",
"pt": "xml",
"publishsettings": "xml", "publishsettings": "xml",
"pubxml": "xml", "pubxml": "xml",
"pubxml.user": "xml", "pubxml.user": "xml",
@ -7883,6 +7950,7 @@
".pubignore": "dart", ".pubignore": "dart",
"cmakelists.txt": "cmake", "cmakelists.txt": "cmake",
"cmakecache.txt": "cmake", "cmakecache.txt": "cmake",
"CMakePresets.json": "cmake",
"semgrep.yml": "semgrep", "semgrep.yml": "semgrep",
".semgrepignore": "semgrep", ".semgrepignore": "semgrep",
"vue.config.js": "vue-config", "vue.config.js": "vue-config",
@ -8491,6 +8559,7 @@
".mocharc.yml": "mocha", ".mocharc.yml": "mocha",
".mocharc.yaml": "mocha", ".mocharc.yaml": "mocha",
".mocharc.js": "mocha", ".mocharc.js": "mocha",
".mocharc.cjs": "mocha",
".mocharc.json": "mocha", ".mocharc.json": "mocha",
".mocharc.jsonc": "mocha", ".mocharc.jsonc": "mocha",
"jenkinsfile": "jenkins", "jenkinsfile": "jenkins",
@ -8739,11 +8808,13 @@
"azure-pipelines-main.yaml": "azure-pipelines", "azure-pipelines-main.yaml": "azure-pipelines",
"vagrantfile": "vagrant", "vagrantfile": "vagrant",
"prisma.yml": "prisma", "prisma.yml": "prisma",
"prisma.config.ts": "prisma",
".nycrc": "istanbul", ".nycrc": "istanbul",
".nycrc.json": "istanbul", ".nycrc.json": "istanbul",
".nycrc.yaml": "istanbul", ".nycrc.yaml": "istanbul",
".nycrc.yml": "istanbul", ".nycrc.yml": "istanbul",
"nyc.config.js": "istanbul", "nyc.config.js": "istanbul",
"nyc.config.cjs": "istanbul",
".istanbul.yml": "istanbul", ".istanbul.yml": "istanbul",
"tailwind.js": "tailwindcss", "tailwind.js": "tailwindcss",
"tailwind.ts": "tailwindcss", "tailwind.ts": "tailwindcss",
@ -9477,6 +9548,7 @@
"hadolint.yaml": "hadolint", "hadolint.yaml": "hadolint",
"hadolint.yml": "hadolint", "hadolint.yml": "hadolint",
".rhistory": "r", ".rhistory": "r",
"cmakepresets.json": "cmake",
"cname": "http", "cname": "http",
"sonarqube.analysis.xml": "sonarcloud", "sonarqube.analysis.xml": "sonarcloud",
"owners": "codeowners", "owners": "codeowners",
@ -9590,7 +9662,13 @@
"tex": "tex", "tex": "tex",
"latex": "latex", "latex": "latex",
"latex-expl3": "latex", "latex-expl3": "latex",
"latex-class": "latex-class",
"latex-package": "latex-package",
"context": "context",
"doctex": "doctex", "doctex": "doctex",
"doctex-installer": "doctex-installer",
"bibtex": "bibliography",
"bibtex-style": "bibtex-style",
"apex": "salesforce", "apex": "salesforce",
"sas": "sas", "sas": "sas",
"dockerfile": "docker", "dockerfile": "docker",
@ -9622,8 +9700,6 @@
"vue-postcss": "vue", "vue-postcss": "vue",
"vue-html": "vue", "vue-html": "vue",
"lua": "lua", "lua": "lua",
"bibtex": "bibliography",
"bibtex-style": "bibtex-style",
"log": "log", "log": "log",
"jupyter": "jupyter", "jupyter": "jupyter",
"plaintext": "document", "plaintext": "document",

File diff suppressed because one or more lines are too long

View File

@ -2274,8 +2274,6 @@ settings.hooks_desc=Webové háčky automaticky vytvářejí dotazy HTTP POST na
settings.webhook_deletion=Odstranit webový háček settings.webhook_deletion=Odstranit webový háček
settings.webhook_deletion_desc=Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat? settings.webhook_deletion_desc=Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat?
settings.webhook_deletion_success=Webový háček byl smazán. settings.webhook_deletion_success=Webový háček byl smazán.
settings.webhook.test_delivery=Test doručitelnosti
settings.webhook.test_delivery_desc=Vyzkoušet tento webový háček pomocí falešné události.
settings.webhook.test_delivery_desc_disabled=Chcete-li tento webový háček otestovat s falešnou událostí, aktivujte ho. settings.webhook.test_delivery_desc_disabled=Chcete-li tento webový háček otestovat s falešnou událostí, aktivujte ho.
settings.webhook.request=Požadavek settings.webhook.request=Požadavek
settings.webhook.response=Odpověď settings.webhook.response=Odpověď

View File

@ -2316,8 +2316,6 @@ settings.hooks_desc=Webhooks senden bei bestimmten Gitea-Events automatisch „H
settings.webhook_deletion=Webhook löschen settings.webhook_deletion=Webhook löschen
settings.webhook_deletion_desc=Das Entfernen eines Webhooks löscht seine Einstellungen und Zustellungsverlauf. Fortfahren? settings.webhook_deletion_desc=Das Entfernen eines Webhooks löscht seine Einstellungen und Zustellungsverlauf. Fortfahren?
settings.webhook_deletion_success=Webhook wurde entfernt. settings.webhook_deletion_success=Webhook wurde entfernt.
settings.webhook.test_delivery=Senden testen
settings.webhook.test_delivery_desc=Teste diesen Webhook mit einem Fake-Event.
settings.webhook.test_delivery_desc_disabled=Um diesen Webhook mit einem Fake-Event zu testen, aktiviere ihn. settings.webhook.test_delivery_desc_disabled=Um diesen Webhook mit einem Fake-Event zu testen, aktiviere ihn.
settings.webhook.request=Anfrage settings.webhook.request=Anfrage
settings.webhook.response=Antwort settings.webhook.response=Antwort

View File

@ -2066,8 +2066,6 @@ settings.hooks_desc=Τα Webhooks κάνουν αυτόματα αιτήσεις
settings.webhook_deletion=Αφαίρεση Webhook settings.webhook_deletion=Αφαίρεση Webhook
settings.webhook_deletion_desc=Η αφαίρεση ενός webhook διαγράφει τις ρυθμίσεις και το ιστορικό παραδόσεων. Συνέχεια; settings.webhook_deletion_desc=Η αφαίρεση ενός webhook διαγράφει τις ρυθμίσεις και το ιστορικό παραδόσεων. Συνέχεια;
settings.webhook_deletion_success=Το webhook έχει αφαιρεθεί. settings.webhook_deletion_success=Το webhook έχει αφαιρεθεί.
settings.webhook.test_delivery=Δοκιμή Παράδοσης
settings.webhook.test_delivery_desc=Δοκιμάστε αυτό το webhook με ένα ψεύτικο συμβάν.
settings.webhook.test_delivery_desc_disabled=Για να δοκιμάσετε αυτό το webhook με μια ψεύτικη κλήση, ενεργοποιήστε το. settings.webhook.test_delivery_desc_disabled=Για να δοκιμάσετε αυτό το webhook με μια ψεύτικη κλήση, ενεργοποιήστε το.
settings.webhook.request=Αίτημα settings.webhook.request=Αίτημα
settings.webhook.response=Απάντηση settings.webhook.response=Απάντηση

View File

@ -2334,8 +2334,8 @@ settings.hooks_desc = Webhooks automatically make HTTP POST requests to a server
settings.webhook_deletion = Remove Webhook settings.webhook_deletion = Remove Webhook
settings.webhook_deletion_desc = Removing a webhook deletes its settings and delivery history. Continue? settings.webhook_deletion_desc = Removing a webhook deletes its settings and delivery history. Continue?
settings.webhook_deletion_success = The webhook has been removed. settings.webhook_deletion_success = The webhook has been removed.
settings.webhook.test_delivery = Test Delivery settings.webhook.test_delivery = Test Push Event
settings.webhook.test_delivery_desc = Test this webhook with a fake event. settings.webhook.test_delivery_desc = Test this webhook with a fake push event.
settings.webhook.test_delivery_desc_disabled = To test this webhook with a fake event, activate it. settings.webhook.test_delivery_desc_disabled = To test this webhook with a fake event, activate it.
settings.webhook.request = Request settings.webhook.request = Request
settings.webhook.response = Response settings.webhook.response = Response
@ -2355,6 +2355,7 @@ settings.payload_url = Target URL
settings.http_method = HTTP Method settings.http_method = HTTP Method
settings.content_type = POST Content Type settings.content_type = POST Content Type
settings.secret = Secret settings.secret = Secret
settings.webhook_secret_desc = If the webhook server supports using secret, you can follow the webhook's manual and fill in a secret here.
settings.slack_username = Username settings.slack_username = Username
settings.slack_icon_url = Icon URL settings.slack_icon_url = Icon URL
settings.slack_color = Color settings.slack_color = Color
@ -2769,6 +2770,8 @@ branch.new_branch_from = Create new branch from "%s"
branch.renamed = Branch %s was renamed to %s. branch.renamed = Branch %s was renamed to %s.
branch.rename_default_or_protected_branch_error = Only admins can rename default or protected branches. branch.rename_default_or_protected_branch_error = Only admins can rename default or protected branches.
branch.rename_protected_branch_failed = This branch is protected by glob-based protection rules. branch.rename_protected_branch_failed = This branch is protected by glob-based protection rules.
branch.commits_divergence_from = Commits divergence: %[1]d behind and %[2]d ahead of %[3]s
branch.commits_no_divergence = The same as branch %[1]s
tag.create_tag = Create tag %s tag.create_tag = Create tag %s
tag.create_tag_operation = Create tag tag.create_tag_operation = Create tag
@ -2782,6 +2785,7 @@ topic.done = Done
topic.count_prompt = You cannot select more than 25 topics topic.count_prompt = You cannot select more than 25 topics
topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase. topic.format_prompt = Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
find_file.follow_symlink= Follow this symlink to where it is pointing at
find_file.go_to_file = Go to file find_file.go_to_file = Go to file
find_file.no_matching = No matching file found find_file.no_matching = No matching file found

View File

@ -2050,8 +2050,6 @@ settings.hooks_desc=Los webhooks automáticamente hacen peticiones HTTP POST a u
settings.webhook_deletion=Eliminar Webhook settings.webhook_deletion=Eliminar Webhook
settings.webhook_deletion_desc=Eliminar un webhook borra sus ajustes e historial de entrega. ¿Continuar? settings.webhook_deletion_desc=Eliminar un webhook borra sus ajustes e historial de entrega. ¿Continuar?
settings.webhook_deletion_success=El webhook ha sido eliminado. settings.webhook_deletion_success=El webhook ha sido eliminado.
settings.webhook.test_delivery=Test de entrega
settings.webhook.test_delivery_desc=Prueba este webhook con un evento falso.
settings.webhook.test_delivery_desc_disabled=Para probar este webhook con un evento falso, actívalo. settings.webhook.test_delivery_desc_disabled=Para probar este webhook con un evento falso, actívalo.
settings.webhook.request=Petición settings.webhook.request=Petición
settings.webhook.response=Respuesta settings.webhook.response=Respuesta

View File

@ -1591,8 +1591,6 @@ settings.hooks_desc=هوک تحت وب به صورت خودکار درخواست
settings.webhook_deletion=حذف Webhook settings.webhook_deletion=حذف Webhook
settings.webhook_deletion_desc=حذف هوک تحت وب موجب حذف تنظیمات آن و تاریخچه تحویل آن می‌شود. همچنان ادامه می‌دهید؟ settings.webhook_deletion_desc=حذف هوک تحت وب موجب حذف تنظیمات آن و تاریخچه تحویل آن می‌شود. همچنان ادامه می‌دهید؟
settings.webhook_deletion_success=هوک تحت وب حذف شد. settings.webhook_deletion_success=هوک تحت وب حذف شد.
settings.webhook.test_delivery=امتحان‌کردن تحویل
settings.webhook.test_delivery_desc=Webhook را با رویداد جعلی امتحان کنید.
settings.webhook.request=درخواست settings.webhook.request=درخواست
settings.webhook.response=پاسخ settings.webhook.response=پاسخ
settings.webhook.headers=سربرگ‎ها settings.webhook.headers=سربرگ‎ها

View File

@ -1097,7 +1097,6 @@ settings.teams=Tiimit
settings.add_team=Lisää tiimi settings.add_team=Lisää tiimi
settings.add_webhook=Lisää webkoukku settings.add_webhook=Lisää webkoukku
settings.webhook_deletion=Poista webkoukku settings.webhook_deletion=Poista webkoukku
settings.webhook.test_delivery=Testitoimitus
settings.webhook.request=Pyyntö settings.webhook.request=Pyyntö
settings.webhook.response=Vastaus settings.webhook.response=Vastaus
settings.webhook.headers=Otsikot settings.webhook.headers=Otsikot

View File

@ -1969,6 +1969,7 @@ pulls.cmd_instruction_checkout_title=Basculer
pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications. pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications.
pulls.cmd_instruction_merge_title=Fusionner pulls.cmd_instruction_merge_title=Fusionner
pulls.cmd_instruction_merge_desc=Fusionner les modifications et mettre à jour sur Gitea. pulls.cmd_instruction_merge_desc=Fusionner les modifications et mettre à jour sur Gitea.
pulls.cmd_instruction_merge_warning=Attention : cette opération ne peut pas fusionner la demande dajout car la « détection automatique de fusion manuelle » na pas été activée
pulls.clear_merge_message=Effacer le message de fusion pulls.clear_merge_message=Effacer le message de fusion
pulls.clear_merge_message_hint=Effacer le message de fusion ne supprimera que le message de la révision, mais pas les pieds de révision générés tels que "Co-Authored-By:". pulls.clear_merge_message_hint=Effacer le message de fusion ne supprimera que le message de la révision, mais pas les pieds de révision générés tels que "Co-Authored-By:".
@ -2333,8 +2334,6 @@ settings.hooks_desc=Les Webhooks font automatiquement des requêtes HTTP POST à
settings.webhook_deletion=Retirer le Webhook settings.webhook_deletion=Retirer le Webhook
settings.webhook_deletion_desc=Supprimer un webhook supprime ses paramètres et son historique. Continuer ? settings.webhook_deletion_desc=Supprimer un webhook supprime ses paramètres et son historique. Continuer ?
settings.webhook_deletion_success=Le webhook a été supprimé. settings.webhook_deletion_success=Le webhook a été supprimé.
settings.webhook.test_delivery=Tester l'envoi
settings.webhook.test_delivery_desc=Testez ce webhook avec un faux événement.
settings.webhook.test_delivery_desc_disabled=Pour tester ce webhook avec un faux événement, activez-le. settings.webhook.test_delivery_desc_disabled=Pour tester ce webhook avec un faux événement, activez-le.
settings.webhook.request=Requête settings.webhook.request=Requête
settings.webhook.response=Réponse settings.webhook.response=Réponse
@ -2768,6 +2767,8 @@ branch.new_branch_from=`Créer une nouvelle branche à partir de "%s"`
branch.renamed=La branche %s à été renommée en %s. branch.renamed=La branche %s à été renommée en %s.
branch.rename_default_or_protected_branch_error=Seuls les administrateurs peuvent renommer les branches par défaut ou protégées. branch.rename_default_or_protected_branch_error=Seuls les administrateurs peuvent renommer les branches par défaut ou protégées.
branch.rename_protected_branch_failed=Cette branche est protégée par des règles de protection basées sur des globs. branch.rename_protected_branch_failed=Cette branche est protégée par des règles de protection basées sur des globs.
branch.commits_divergence_from=Divergence de révisions : %[1]d en retard et %[2]d en avance sur %[3]s
branch.commits_no_divergence=Identique à la branche %[1]s
tag.create_tag=Créer l'étiquette %s tag.create_tag=Créer l'étiquette %s
tag.create_tag_operation=Créer une étiquette tag.create_tag_operation=Créer une étiquette

View File

@ -1969,6 +1969,7 @@ pulls.cmd_instruction_checkout_title=Seiceáil
pulls.cmd_instruction_checkout_desc=Ó stór tionscadail, seiceáil brainse nua agus déan tástáil ar na hathruithe. pulls.cmd_instruction_checkout_desc=Ó stór tionscadail, seiceáil brainse nua agus déan tástáil ar na hathruithe.
pulls.cmd_instruction_merge_title=Cumaisc pulls.cmd_instruction_merge_title=Cumaisc
pulls.cmd_instruction_merge_desc=Cumaisc na hathruithe agus nuashonrú ar Gitea. pulls.cmd_instruction_merge_desc=Cumaisc na hathruithe agus nuashonrú ar Gitea.
pulls.cmd_instruction_merge_warning=Rabhadh: Ní féidir iarratas tarraingthe cumaisc a dhéanamh leis an oibríocht seo mar nach bhfuil "autodetect manual merge" cumasaithe.
pulls.clear_merge_message=Glan an teachtaireacht chumaisc pulls.clear_merge_message=Glan an teachtaireacht chumaisc
pulls.clear_merge_message_hint=Má imrítear an teachtaireacht chumaisc ní bhainfear ach ábhar na teachtaireachta tiomanta agus coimeádfar leantóirí git ginte ar nós "Co-Authored-By …". pulls.clear_merge_message_hint=Má imrítear an teachtaireacht chumaisc ní bhainfear ach ábhar na teachtaireachta tiomanta agus coimeádfar leantóirí git ginte ar nós "Co-Authored-By …".
@ -2333,8 +2334,8 @@ settings.hooks_desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibr
settings.webhook_deletion=Bain Crúca Gréasán settings.webhook_deletion=Bain Crúca Gréasán
settings.webhook_deletion_desc=Scriostar a shocruithe agus a stair seachadta a bhaineann le Crúca Gréasán a bhaint. Lean ar aghaidh? settings.webhook_deletion_desc=Scriostar a shocruithe agus a stair seachadta a bhaineann le Crúca Gréasán a bhaint. Lean ar aghaidh?
settings.webhook_deletion_success=Tá an Crúca Gréasán bainte amach. settings.webhook_deletion_success=Tá an Crúca Gréasán bainte amach.
settings.webhook.test_delivery=Seachadadh Tástála settings.webhook.test_delivery=Imeacht Brúigh Tástála
settings.webhook.test_delivery_desc=Déan tástáil ar an Crúca Gréasán seo le himeacht bhréige. settings.webhook.test_delivery_desc=Déan tástáil ar an webhook seo le teagmhas brú bréige.
settings.webhook.test_delivery_desc_disabled=Chun an Crúca Gréasán seo a thástáil le himeacht bhréige, gníomhachtaigh é. settings.webhook.test_delivery_desc_disabled=Chun an Crúca Gréasán seo a thástáil le himeacht bhréige, gníomhachtaigh é.
settings.webhook.request=Iarratas settings.webhook.request=Iarratas
settings.webhook.response=Freagra settings.webhook.response=Freagra
@ -2354,6 +2355,7 @@ settings.payload_url=URL spriocdhírithe
settings.http_method=Modh HTTP settings.http_method=Modh HTTP
settings.content_type=Cineál Ábhar POST settings.content_type=Cineál Ábhar POST
settings.secret=Rúnda settings.secret=Rúnda
settings.webhook_secret_desc=Más féidir le freastalaí an webhook rún a úsáid, is féidir leat lámhleabhar an webhook a leanúint agus rún a líonadh isteach anseo.
settings.slack_username=Ainm úsáideora settings.slack_username=Ainm úsáideora
settings.slack_icon_url=URL deilbhín settings.slack_icon_url=URL deilbhín
settings.slack_color=Dath settings.slack_color=Dath
@ -2768,6 +2770,8 @@ branch.new_branch_from=`Cruthaigh brainse nua ó "%s"`
branch.renamed=Ainmníodh brainse %s go %s. branch.renamed=Ainmníodh brainse %s go %s.
branch.rename_default_or_protected_branch_error=Ní féidir ach le riarthóirí brainsí réamhshocraithe nó cosanta a athainmniú. branch.rename_default_or_protected_branch_error=Ní féidir ach le riarthóirí brainsí réamhshocraithe nó cosanta a athainmniú.
branch.rename_protected_branch_failed=Tá an brainse seo faoi chosaint ag rialacha cosanta domhanda. branch.rename_protected_branch_failed=Tá an brainse seo faoi chosaint ag rialacha cosanta domhanda.
branch.commits_divergence_from=Déanann sé dialltacht a thiomnú: %[1]d taobh thiar agus %[2]d chun tosaigh ar %[3]s
branch.commits_no_divergence=Mar an gcéanna le brainse %[1]s
tag.create_tag=Cruthaigh clib %s tag.create_tag=Cruthaigh clib %s
tag.create_tag_operation=Cruthaigh clib tag.create_tag_operation=Cruthaigh clib
@ -2781,6 +2785,7 @@ topic.done=Déanta
topic.count_prompt=Ní féidir leat níos mó ná 25 topaicí a roghnú topic.count_prompt=Ní féidir leat níos mó ná 25 topaicí a roghnú
topic.format_prompt=Ní mór do thopaicí tosú le litir nó uimhir, is féidir daiseanna ('-') agus poncanna ('.') a áireamh, a bheith suas le 35 carachtar ar fad. Ní mór litreacha a bheith i litreacha beaga. topic.format_prompt=Ní mór do thopaicí tosú le litir nó uimhir, is féidir daiseanna ('-') agus poncanna ('.') a áireamh, a bheith suas le 35 carachtar ar fad. Ní mór litreacha a bheith i litreacha beaga.
find_file.follow_symlink=Lean an nasc siombalach seo go dtí an áit a bhfuil sé ag pointeáil air
find_file.go_to_file=Téigh go dtí an comhad find_file.go_to_file=Téigh go dtí an comhad
find_file.no_matching=Níl aon chomhad meaitseála le fáil find_file.no_matching=Níl aon chomhad meaitseála le fáil

View File

@ -956,7 +956,6 @@ settings.delete_notices_1=- Operasi ini <strong>TIDAK BISA</strong> dibatalkan.
settings.delete_collaborator=Menghapus settings.delete_collaborator=Menghapus
settings.teams=Tim settings.teams=Tim
settings.add_webhook=Tambahkan Webhook settings.add_webhook=Tambahkan Webhook
settings.webhook.test_delivery=Percobaan Pengiriman
settings.webhook.request=Permintaan settings.webhook.request=Permintaan
settings.webhook.response=Tanggapan settings.webhook.response=Tanggapan
settings.webhook.headers=Tajuk settings.webhook.headers=Tajuk

View File

@ -1720,8 +1720,6 @@ settings.hooks_desc=I Webhook effettuano automaticamente richieste HTTP POST ad
settings.webhook_deletion=Rimuovi Webhook settings.webhook_deletion=Rimuovi Webhook
settings.webhook_deletion_desc=Rimuovere un webhook rimuove le sue impostazioni e la sua cronologia di consegna. Continuare? settings.webhook_deletion_desc=Rimuovere un webhook rimuove le sue impostazioni e la sua cronologia di consegna. Continuare?
settings.webhook_deletion_success=Il webhook è stato rimosso. settings.webhook_deletion_success=Il webhook è stato rimosso.
settings.webhook.test_delivery=Test di consegna
settings.webhook.test_delivery_desc=Prova questo webhook con un evento falso.
settings.webhook.request=Richiesta settings.webhook.request=Richiesta
settings.webhook.response=Risposta settings.webhook.response=Risposta
settings.webhook.headers=Intestazioni settings.webhook.headers=Intestazioni

View File

@ -2323,8 +2323,6 @@ settings.hooks_desc=Webhookは、指定したGiteaイベントが発生したと
settings.webhook_deletion=Webhookの削除 settings.webhook_deletion=Webhookの削除
settings.webhook_deletion_desc=Webhook設定と配信履歴が削除されます。 続行しますか? settings.webhook_deletion_desc=Webhook設定と配信履歴が削除されます。 続行しますか?
settings.webhook_deletion_success=Webhookを削除しました。 settings.webhook_deletion_success=Webhookを削除しました。
settings.webhook.test_delivery=テスト配信
settings.webhook.test_delivery_desc=ダミーのイベントでこのWebhookをテストします。
settings.webhook.test_delivery_desc_disabled=このWebhookをダミーのイベントでテストするには、有効にしてください。 settings.webhook.test_delivery_desc_disabled=このWebhookをダミーのイベントでテストするには、有効にしてください。
settings.webhook.request=リクエスト settings.webhook.request=リクエスト
settings.webhook.response=レスポンス settings.webhook.response=レスポンス

View File

@ -993,8 +993,6 @@ settings.teams=팀
settings.add_webhook=Webhook 추가 settings.add_webhook=Webhook 추가
settings.webhook_deletion=Webhook 삭제 settings.webhook_deletion=Webhook 삭제
settings.webhook_deletion_success=Webhook을 삭제했습니다. settings.webhook_deletion_success=Webhook을 삭제했습니다.
settings.webhook.test_delivery=전달 시험
settings.webhook.test_delivery_desc=이 웹훅을 가상 이벤트로 테스트
settings.webhook.request=요청 settings.webhook.request=요청
settings.webhook.response=응답 settings.webhook.response=응답
settings.webhook.headers=제목 settings.webhook.headers=제목

View File

@ -2072,8 +2072,6 @@ settings.hooks_desc=Tīmekļa āķi ļauj paziņot ārējiem servisiem par notei
settings.webhook_deletion=Noņemt tīmekļa āķi settings.webhook_deletion=Noņemt tīmekļa āķi
settings.webhook_deletion_desc=Noņemot tīmekļa āķi, tiks dzēsti visi tā iestatījumi un piegādes vēsture. Vai turpināt? settings.webhook_deletion_desc=Noņemot tīmekļa āķi, tiks dzēsti visi tā iestatījumi un piegādes vēsture. Vai turpināt?
settings.webhook_deletion_success=Tīmekļa āķis tika noņemts. settings.webhook_deletion_success=Tīmekļa āķis tika noņemts.
settings.webhook.test_delivery=Testa piegāde
settings.webhook.test_delivery_desc=Veikt viltus push-notikuma piegādi, lai notestētu Jūsu tīmekļa āķa iestatījumus.
settings.webhook.test_delivery_desc_disabled=Lai pārbaudītu šo tīmekļa āķi ar neīstu notikumu, tas ir jāiespējo. settings.webhook.test_delivery_desc_disabled=Lai pārbaudītu šo tīmekļa āķi ar neīstu notikumu, tas ir jāiespējo.
settings.webhook.request=Pieprasījums settings.webhook.request=Pieprasījums
settings.webhook.response=Atbilde settings.webhook.response=Atbilde

View File

@ -1666,8 +1666,6 @@ settings.hooks_desc=Webhooks maken automatisch een HTTP POST verzoek naar een se
settings.webhook_deletion=Verwijder webhook settings.webhook_deletion=Verwijder webhook
settings.webhook_deletion_desc=Verwijderen van een webhook verwijdert de instellingen en de geschiedenis van afleveringen. Doorgaan? settings.webhook_deletion_desc=Verwijderen van een webhook verwijdert de instellingen en de geschiedenis van afleveringen. Doorgaan?
settings.webhook_deletion_success=Webhook is verwijderd. settings.webhook_deletion_success=Webhook is verwijderd.
settings.webhook.test_delivery=Test-bezorging
settings.webhook.test_delivery_desc=Test deze webhook met een nep-gebeurtenis.
settings.webhook.request=Verzoek settings.webhook.request=Verzoek
settings.webhook.response=Antwoord settings.webhook.response=Antwoord
settings.webhook.headers=Headers settings.webhook.headers=Headers

View File

@ -1553,8 +1553,6 @@ settings.hooks_desc=Webhooki automatycznie tworzą zapytania HTTP POST do serwer
settings.webhook_deletion=Usuń Webhooka settings.webhook_deletion=Usuń Webhooka
settings.webhook_deletion_desc=Usunięcie Webhooka wykasuje jego ustawienia i historię dostaw. Kontynuować? settings.webhook_deletion_desc=Usunięcie Webhooka wykasuje jego ustawienia i historię dostaw. Kontynuować?
settings.webhook_deletion_success=Webhook został usunięty. settings.webhook_deletion_success=Webhook został usunięty.
settings.webhook.test_delivery=Testuj dostawę
settings.webhook.test_delivery_desc=Sprawdź tego Webhooka przy pomocy testowego zdarzenia.
settings.webhook.request=Żądanie settings.webhook.request=Żądanie
settings.webhook.response=Odpowiedź settings.webhook.response=Odpowiedź
settings.webhook.headers=Nagłówki settings.webhook.headers=Nagłówki

View File

@ -2055,8 +2055,6 @@ settings.hooks_desc=Webhooks automaticamente fazem requisições de HTTP POST pa
settings.webhook_deletion=Remover webhook settings.webhook_deletion=Remover webhook
settings.webhook_deletion_desc=A exclusão de um webhook exclui suas configurações e o histórico de entrega. Continuar? settings.webhook_deletion_desc=A exclusão de um webhook exclui suas configurações e o histórico de entrega. Continuar?
settings.webhook_deletion_success=O webhook foi removido. settings.webhook_deletion_success=O webhook foi removido.
settings.webhook.test_delivery=Entrega de teste
settings.webhook.test_delivery_desc=Teste este webhook com um falso evento.
settings.webhook.request=Solicitação settings.webhook.request=Solicitação
settings.webhook.response=Resposta settings.webhook.response=Resposta
settings.webhook.headers=Cabeçalhos settings.webhook.headers=Cabeçalhos

View File

@ -1562,8 +1562,8 @@ issues.filter_project=Planeamento
issues.filter_project_all=Todos os planeamentos issues.filter_project_all=Todos os planeamentos
issues.filter_project_none=Nenhum planeamento issues.filter_project_none=Nenhum planeamento
issues.filter_assignee=Encarregado issues.filter_assignee=Encarregado
issues.filter_assignee_no_assignee=Não atribuído issues.filter_assignee_no_assignee=Não atribuída
issues.filter_assignee_any_assignee=Atribuído a qualquer pessoa issues.filter_assignee_any_assignee=Atribuída a alguém
issues.filter_poster=Autor(a) issues.filter_poster=Autor(a)
issues.filter_user_placeholder=Procurar utilizadores issues.filter_user_placeholder=Procurar utilizadores
issues.filter_user_no_select=Todos os utilizadores issues.filter_user_no_select=Todos os utilizadores
@ -1969,6 +1969,7 @@ pulls.cmd_instruction_checkout_title=Checkout
pulls.cmd_instruction_checkout_desc=A partir do seu repositório, crie um novo ramo e teste nele as modificações. pulls.cmd_instruction_checkout_desc=A partir do seu repositório, crie um novo ramo e teste nele as modificações.
pulls.cmd_instruction_merge_title=Integrar pulls.cmd_instruction_merge_title=Integrar
pulls.cmd_instruction_merge_desc=Integrar as modificações e enviar para o Gitea. pulls.cmd_instruction_merge_desc=Integrar as modificações e enviar para o Gitea.
pulls.cmd_instruction_merge_warning=Aviso: Esta operação não pode executar pedidos de integração porque a opção "auto-identificar integração manual" não está habilitada.
pulls.clear_merge_message=Apagar mensagem de integração pulls.clear_merge_message=Apagar mensagem de integração
pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …". pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …".
@ -2333,8 +2334,6 @@ settings.hooks_desc=Os automatismos web fazem pedidos HTTP POST automaticamente
settings.webhook_deletion=Remover automatismo web settings.webhook_deletion=Remover automatismo web
settings.webhook_deletion_desc=Remover um automatismo web elimina as configurações e o histórico de entrega desse automatismo. Quer continuar? settings.webhook_deletion_desc=Remover um automatismo web elimina as configurações e o histórico de entrega desse automatismo. Quer continuar?
settings.webhook_deletion_success=O automatismo web foi removido. settings.webhook_deletion_success=O automatismo web foi removido.
settings.webhook.test_delivery=Entrega de teste
settings.webhook.test_delivery_desc=Testar este automatismo web com um evento falso.
settings.webhook.test_delivery_desc_disabled=Para testar este automatismo web com um evento falso, habilite-o. settings.webhook.test_delivery_desc_disabled=Para testar este automatismo web com um evento falso, habilite-o.
settings.webhook.request=Pedido settings.webhook.request=Pedido
settings.webhook.response=Resposta settings.webhook.response=Resposta
@ -2354,6 +2353,7 @@ settings.payload_url=URL de destino
settings.http_method=Método HTTP settings.http_method=Método HTTP
settings.content_type=Tipo de conteúdo POST settings.content_type=Tipo de conteúdo POST
settings.secret=Segredo settings.secret=Segredo
settings.webhook_secret_desc=Se o servidor de automatismos web suportar a utilização de segredos, você pode seguir o manual do automatismo web e preencher um segredo aqui.
settings.slack_username=Nome de utilizador settings.slack_username=Nome de utilizador
settings.slack_icon_url=URL do ícone settings.slack_icon_url=URL do ícone
settings.slack_color=Cor settings.slack_color=Cor
@ -2768,6 +2768,8 @@ branch.new_branch_from=`Criar um novo ramo a partir do ramo "%s"`
branch.renamed=O ramo %s foi renomeado para %s. branch.renamed=O ramo %s foi renomeado para %s.
branch.rename_default_or_protected_branch_error=Só os administradores é que podem renomear o ramo principal ou ramos protegidos. branch.rename_default_or_protected_branch_error=Só os administradores é que podem renomear o ramo principal ou ramos protegidos.
branch.rename_protected_branch_failed=Este ramo está protegido por regras de salvaguarda baseadas em padrões glob. branch.rename_protected_branch_failed=Este ramo está protegido por regras de salvaguarda baseadas em padrões glob.
branch.commits_divergence_from=Divergência nos cometimentos: %[1]d atrás e %[2]d à frente de %[3]s
branch.commits_no_divergence=Idêntico ao ramo %[1]s
tag.create_tag=Criar etiqueta %s tag.create_tag=Criar etiqueta %s
tag.create_tag_operation=Criar etiqueta tag.create_tag_operation=Criar etiqueta
@ -2781,6 +2783,7 @@ topic.done=Concluído
topic.count_prompt=Não pode escolher mais do que 25 tópicos topic.count_prompt=Não pode escolher mais do que 25 tópicos
topic.format_prompt=Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') ou pontos ('.') e podem ter até 35 caracteres. As letras têm que ser minúsculas. topic.format_prompt=Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') ou pontos ('.') e podem ter até 35 caracteres. As letras têm que ser minúsculas.
find_file.follow_symlink=Seguir esta ligação simbólica para onde ela está apontando
find_file.go_to_file=Ir para o ficheiro find_file.go_to_file=Ir para o ficheiro
find_file.no_matching=Não foi encontrado qualquer ficheiro correspondente find_file.no_matching=Não foi encontrado qualquer ficheiro correspondente

View File

@ -2025,8 +2025,6 @@ settings.hooks_desc=Веб-хуки позволяют внешним служб
settings.webhook_deletion=Удалить веб-хук settings.webhook_deletion=Удалить веб-хук
settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей связанной с ним информации, включая историю. Хотите продолжить? settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей связанной с ним информации, включая историю. Хотите продолжить?
settings.webhook_deletion_success=Веб-хук был удалён. settings.webhook_deletion_success=Веб-хук был удалён.
settings.webhook.test_delivery=Проверить доставку
settings.webhook.test_delivery_desc=Отправить тестовое событие для тестирования настройки веб-хука.
settings.webhook.request=Запрос settings.webhook.request=Запрос
settings.webhook.response=Ответ settings.webhook.response=Ответ
settings.webhook.headers=Заголовки settings.webhook.headers=Заголовки

View File

@ -1555,8 +1555,6 @@ settings.hooks_desc=ඇතැම් Gitea සිදුවීම් අවුල
settings.webhook_deletion=වෙබ්හූක් ඉවත් කරන්න settings.webhook_deletion=වෙබ්හූක් ඉවත් කරන්න
settings.webhook_deletion_desc=වෙබ්කොක්කක් ඉවත් කිරීම එහි සැකසුම් සහ බෙදාහැරීමේ ඉතිහාසය මකා දමයි. දිගටම? settings.webhook_deletion_desc=වෙබ්කොක්කක් ඉවත් කිරීම එහි සැකසුම් සහ බෙදාහැරීමේ ඉතිහාසය මකා දමයි. දිගටම?
settings.webhook_deletion_success=වෙබ්කොක්කෙන් ඉවත් කර ඇත. settings.webhook_deletion_success=වෙබ්කොක්කෙන් ඉවත් කර ඇත.
settings.webhook.test_delivery=ටෙස්ට් සැපයුම්
settings.webhook.test_delivery_desc=ව්යාජ සිදුවීමකින් මෙම වෙබ්කොක්කෙන් පරීක්ෂා කරන්න.
settings.webhook.request=ඉල්ලීම settings.webhook.request=ඉල්ලීම
settings.webhook.response=ප්‍රතිචාරය settings.webhook.response=ප්‍රතිචාරය
settings.webhook.headers=ශීර්ෂ settings.webhook.headers=ශීර්ෂ

View File

@ -1165,7 +1165,6 @@ settings.hooks_desc=Webhooky automaticky odosielajú požiadavky HTTP POST na se
settings.webhook_deletion=Odstrániť webhook settings.webhook_deletion=Odstrániť webhook
settings.webhook_deletion_desc=Odstránením webhooku sa vymažú jeho nastavenia a história doručovania. Ďalej? settings.webhook_deletion_desc=Odstránením webhooku sa vymažú jeho nastavenia a história doručovania. Ďalej?
settings.webhook_deletion_success=Webhook bol odstránený. settings.webhook_deletion_success=Webhook bol odstránený.
settings.webhook.test_delivery_desc=Otestujte tento webhook pomocou testovacej udalosti.
settings.webhook.replay.description=Zopakujte tento webhook. settings.webhook.replay.description=Zopakujte tento webhook.
settings.add_webhook_desc=Gitea odošle požiadavky <code>POST</code> so špecifikovaným typom obsahu na cieľovú adresu URL. Prečítajte si viac v <a target="_blank" rel="noopener noreferrer" href="%s">sprievodcovi webhookmi</a>. settings.add_webhook_desc=Gitea odošle požiadavky <code>POST</code> so špecifikovaným typom obsahu na cieľovú adresu URL. Prečítajte si viac v <a target="_blank" rel="noopener noreferrer" href="%s">sprievodcovi webhookmi</a>.
settings.event_header_repository=Udalosti repozitára settings.event_header_repository=Udalosti repozitára

View File

@ -1292,8 +1292,6 @@ settings.hooks_desc=Webhooks gör automatiskt ett HTTP POST anrop mot en server
settings.webhook_deletion=Ta bort Webhook settings.webhook_deletion=Ta bort Webhook
settings.webhook_deletion_desc=Borttagning utav en webhook tar även bort dess inställningar och leveranshistorik. Vill du fortsätta? settings.webhook_deletion_desc=Borttagning utav en webhook tar även bort dess inställningar och leveranshistorik. Vill du fortsätta?
settings.webhook_deletion_success=Webhooken har blivit borttagen. settings.webhook_deletion_success=Webhooken har blivit borttagen.
settings.webhook.test_delivery=Testa Leverans
settings.webhook.test_delivery_desc=Testa webhooken genom ett testevent.
settings.webhook.request=Begäran settings.webhook.request=Begäran
settings.webhook.response=Svar settings.webhook.response=Svar
settings.webhook.headers=Huvuden settings.webhook.headers=Huvuden

View File

@ -2310,8 +2310,6 @@ settings.hooks_desc=Web istemcileri, belirli Gitea olayları tetiklendiğinde ot
settings.webhook_deletion=Web İsteğini Sil settings.webhook_deletion=Web İsteğini Sil
settings.webhook_deletion_desc=Bir web isteğini kaldırmak, ayarlarını ve teslimat geçmişini siler. Devam edilsin mi? settings.webhook_deletion_desc=Bir web isteğini kaldırmak, ayarlarını ve teslimat geçmişini siler. Devam edilsin mi?
settings.webhook_deletion_success=Web isteği silindi. settings.webhook_deletion_success=Web isteği silindi.
settings.webhook.test_delivery=Test Dağıtımı
settings.webhook.test_delivery_desc=Bu web isteğini sahte bir olayla test edin.
settings.webhook.test_delivery_desc_disabled=Bu web istemcisini sahte bir olayla denemek için etkinleştirin. settings.webhook.test_delivery_desc_disabled=Bu web istemcisini sahte bir olayla denemek için etkinleştirin.
settings.webhook.request=İstekler settings.webhook.request=İstekler
settings.webhook.response=Cevaplar settings.webhook.response=Cevaplar

View File

@ -2215,8 +2215,6 @@ settings.hooks_desc=Веб-хуки автоматично роблять HTTP P
settings.webhook_deletion=Видалити веб-хук settings.webhook_deletion=Видалити веб-хук
settings.webhook_deletion_desc=Видалення веб-хука видаляє його налаштування та історію доставки. Продовжити? settings.webhook_deletion_desc=Видалення веб-хука видаляє його налаштування та історію доставки. Продовжити?
settings.webhook_deletion_success=Веб-хук видалено. settings.webhook_deletion_success=Веб-хук видалено.
settings.webhook.test_delivery=Перевірити доставку
settings.webhook.test_delivery_desc=Перевірте цей веб-хук з фальшивою подією.
settings.webhook.request=Запит settings.webhook.request=Запит
settings.webhook.response=Відповідь settings.webhook.response=Відповідь
settings.webhook.headers=Заголовки settings.webhook.headers=Заголовки

View File

@ -420,8 +420,9 @@ remember_me=记住此设备
remember_me.compromised=登录令牌不再有效,因为它可能表明帐户已被破坏。请检查您的帐户是否有异常活动。 remember_me.compromised=登录令牌不再有效,因为它可能表明帐户已被破坏。请检查您的帐户是否有异常活动。
forgot_password_title=忘记密码 forgot_password_title=忘记密码
forgot_password=忘记密码? forgot_password=忘记密码?
need_account=需要一个帐户? need_account=需要一个帐户?
sign_up_now=还没账号?马上注册。 sign_up_tip=您正在系统中注册第一个帐户,它拥有管理员权限。请仔细记住您的用户名和密码。 如果您忘记了用户名或密码,请参阅 Gitea 文档以恢复账户。
sign_up_now=立即注册。
sign_up_successful=帐户创建成功。欢迎! sign_up_successful=帐户创建成功。欢迎!
confirmation_mail_sent_prompt_ex=一封新的确认邮件已经发送到 <b>%s</b>。请在下一个 %s 中检查您的收件箱以完成注册流程。 如果您的注册邮箱地址不正确,您可以重新登录并更改它。 confirmation_mail_sent_prompt_ex=一封新的确认邮件已经发送到 <b>%s</b>。请在下一个 %s 中检查您的收件箱以完成注册流程。 如果您的注册邮箱地址不正确,您可以重新登录并更改它。
must_change_password=更新您的密码 must_change_password=更新您的密码
@ -485,7 +486,7 @@ sspi_auth_failed=SSPI 认证失败
password_pwned=此密码出现在 <a target="_blank" rel="noopener noreferrer" href="%s">被盗密码</a> 列表上并且曾经被公开。 请使用另一个密码再试一次。 password_pwned=此密码出现在 <a target="_blank" rel="noopener noreferrer" href="%s">被盗密码</a> 列表上并且曾经被公开。 请使用另一个密码再试一次。
password_pwned_err=无法完成对 HaveIBeenPwned 的请求 password_pwned_err=无法完成对 HaveIBeenPwned 的请求
last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。 last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。
signin_passkey=使用密钥登录 signin_passkey=使用通行密钥登录
back_to_sign_in=返回登录页面 back_to_sign_in=返回登录页面
[mail] [mail]
@ -518,7 +519,7 @@ register_success=注册成功
issue_assigned.pull=@%[1]s 已将仓库 %[3]s 中的合并请求 %[2]s 指派给您 issue_assigned.pull=@%[1]s 已将仓库 %[3]s 中的合并请求 %[2]s 指派给您
issue_assigned.issue=@%[1]s 已将仓库 %[3]s 中的工单 %[2]s 指派给您 issue_assigned.issue=@%[1]s 已将仓库 %[3]s 中的工单 %[2]s 指派给您
issue.x_mentioned_you=<b>@%s</b> 提了您: issue.x_mentioned_you=<b>@%s</b> 提了您:
issue.action.force_push=<b>%[1]s</b> 强制从 %[3]s 推送 <b>%[2]s</b> 至 [4]s。 issue.action.force_push=<b>%[1]s</b> 强制从 %[3]s 推送 <b>%[2]s</b> 至 [4]s。
issue.action.push_1=<b>@%[1]s</b> 推送了 %[3]d 个提交到 %[2]s issue.action.push_1=<b>@%[1]s</b> 推送了 %[3]d 个提交到 %[2]s
issue.action.push_n=<b>@%[1]s</b> 推送了 %[3]d 个提交到 %[2]s issue.action.push_n=<b>@%[1]s</b> 推送了 %[3]d 个提交到 %[2]s
@ -838,7 +839,7 @@ ssh_desc=这些 SSH 公钥已经关联到您的账号。相应的私钥拥有完
principal_desc=这些 SSH 证书规则已关联到您的账号将允许完全访问您所有仓库。 principal_desc=这些 SSH 证书规则已关联到您的账号将允许完全访问您所有仓库。
gpg_desc=这些 GPG 公钥已经关联到您的账号。请妥善保管您的私钥因为他们将被用于认证提交。 gpg_desc=这些 GPG 公钥已经关联到您的账号。请妥善保管您的私钥因为他们将被用于认证提交。
ssh_helper=<strong>需要帮助?</strong> 请查看有关 <a href="%s">如何生成 SSH 密钥</a> 或 <a href="%s">常见 SSH 问题</a> 寻找答案。 ssh_helper=<strong>需要帮助?</strong> 请查看有关 <a href="%s">如何生成 SSH 密钥</a> 或 <a href="%s">常见 SSH 问题</a> 寻找答案。
gpg_helper=<strong>需要帮助</strong>看一看 GitHub <a href="%s">关于 GPG</a> 的指导。 gpg_helper=<strong>需要帮助</strong>看一看 GitHub <a href="%s">关于 GPG</a> 的指导。
add_new_key=增加 SSH 密钥 add_new_key=增加 SSH 密钥
add_new_gpg_key=添加的 GPG 密钥 add_new_gpg_key=添加的 GPG 密钥
key_content_ssh_placeholder=以 'ssh-ed25519'、 'ssh-rsa'、 'ecdsa-sha2-nistp256'、'ecdsa-sha2-nistp384'、'ecdsa-sha2-nistp521'、 'sk-ecdsa-sha2-nistp256@openssh.com' 或 'sk-ssh-ed25519@openssh.com' 开头 key_content_ssh_placeholder=以 'ssh-ed25519'、 'ssh-rsa'、 'ecdsa-sha2-nistp256'、'ecdsa-sha2-nistp384'、'ecdsa-sha2-nistp521'、 'sk-ecdsa-sha2-nistp256@openssh.com' 或 'sk-ssh-ed25519@openssh.com' 开头
@ -1016,10 +1017,10 @@ delete_account_title=删除当前帐户
delete_account_desc=确实要永久删除此用户帐户吗? delete_account_desc=确实要永久删除此用户帐户吗?
email_notifications.enable=启用邮件通知 email_notifications.enable=启用邮件通知
email_notifications.onmention=只在被提到时邮件通知 email_notifications.onmention=仅被提及时通知
email_notifications.disable=停用邮件通知 email_notifications.disable=停用邮件通知
email_notifications.submit=邮件通知设置 email_notifications.submit=设置邮件通知
email_notifications.andyourown=和您自己的通知 email_notifications.andyourown=仅与您相关的通知
visibility=用户可见性 visibility=用户可见性
visibility.public=公开 visibility.public=公开
@ -1061,6 +1062,7 @@ fork_no_valid_owners=这个代码仓库无法被派生,因为没有有效的
fork.blocked_user=无法克隆仓库,因为您被仓库所有者屏蔽。 fork.blocked_user=无法克隆仓库,因为您被仓库所有者屏蔽。
use_template=使用此模板 use_template=使用此模板
open_with_editor=用 %s 打开 open_with_editor=用 %s 打开
download_zip=下载 ZIP download_zip=下载 ZIP
download_tar=下载 TAR.GZ download_tar=下载 TAR.GZ
download_bundle=下载 BUNDLE download_bundle=下载 BUNDLE
@ -1070,12 +1072,12 @@ repo_desc=描述
repo_desc_helper=输入简要描述 (可选) repo_desc_helper=输入简要描述 (可选)
repo_no_desc=无详细信息 repo_no_desc=无详细信息
repo_lang=语言 repo_lang=语言
repo_gitignore_helper=选择 .gitignore 模板 repo_gitignore_helper=选择 .gitignore 模板
repo_gitignore_helper_desc=从常见语言的模板列表中选择忽略跟踪的文件。默认情况下,由开发或构建工具生成的特殊文件都包含在 .gitignore 中。 repo_gitignore_helper_desc=从常见语言的模板列表中选择忽略跟踪的文件。默认情况下,由开发或构建工具生成的特殊文件都包含在 .gitignore 中。
issue_labels=工单标签 issue_labels=工单标签
issue_labels_helper=选择一个工单标签集 issue_labels_helper=选择一个工单标签集
license=授权许可 license=授权许可
license_helper=选择授权许可文件 license_helper=选择授权许可文件
license_helper_desc=许可证说明了其他人可以和不可以用您的代码做什么。不确定哪一个适合您的项目?见 <a target="_blank" rel="noopener noreferrer" href="%s">选择一个许可证</a> license_helper_desc=许可证说明了其他人可以和不可以用您的代码做什么。不确定哪一个适合您的项目?见 <a target="_blank" rel="noopener noreferrer" href="%s">选择一个许可证</a>
multiple_licenses=多许可证 multiple_licenses=多许可证
object_format=对象格式 object_format=对象格式
@ -1228,6 +1230,7 @@ migrate.migrating_issues=迁移工单
migrate.migrating_pulls=迁移合并请求 migrate.migrating_pulls=迁移合并请求
migrate.cancel_migrating_title=取消迁移 migrate.cancel_migrating_title=取消迁移
migrate.cancel_migrating_confirm=您想要取消此次迁移吗? migrate.cancel_migrating_confirm=您想要取消此次迁移吗?
migration_status=迁移状态
mirror_from=镜像自地址 mirror_from=镜像自地址
forked_from=派生自 forked_from=派生自
@ -1353,6 +1356,7 @@ editor.update=更新 %s
editor.delete=删除 %s editor.delete=删除 %s
editor.patch=应用补丁 editor.patch=应用补丁
editor.patching=打补丁: editor.patching=打补丁:
editor.fail_to_apply_patch=无法应用补丁
editor.new_patch=新补丁 editor.new_patch=新补丁
editor.commit_message_desc=添加一个可选的扩展描述... editor.commit_message_desc=添加一个可选的扩展描述...
editor.signoff_desc=在提交日志消息末尾添加签署人信息。 editor.signoff_desc=在提交日志消息末尾添加签署人信息。
@ -1372,6 +1376,7 @@ editor.branch_already_exists=此仓库已存在名为「%s」的分支。
editor.directory_is_a_file=目录名「%s」已作为文件名在此仓库中存在。 editor.directory_is_a_file=目录名「%s」已作为文件名在此仓库中存在。
editor.file_is_a_symlink=`「%s」是一个符号链接无法在 Web 编辑器中编辑` editor.file_is_a_symlink=`「%s」是一个符号链接无法在 Web 编辑器中编辑`
editor.filename_is_a_directory=文件名「%s」已作为目录名在此仓库中存在。 editor.filename_is_a_directory=文件名「%s」已作为目录名在此仓库中存在。
editor.file_modifying_no_longer_exists=正在修改的文件「%s」已不存在于此仓库。
editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。<a target="_blank" rel="noopener noreferrer" href="%s">单击此处</a> 查看变动的具体内容,或者 <strong>再次提交</strong> 覆盖已发生的变动。 editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。<a target="_blank" rel="noopener noreferrer" href="%s">单击此处</a> 查看变动的具体内容,或者 <strong>再次提交</strong> 覆盖已发生的变动。
editor.file_already_exists=此仓库已经存在名为「%s」的文件。 editor.file_already_exists=此仓库已经存在名为「%s」的文件。
editor.commit_id_not_matching=提交 ID 与您开始编辑时的 ID 不匹配。请提交到补丁分支然后合并。 editor.commit_id_not_matching=提交 ID 与您开始编辑时的 ID 不匹配。请提交到补丁分支然后合并。
@ -1392,7 +1397,15 @@ editor.user_no_push_to_branch=用户不能推送到分支
editor.require_signed_commit=分支需要签名提交 editor.require_signed_commit=分支需要签名提交
editor.cherry_pick=拣选提交 %s 到: editor.cherry_pick=拣选提交 %s 到:
editor.revert=将 %s 还原到: editor.revert=将 %s 还原到:
editor.failed_to_commit=提交更改失败。
editor.failed_to_commit_summary=错误信息:
editor.fork_create=派生仓库发起请求变更
editor.fork_create_description=您不能直接编辑此仓库。您可以从此仓库派生,进行编辑并创建一个拉取请求。
editor.fork_edit_description=您不能直接编辑此仓库。 更改将写入您的派生仓库 <b>%s</b>,以便您可以创建一个拉取请求。
editor.fork_not_editable=你已经派生了这个仓库,但是你的分叉是不可编辑的。
editor.fork_failed_to_push_branch=推送分支 %s 到仓库失败。
editor.fork_branch_exists=分支 "%s" 已存在于您的派生仓库中,请选择一个新的分支名称。
commits.desc=浏览代码修改历史 commits.desc=浏览代码修改历史
commits.commits=次代码提交 commits.commits=次代码提交
@ -1714,6 +1727,8 @@ issues.remove_time_estimate_at=删除预估时间 %s
issues.time_estimate_invalid=预计时间格式无效 issues.time_estimate_invalid=预计时间格式无效
issues.start_tracking_history=`开始工作 %s` issues.start_tracking_history=`开始工作 %s`
issues.tracker_auto_close=当此工单关闭时,自动停止计时器 issues.tracker_auto_close=当此工单关闭时,自动停止计时器
issues.stopwatch_already_stopped=此工单的计时器已经停止
issues.stopwatch_already_created=此工单的计时器已经存在
issues.tracking_already_started=`您已经开始对 <a href="%s">另一个工单</a> 进行时间跟踪!` issues.tracking_already_started=`您已经开始对 <a href="%s">另一个工单</a> 进行时间跟踪!`
issues.stop_tracking=停止计时器 issues.stop_tracking=停止计时器
issues.stop_tracking_history=工作 <b>%[1]s</b> 于 %[2]s 停止 issues.stop_tracking_history=工作 <b>%[1]s</b> 于 %[2]s 停止
@ -1955,6 +1970,7 @@ pulls.cmd_instruction_checkout_title=检出
pulls.cmd_instruction_checkout_desc=从您的仓库中检出一个新的分支并测试变更。 pulls.cmd_instruction_checkout_desc=从您的仓库中检出一个新的分支并测试变更。
pulls.cmd_instruction_merge_title=合并 pulls.cmd_instruction_merge_title=合并
pulls.cmd_instruction_merge_desc=合并变更并更新到 Gitea 上 pulls.cmd_instruction_merge_desc=合并变更并更新到 Gitea 上
pulls.cmd_instruction_merge_warning=警告:此操作不能合并该合并请求,因为「自动检测手动合并」未启用
pulls.clear_merge_message=清除合并信息 pulls.clear_merge_message=清除合并信息
pulls.clear_merge_message_hint=清除合并消息只会删除提交消息内容,并保留生成的 Git 附加内容如「Co-Authored-By…」。 pulls.clear_merge_message_hint=清除合并消息只会删除提交消息内容,并保留生成的 Git 附加内容如「Co-Authored-By…」。
@ -2150,6 +2166,7 @@ settings.collaboration.write=可写权限
settings.collaboration.read=可读权限 settings.collaboration.read=可读权限
settings.collaboration.owner=所有者 settings.collaboration.owner=所有者
settings.collaboration.undefined=未定义 settings.collaboration.undefined=未定义
settings.collaboration.per_unit=单元权限
settings.hooks=Web 钩子 settings.hooks=Web 钩子
settings.githooks=管理 Git 钩子 settings.githooks=管理 Git 钩子
settings.basic_settings=基本设置 settings.basic_settings=基本设置
@ -2318,8 +2335,6 @@ settings.hooks_desc=当 Gitea 事件发生时Web 钩子自动发出 HTTP POST
settings.webhook_deletion=删除 Web 钩子 settings.webhook_deletion=删除 Web 钩子
settings.webhook_deletion_desc=删除 Web 钩子将删除其设置和历史记录。继续? settings.webhook_deletion_desc=删除 Web 钩子将删除其设置和历史记录。继续?
settings.webhook_deletion_success=Web 钩子删除成功! settings.webhook_deletion_success=Web 钩子删除成功!
settings.webhook.test_delivery=测试推送
settings.webhook.test_delivery_desc=用假事件测试这个 Web 钩子。
settings.webhook.test_delivery_desc_disabled=要用假事件测试这个 Web钩子请激活它。 settings.webhook.test_delivery_desc_disabled=要用假事件测试这个 Web钩子请激活它。
settings.webhook.request=请求内容 settings.webhook.request=请求内容
settings.webhook.response=响应内容 settings.webhook.response=响应内容
@ -2368,6 +2383,7 @@ settings.event_repository=仓库
settings.event_repository_desc=创建或删除仓库 settings.event_repository_desc=创建或删除仓库
settings.event_header_issue=工单事件 settings.event_header_issue=工单事件
settings.event_issues=工单 settings.event_issues=工单
settings.event_issues_desc=工单已打开、已关闭、已重新打开或已编辑。
settings.event_issue_assign=工单已指派 settings.event_issue_assign=工单已指派
settings.event_issue_assign_desc=工单已指派或取消指派。 settings.event_issue_assign_desc=工单已指派或取消指派。
settings.event_issue_label=工单增删标签 settings.event_issue_label=工单增删标签
@ -2378,6 +2394,7 @@ settings.event_issue_comment=工单评论
settings.event_issue_comment_desc=工单评论已创建、编辑或删除。 settings.event_issue_comment_desc=工单评论已创建、编辑或删除。
settings.event_header_pull_request=合并请求事件 settings.event_header_pull_request=合并请求事件
settings.event_pull_request=合并请求 settings.event_pull_request=合并请求
settings.event_pull_request_desc=合并请求已打开、关闭、重新打开或编辑。
settings.event_pull_request_assign=合并请求已指派 settings.event_pull_request_assign=合并请求已指派
settings.event_pull_request_assign_desc=合并请求已指派或取消指派。 settings.event_pull_request_assign_desc=合并请求已指派或取消指派。
settings.event_pull_request_label=合并请求增删标签 settings.event_pull_request_label=合并请求增删标签
@ -2395,6 +2412,8 @@ settings.event_pull_request_review_request_desc=合并请求评审已请求或
settings.event_pull_request_approvals=合并请求批准 settings.event_pull_request_approvals=合并请求批准
settings.event_pull_request_merge=合并请求合并 settings.event_pull_request_merge=合并请求合并
settings.event_header_workflow=工作流程事件 settings.event_header_workflow=工作流程事件
settings.event_workflow_run=工作流运行
settings.event_workflow_run_desc=Gitea 工作流队列中、等待中、正在进行或已完成的任务。
settings.event_workflow_job=工作流任务 settings.event_workflow_job=工作流任务
settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在进行或已完成的任务。 settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在进行或已完成的任务。
settings.event_package=软件包 settings.event_package=软件包
@ -2773,7 +2792,7 @@ error.broken_git_hook=此仓库的 Git 钩子似乎已损坏。 请按照 <a tar
[graphs] [graphs]
component_loading=正在加载 %s... component_loading=正在加载 %s...
component_loading_failed=无法加载 %s component_loading_failed=无法加载 %s
component_loading_info=这可能需要一点 component_loading_info=这可能需要一点时间
component_failed_to_load=意外的错误发生了。 component_failed_to_load=意外的错误发生了。
code_frequency.what=代码频率 code_frequency.what=代码频率
contributors.what=贡献 contributors.what=贡献
@ -2802,6 +2821,7 @@ team_permission_desc=权限
team_unit_desc=允许访问仓库单元 team_unit_desc=允许访问仓库单元
team_unit_disabled=(已禁用) team_unit_disabled=(已禁用)
form.name_been_taken=组织名称「%s」已经被占用。
form.name_reserved=组织名称「%s」是保留的。 form.name_reserved=组织名称「%s」是保留的。
form.name_pattern_not_allowed=组织名中不允许使用「%s」格式。 form.name_pattern_not_allowed=组织名中不允许使用「%s」格式。
form.create_org_not_allowed=此账号禁止创建组织 form.create_org_not_allowed=此账号禁止创建组织
@ -2824,12 +2844,27 @@ settings.visibility.private_shortname=私有
settings.update_settings=更新组织设置 settings.update_settings=更新组织设置
settings.update_setting_success=组织设置已更新。 settings.update_setting_success=组织设置已更新。
settings.rename=修改组织名称
settings.rename_desc=更改组织名称同时会更改组织的 URL 地址并释放旧的名称。
settings.rename_success=组织 %[1]s 已成功重命名为 %[2]s。
settings.rename_no_change=组织名称没有变化。
settings.rename_new_org_name=新组织名称
settings.rename_failed=由于内部错误,重命名组织失败
settings.rename_notices_1=此操作 <strong>无法</strong> 被回滚。
settings.rename_notices_2=在被人使用前,旧名称将会被重定向。
settings.update_avatar_success=组织头像已经更新。 settings.update_avatar_success=组织头像已经更新。
settings.delete=删除组织 settings.delete=删除组织
settings.delete_account=删除当前组织 settings.delete_account=删除当前组织
settings.delete_prompt=删除操作会永久清除该组织的信息,并且 <strong>不可恢复</strong> settings.delete_prompt=删除操作会永久清除该组织的信息,并且 <strong>无法</strong> 恢复!
settings.name_confirm=输入组织名称以确认:
settings.delete_notices_1=此操作 <strong>无法</strong> 被回滚。
settings.delete_notices_2=此操作将永久删除 <strong>%s</strong> 的所有<strong>仓库</strong>,包括 Git 数据、 工单、评论、百科和协作者的操作权限。
settings.delete_notices_3=此操作将永久删除 <strong>%s</strong> 的所有 <strong>软件包</strong>。
settings.delete_notices_4=此操作将永久删除 <strong>%s</strong> 的所有 <strong>项目</strong>。
settings.confirm_delete_account=确认删除组织 settings.confirm_delete_account=确认删除组织
settings.delete_failed=由于内部错误,删除组织失败
settings.delete_successful=组织 <b>%s</b> 已成功删除。
settings.hooks_desc=在此处添加的 Web 钩子将会应用到该组织下的 <strong>所有仓库</strong>。 settings.hooks_desc=在此处添加的 Web 钩子将会应用到该组织下的 <strong>所有仓库</strong>。
settings.labels_desc=添加能够被该组织下的 <strong>所有仓库</strong> 的工单使用的标签。 settings.labels_desc=添加能够被该组织下的 <strong>所有仓库</strong> 的工单使用的标签。
@ -3720,8 +3755,8 @@ none=还没有密钥。
; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation ; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation
creation.description=组织描述 creation.description=组织描述
creation.name_placeholder=不区分大小写,仅限字母数字或下划线且不能以 GITEA_ 或 GITHUB_ 开头 creation.name_placeholder=不区分大小写,仅限字母数字或下划线且不能以 GITEA_ 或 GITHUB_ 开头
creation.value_placeholder=输入任何内容,开头和结尾的空白将会被忽略 creation.value_placeholder=输入任何内容,开头和结尾的空白将会被忽略
creation.description_placeholder=输入简短描述(可选) creation.description_placeholder=输入简短描述(可选)
save_success=密钥「%s」保存成功。 save_success=密钥「%s」保存成功。
save_failed=密钥保存失败。 save_failed=密钥保存失败。
@ -3806,6 +3841,7 @@ runs.no_runs=工作流尚未运行过。
runs.empty_commit_message=(空白的提交消息) runs.empty_commit_message=(空白的提交消息)
runs.expire_log_message=旧的日志已清除。 runs.expire_log_message=旧的日志已清除。
runs.delete=删除工作流运行 runs.delete=删除工作流运行
runs.cancel=取消工作流运行
runs.delete.description=您确定要永久删除此工作流运行吗?此操作无法撤消。 runs.delete.description=您确定要永久删除此工作流运行吗?此操作无法撤消。
runs.not_done=此工作流运行尚未完成。 runs.not_done=此工作流运行尚未完成。
runs.view_workflow_file=查看工作流文件 runs.view_workflow_file=查看工作流文件

View File

@ -569,7 +569,6 @@ settings.delete_notices_1=- 此操作 <strong>不可以</strong> 被回滾。
settings.delete_collaborator=移除成員 settings.delete_collaborator=移除成員
settings.teams=組織團隊 settings.teams=組織團隊
settings.add_webhook=建立 Webhook settings.add_webhook=建立 Webhook
settings.webhook.test_delivery=測試推送
settings.webhook.request=請求內容 settings.webhook.request=請求內容
settings.webhook.response=響應內容 settings.webhook.response=響應內容
settings.webhook.headers=標題 settings.webhook.headers=標題

View File

@ -2255,8 +2255,6 @@ settings.hooks_desc=當觸發某些 Gitea 事件時Webhook 會自動發出 HT
settings.webhook_deletion=移除 Webhook settings.webhook_deletion=移除 Webhook
settings.webhook_deletion_desc=移除 Webhook 將刪除它的設定及傳送記錄,是否繼續? settings.webhook_deletion_desc=移除 Webhook 將刪除它的設定及傳送記錄,是否繼續?
settings.webhook_deletion_success=Webhook 已移除。 settings.webhook_deletion_success=Webhook 已移除。
settings.webhook.test_delivery=傳送測試資料
settings.webhook.test_delivery_desc=使用假事件測試此 Webhook。
settings.webhook.test_delivery_desc_disabled=要使用假事件測試此 Webhook請啟用它。 settings.webhook.test_delivery_desc_disabled=要使用假事件測試此 Webhook請啟用它。
settings.webhook.request=請求 settings.webhook.request=請求
settings.webhook.response=回應 settings.webhook.response=回應

1592
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,12 +12,12 @@
"@github/relative-time-element": "4.4.8", "@github/relative-time-element": "4.4.8",
"@github/text-expander-element": "2.9.2", "@github/text-expander-element": "2.9.2",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
"@primer/octicons": "19.15.2", "@primer/octicons": "19.15.3",
"@silverwind/vue3-calendar-heatmap": "2.0.6", "@silverwind/vue3-calendar-heatmap": "2.0.6",
"add-asset-webpack-plugin": "3.0.0", "add-asset-webpack-plugin": "3.0.0",
"ansi_up": "6.0.6", "ansi_up": "6.0.6",
"asciinema-player": "3.10.0", "asciinema-player": "3.10.0",
"chart.js": "4.4.9", "chart.js": "4.5.0",
"chartjs-adapter-dayjs-4": "1.0.4", "chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.2.0", "chartjs-plugin-zoom": "2.2.0",
"clippie": "4.1.7", "clippie": "4.1.7",
@ -27,26 +27,25 @@
"dropzone": "6.0.0-beta.2", "dropzone": "6.0.0-beta.2",
"easymde": "2.20.0", "easymde": "2.20.0",
"esbuild-loader": "4.3.0", "esbuild-loader": "4.3.0",
"escape-goat": "4.0.0",
"fast-glob": "3.3.3", "fast-glob": "3.3.3",
"htmx.org": "2.0.6", "htmx.org": "2.0.6",
"idiomorph": "0.7.3", "idiomorph": "0.7.3",
"jquery": "3.7.1", "jquery": "3.7.1",
"katex": "0.16.22", "katex": "0.16.22",
"license-checker-webpack-plugin": "0.2.1", "license-checker-webpack-plugin": "0.2.1",
"mermaid": "11.6.0", "mermaid": "11.8.0",
"mini-css-extract-plugin": "2.9.2", "mini-css-extract-plugin": "2.9.2",
"minimatch": "10.0.2", "minimatch": "10.0.3",
"monaco-editor": "0.52.2", "monaco-editor": "0.52.2",
"monaco-editor-webpack-plugin": "7.1.0", "monaco-editor-webpack-plugin": "7.1.0",
"online-3d-viewer": "0.16.0", "online-3d-viewer": "0.16.0",
"pdfobject": "2.3.1", "pdfobject": "2.3.1",
"perfect-debounce": "1.0.0", "perfect-debounce": "1.0.0",
"postcss": "8.5.5", "postcss": "8.5.6",
"postcss-loader": "8.1.1", "postcss-loader": "8.1.1",
"postcss-nesting": "13.0.2", "postcss-nesting": "13.0.2",
"sortablejs": "1.15.6", "sortablejs": "1.15.6",
"swagger-ui-dist": "5.24.1", "swagger-ui-dist": "5.26.0",
"tailwindcss": "3.4.17", "tailwindcss": "3.4.17",
"throttle-debounce": "5.0.2", "throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
@ -56,7 +55,7 @@
"typescript": "5.8.3", "typescript": "5.8.3",
"uint8-to-base64": "0.2.1", "uint8-to-base64": "0.2.1",
"vanilla-colorful": "0.7.2", "vanilla-colorful": "0.7.2",
"vue": "3.5.16", "vue": "3.5.17",
"vue-bar-graph": "2.2.0", "vue-bar-graph": "2.2.0",
"vue-chartjs": "5.3.2", "vue-chartjs": "5.3.2",
"vue-loader": "17.4.2", "vue-loader": "17.4.2",
@ -66,55 +65,55 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0", "@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
"@playwright/test": "1.53.0", "@playwright/test": "1.53.2",
"@stoplight/spectral-cli": "6.15.0", "@stoplight/spectral-cli": "6.15.0",
"@stylistic/eslint-plugin-js": "3.1.0", "@stylistic/eslint-plugin-js": "3.1.0",
"@stylistic/stylelint-plugin": "3.1.2", "@stylistic/stylelint-plugin": "3.1.3",
"@types/dropzone": "5.7.9", "@types/dropzone": "5.7.9",
"@types/jquery": "3.5.32", "@types/jquery": "3.5.32",
"@types/katex": "0.16.7", "@types/katex": "0.16.7",
"@types/license-checker-webpack-plugin": "0.2.4", "@types/license-checker-webpack-plugin": "0.2.5",
"@types/pdfobject": "2.2.5", "@types/pdfobject": "2.2.5",
"@types/sortablejs": "1.15.8", "@types/sortablejs": "1.15.8",
"@types/swagger-ui-dist": "3.30.5", "@types/swagger-ui-dist": "3.30.6",
"@types/throttle-debounce": "5.0.2", "@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6", "@types/tinycolor2": "1.4.6",
"@types/toastify-js": "1.12.4", "@types/toastify-js": "1.12.4",
"@typescript-eslint/eslint-plugin": "8.34.0", "@typescript-eslint/eslint-plugin": "8.35.1",
"@typescript-eslint/parser": "8.34.0", "@typescript-eslint/parser": "8.35.1",
"@vitejs/plugin-vue": "5.2.4", "@vitejs/plugin-vue": "6.0.0",
"@vitest/eslint-plugin": "1.2.2", "@vitest/eslint-plugin": "1.3.4",
"eslint": "8.57.0", "eslint": "8.57.0",
"eslint-import-resolver-typescript": "4.4.3", "eslint-import-resolver-typescript": "4.4.4",
"eslint-plugin-array-func": "4.0.0", "eslint-plugin-array-func": "4.0.0",
"eslint-plugin-github": "5.0.2", "eslint-plugin-github": "5.0.2",
"eslint-plugin-import-x": "4.15.2", "eslint-plugin-import-x": "4.16.1",
"eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-jquery": "3.1.1",
"eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-playwright": "2.2.0", "eslint-plugin-playwright": "2.2.0",
"eslint-plugin-regexp": "2.9.0", "eslint-plugin-regexp": "2.9.0",
"eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-sonarjs": "3.0.4",
"eslint-plugin-unicorn": "56.0.1", "eslint-plugin-unicorn": "56.0.1",
"eslint-plugin-vue": "10.2.0", "eslint-plugin-vue": "10.3.0",
"eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-vue-scoped-css": "2.11.0",
"eslint-plugin-wc": "3.0.1", "eslint-plugin-wc": "3.0.1",
"happy-dom": "18.0.1", "happy-dom": "18.0.1",
"markdownlint-cli": "0.45.0", "markdownlint-cli": "0.45.0",
"material-icon-theme": "5.23.0", "material-icon-theme": "5.24.0",
"nolyfill": "1.0.44", "nolyfill": "1.0.44",
"postcss-html": "1.8.0", "postcss-html": "1.8.0",
"stylelint": "16.20.0", "stylelint": "16.21.1",
"stylelint-config-recommended": "16.0.0", "stylelint-config-recommended": "16.0.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.11", "stylelint-declaration-strict-value": "1.10.11",
"stylelint-define-config": "16.19.0", "stylelint-define-config": "16.21.0",
"stylelint-value-no-unknown-custom-properties": "6.0.1", "stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.3.2", "svgo": "4.0.0",
"type-fest": "4.41.0", "type-fest": "4.41.0",
"updates": "16.4.2", "updates": "16.4.2",
"vite-string-plugin": "1.4.4", "vite-string-plugin": "1.4.4",
"vitest": "3.2.3", "vitest": "3.2.4",
"vue-tsc": "2.2.10" "vue-tsc": "3.0.1"
}, },
"browserslist": [ "browserslist": [
"defaults" "defaults"

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" class="svg gitea-chef" width="16" height="16" aria-hidden="true"><g fill="none" fill-rule="evenodd"><path fill="#435363" d="M18 25.8c-4.3 0-7.7-3.6-7.7-8s3.4-7.9 7.7-7.9c3.5 0 6.4 2.4 7.3 5.7h3c-1-5-5.2-8.7-10.3-8.7-5.9 0-10.6 4.9-10.6 10.9 0 6.1 4.7 11 10.6 11 5.1 0 9.3-3.7 10.3-8.7h-3c-.9 3.3-3.8 5.7-7.3 5.7"/><path fill="#435363" d="M12.8 23.2c1.3 1.4 3.1 2.3 5.2 2.3v-3.2c-1.2 0-2.3-.5-3.1-1.3z"/><path fill="#F38B00" d="M10.6 17.8c0 1.1.3 2.2.6 3.1l2.9-1.3c-.3-.5-.4-1.1-.4-1.8 0-2.4 1.9-4.4 4.3-4.4v-3.2c-4.1 0-7.4 3.4-7.4 7.6"/><path fill="#435363" d="m20.6 10.7-1.1 3c.9.4 1.7 1.1 2.2 1.9H25c-.7-2.2-2.3-4-4.4-4.9"/><path fill="#F38B00" d="m19.5 22 1.1 2.9c2.1-.8 3.7-2.6 4.4-4.8h-3.3c-.5.8-1.3 1.5-2.2 1.9"/><path fill="#435363" d="M4.4 22.1c-.1-.2-.1-.3-.1-.5-.1-.2-.1-.3-.2-.5V21c0-.1 0-.3-.1-.4v-.5c-.1-.1-.1-.2-.1-.3-.1-.6-.1-1.3-.1-2H.9c0 .8 0 1.5.1 2.2 0 .2.1.4.1.6v.1c0 .2.1.4.1.5s0 .2.1.3v.3c.1.1.1.2.1.4 0 0 .1.1.1.2 0 .2 0 .3.1.4v.2c.2.7.5 1.3.7 2L5 23.8c-.2-.6-.4-1.1-.6-1.7"/><path fill="#F38B00" d="M18 32.6c-3.9 0-7.5-1.7-10.1-4.4l-2 2.2c3.1 3.2 7.3 5.2 12.1 5.2 8.7 0 15.8-6.8 16.9-15.5H32c-1.1 7-7 12.5-14 12.5M18 3.1c3.1 0 6.1 1.1 8.4 2.9l1.8-2.4C25.3 1.4 21.8.1 18 .1 10.7.1 4.5 4.8 2.1 11.4l2.7 1.1C6.8 7 12 3.1 18 3.1"/><path fill="#435363" d="M32 15.6h2.9c-.3-2.6-1.2-5-2.5-7.2L30 10c1 1.7 1.7 3.6 2 5.6"/><path fill="#F38B00" d="M28.7 15.6h2.9c-.8-5.1-4.1-9.3-8.6-11.1l-1.1 2.8c3.5 1.3 6 4.5 6.8 8.3"/><path fill="#435363" d="M18 6.5v-3c-5.9 0-10.9 3.8-12.9 9.1l2.7 1.1C9.4 9.5 13.3 6.5 18 6.5"/><path fill="#F38B00" d="M7 17.8H4.1c0 6.1 3.6 11.2 8.7 13.4l1.1-2.8C9.9 26.7 7 22.6 7 17.8"/><path fill="#435363" d="M18 29.2v3c6.9 0 12.6-5.3 13.6-12.1h-2.9c-1 5.2-5.4 9.1-10.7 9.1"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" class="svg gitea-chef" width="16" height="16" aria-hidden="true"><g fill="none" fill-rule="evenodd"><path fill="#435363" d="M18 25.8c-4.3 0-7.7-3.6-7.7-8s3.4-7.9 7.7-7.9c3.5 0 6.4 2.4 7.3 5.7h3c-1-5-5.2-8.7-10.3-8.7-5.9 0-10.6 4.9-10.6 10.9 0 6.1 4.7 11 10.6 11 5.1 0 9.3-3.7 10.3-8.7h-3c-.9 3.3-3.8 5.7-7.3 5.7"/><path fill="#435363" d="M12.8 23.2c1.3 1.4 3.1 2.3 5.2 2.3v-3.2c-1.2 0-2.3-.5-3.1-1.3z"/><path fill="#f38b00" d="M10.6 17.8c0 1.1.3 2.2.6 3.1l2.9-1.3c-.3-.5-.4-1.1-.4-1.8 0-2.4 1.9-4.4 4.3-4.4v-3.2c-4.1 0-7.4 3.4-7.4 7.6"/><path fill="#435363" d="m20.6 10.7-1.1 3c.9.4 1.7 1.1 2.2 1.9H25c-.7-2.2-2.3-4-4.4-4.9"/><path fill="#f38b00" d="m19.5 22 1.1 2.9c2.1-.8 3.7-2.6 4.4-4.8h-3.3c-.5.8-1.3 1.5-2.2 1.9"/><path fill="#435363" d="M4.4 22.1c-.1-.2-.1-.3-.1-.5-.1-.2-.1-.3-.2-.5V21c0-.1 0-.3-.1-.4v-.5c-.1-.1-.1-.2-.1-.3-.1-.6-.1-1.3-.1-2H.9c0 .8 0 1.5.1 2.2 0 .2.1.4.1.6v.1c0 .2.1.4.1.5s0 .2.1.3v.3c.1.1.1.2.1.4 0 0 .1.1.1.2 0 .2 0 .3.1.4v.2c.2.7.5 1.3.7 2L5 23.8c-.2-.6-.4-1.1-.6-1.7"/><path fill="#f38b00" d="M18 32.6c-3.9 0-7.5-1.7-10.1-4.4l-2 2.2c3.1 3.2 7.3 5.2 12.1 5.2 8.7 0 15.8-6.8 16.9-15.5H32c-1.1 7-7 12.5-14 12.5M18 3.1c3.1 0 6.1 1.1 8.4 2.9l1.8-2.4C25.3 1.4 21.8.1 18 .1 10.7.1 4.5 4.8 2.1 11.4l2.7 1.1C6.8 7 12 3.1 18 3.1"/><path fill="#435363" d="M32 15.6h2.9c-.3-2.6-1.2-5-2.5-7.2L30 10c1 1.7 1.7 3.6 2 5.6"/><path fill="#f38b00" d="M28.7 15.6h2.9c-.8-5.1-4.1-9.3-8.6-11.1l-1.1 2.8c3.5 1.3 6 4.5 6.8 8.3"/><path fill="#435363" d="M18 6.5v-3c-5.9 0-10.9 3.8-12.9 9.1l2.7 1.1C9.4 9.5 13.3 6.5 18 6.5"/><path fill="#f38b00" d="M7 17.8H4.1c0 6.1 3.6 11.2 8.7 13.4l1.1-2.8C9.9 26.7 7 22.6 7 17.8"/><path fill="#435363" d="M18 29.2v3c6.9 0 12.6-5.3 13.6-12.1h-2.9c-1 5.2-5.4 9.1-10.7 9.1"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 100 100" class="svg gitea-codecommit" width="16" height="16" aria-hidden="true"><g fill="none" fill-rule="evenodd"><path fill="#C925D1" d="M0 0h80v80H0z"/><path fill="#FFF" d="M26.628 28.105h-2.017v-6.982c0-.558.36-.99.926-.99l7.144-.007v1.994H27.95l4.862 4.819-1.445 1.434-4.806-4.728zm28.07 10.867 1.869.827-6.541 14.446-1.868-.827zm1.311 10.493 4.003-2.89-3.526-3.535 1.458-1.422 4.36 4.373a1.002 1.002 0 0 1-.126 1.527l-4.963 3.58zm-9.043-8.802 1.205 1.633-4.061 2.932 3.538 3.536-1.454 1.424-4.374-4.373a1 1 0 0 1 .124-1.528zM69 24.13v42.858c0 .56-.458 1.012-1.024 1.012h-31.26c-.272 0-.53-.107-.723-.297a.96.96 0 0 1-.285-.7V55.034h2.018v10.971h29.256V25.113H37.726v-1.995h30.25c.566 0 1.024.453 1.024 1.012M33.182 34.588c0-1.927 1.585-3.495 3.535-3.495s3.535 1.568 3.535 3.495-1.585 3.495-3.535 3.495-3.535-1.568-3.535-3.495M17.549 66.009c-1.95 0-3.535-1.568-3.535-3.495s1.585-3.494 3.535-3.494 3.535 1.567 3.535 3.494-1.585 3.495-3.535 3.495m-3.535-23.442c0-1.927 1.585-3.495 3.535-3.495 1.982 0 3.535 1.535 3.535 3.495 0 1.927-1.585 3.495-3.535 3.495s-3.535-1.568-3.535-3.495m.004-25.081c0-1.925 1.584-3.491 3.53-3.491 1.948 0 3.532 1.566 3.532 3.49s-1.584 3.491-3.531 3.491-3.531-1.566-3.531-3.49m23.708 29.762v-7.276c2.57-.477 4.535-2.708 4.535-5.384 0-3.022-2.487-5.482-5.544-5.482s-5.545 2.46-5.545 5.482c0 2.676 1.966 4.907 4.536 5.384v7.276c0 1.163-.786 2.218-1.98 2.686l-10.451 4.1c-1.673.657-2.903 1.948-3.434 3.496-.433-.195-.801-.336-1.285-.416v-9.146c2.623-.433 4.535-2.687 4.535-5.401 0-2.764-1.878-4.972-4.535-5.393V22.889c2.626-.431 4.54-2.688 4.54-5.403 0-3.025-2.49-5.486-5.55-5.486S12 14.46 12 17.486c0 2.64 2.022 4.85 4.54 5.369v14.347c-2.515.518-4.536 2.727-4.536 5.365s2.02 4.846 4.536 5.365v9.217c-2.515.52-4.536 2.727-4.536 5.365 0 3.022 2.488 5.482 5.545 5.482s5.544-2.46 5.544-5.482a5.43 5.43 0 0 0-1.458-3.693c.167-1.27 1.066-2.384 2.397-2.905l10.45-4.1c1.98-.777 3.244-2.57 3.244-4.568"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 100 100" class="svg gitea-codecommit" width="16" height="16" aria-hidden="true"><g fill="none" fill-rule="evenodd"><path fill="#c925d1" d="M0 0h80v80H0z"/><path fill="#fff" d="M26.628 28.105h-2.017v-6.982c0-.558.36-.99.926-.99l7.144-.007v1.994H27.95l4.862 4.819-1.445 1.434-4.806-4.728zm28.07 10.867 1.869.827-6.541 14.446-1.868-.827zm1.311 10.493 4.003-2.89-3.526-3.535 1.458-1.422 4.36 4.373a1.002 1.002 0 0 1-.126 1.527l-4.963 3.58zm-9.043-8.802 1.205 1.633-4.061 2.932 3.538 3.536-1.454 1.424-4.374-4.373a1 1 0 0 1 .124-1.528zM69 24.13v42.858c0 .56-.458 1.012-1.024 1.012h-31.26c-.272 0-.53-.107-.723-.297a.96.96 0 0 1-.285-.7V55.034h2.018v10.971h29.256V25.113H37.726v-1.995h30.25c.566 0 1.024.453 1.024 1.012M33.182 34.588c0-1.927 1.585-3.495 3.535-3.495s3.535 1.568 3.535 3.495-1.585 3.495-3.535 3.495-3.535-1.568-3.535-3.495M17.549 66.009c-1.95 0-3.535-1.568-3.535-3.495s1.585-3.494 3.535-3.494 3.535 1.567 3.535 3.494-1.585 3.495-3.535 3.495m-3.535-23.442c0-1.927 1.585-3.495 3.535-3.495 1.982 0 3.535 1.535 3.535 3.495 0 1.927-1.585 3.495-3.535 3.495s-3.535-1.568-3.535-3.495m.004-25.081c0-1.925 1.584-3.491 3.53-3.491 1.948 0 3.532 1.566 3.532 3.49s-1.584 3.491-3.531 3.491-3.531-1.566-3.531-3.49m23.708 29.762v-7.276c2.57-.477 4.535-2.708 4.535-5.384 0-3.022-2.487-5.482-5.544-5.482s-5.545 2.46-5.545 5.482c0 2.676 1.966 4.907 4.536 5.384v7.276c0 1.163-.786 2.218-1.98 2.686l-10.451 4.1c-1.673.657-2.903 1.948-3.434 3.496-.433-.195-.801-.336-1.285-.416v-9.146c2.623-.433 4.535-2.687 4.535-5.401 0-2.764-1.878-4.972-4.535-5.393V22.889c2.626-.431 4.54-2.688 4.54-5.403 0-3.025-2.49-5.486-5.55-5.486S12 14.46 12 17.486c0 2.64 2.022 4.85 4.54 5.369v14.347c-2.515.518-4.536 2.727-4.536 5.365s2.02 4.846 4.536 5.365v9.217c-2.515.52-4.536 2.727-4.536 5.365 0 3.022 2.488 5.482 5.545 5.482s5.544-2.46 5.544-5.482a5.43 5.43 0 0 0-1.458-3.693c.167-1.27 1.066-2.384 2.397-2.905l10.45-4.1c1.98-.777 3.244-2.57 3.244-4.568"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 260" class="svg gitea-debian" width="16" height="16" aria-hidden="true"><g fill="#D70751"><path d="M124.525 137.053c-4.125.058.78 2.125 6.165 2.954a55 55 0 0 0 4.04-3.479c-3.354.821-6.765.838-10.205.525m22.14-5.52c2.457-3.389 4.246-7.102 4.878-10.939-.551 2.736-2.035 5.099-3.435 7.592-7.711 4.854-.726-2.883-.004-5.824-8.29 10.436-1.138 6.257-1.439 9.171m8.174-21.265c.497-7.428-1.462-5.08-2.121-2.245.766.4 1.377 5.237 2.121 2.245M108.883 8.736c2.201.395 4.757.698 4.398 1.224 2.407-.528 2.954-1.015-4.398-1.224M113.281 9.96l-1.556.32 1.448-.127z"/><path d="M181.93 113.085c.247 6.671-1.95 9.907-3.932 15.637l-3.564 1.781c-2.919 5.666.282 3.598-1.807 8.105-4.556 4.049-13.823 12.67-16.789 13.457-2.163-.047 1.469-2.554 1.943-3.537-6.097 4.188-4.894 6.285-14.217 8.83l-.273-.607c-23.001 10.818-54.947-10.622-54.526-39.876-.246 1.857-.698 1.393-1.208 2.144-1.186-15.052 6.952-30.17 20.675-36.343 13.427-6.646 29.163-3.918 38.78 5.044-5.282-6.92-15.795-14.254-28.255-13.568-12.208.193-23.625 7.95-27.436 16.369-6.253 3.938-6.979 15.177-9.704 17.233-3.665 26.943 6.896 38.583 24.762 52.275 2.812 1.896.792 2.184 1.173 3.627-5.936-2.779-11.372-6.976-15.841-12.114 2.372 3.473 4.931 6.847 8.239 9.499-5.596-1.897-13.074-13.563-15.256-14.038 9.647 17.274 39.142 30.295 54.587 23.836-7.146.263-16.226.146-24.256-2.822-3.371-1.734-7.958-5.331-7.14-6.003 21.079 7.875 42.854 5.965 61.09-8.655 4.641-3.614 9.709-9.761 11.173-9.846-2.206 3.317.377 1.596-1.318 4.523 4.625-7.456-2.008-3.035 4.779-12.877l2.507 3.453c-.931-6.188 7.687-13.704 6.813-23.492 1.975-2.994 2.206 3.22.107 10.107 2.912-7.64.767-8.867 1.516-15.171.81 2.118 1.867 4.37 2.412 6.606-1.895-7.382 1.948-12.433 2.898-16.724-.937-.415-2.928 3.264-3.383-5.457.065-3.788 1.054-1.985 1.435-2.917-.744-.427-2.694-3.33-3.88-8.9.86-1.308 2.3 3.393 3.47 3.586-.753-4.429-2.049-7.805-2.103-11.202-3.421-7.149-1.211.953-3.985-3.069-3.641-11.357 3.021-2.637 3.47-7.796 5.52 7.995 8.667 20.387 10.11 25.519-1.103-6.258-2.883-12.32-5.058-18.185 1.677.705-2.699-12.875 2.18-3.882-5.21-19.172-22.302-37.087-38.025-45.493 1.924 1.76 4.354 3.971 3.481 4.317-7.819-4.656-6.444-5.018-7.565-6.985-6.369-2.591-6.788.208-11.007.004-12.005-6.368-14.318-5.69-25.368-9.681l.502 2.349c-7.953-2.649-9.265 1.005-17.862.009-.523-.409 2.753-1.479 5.452-1.871-7.69 1.015-7.329-1.515-14.854.279 1.855-1.301 3.815-2.162 5.793-3.269-6.271.381-14.971 3.649-12.286.677-10.235 4.569-28.403 10.976-38.597 20.535l-.321-2.142c-4.672 5.608-20.371 16.748-21.622 24.011l-1.249.291c-2.431 4.116-4.004 8.781-5.932 13.016-3.18 5.417-4.661 2.085-4.208 2.934-6.253 12.679-9.359 23.332-12.043 32.069 1.912 2.858.046 17.206.769 28.688-3.141 56.709 39.8 111.77 86.737 124.48 6.88 2.459 17.11 2.364 25.813 2.618-10.268-2.937-11.595-1.556-21.595-5.044-7.215-3.398-8.797-7.277-13.907-11.711l2.022 3.573c-10.021-3.547-5.829-4.39-13.982-6.972l2.16-2.82c-3.249-.246-8.604-5.475-10.069-8.371l-3.553.14c-4.27-5.269-6.545-9.063-6.379-12.005l-1.148 2.047c-1.301-2.235-15.709-19.759-8.234-15.679-1.389-1.271-3.235-2.067-5.237-5.703l1.522-1.739c-3.597-4.627-6.621-10.562-6.391-12.536 1.919 2.592 3.25 3.075 4.568 3.52-9.083-22.539-9.593-1.242-16.474-22.942l1.456-.116c-1.116-1.682-1.793-3.506-2.69-5.298l.633-6.313c-6.541-7.562-1.829-32.151-.887-45.637.655-5.485 5.459-11.322 9.114-20.477l-2.227-.384c4.256-7.423 24.301-29.814 33.583-28.662 4.499-5.649-.892-.02-1.772-1.443 9.878-10.223 12.984-7.222 19.65-9.061 7.19-4.268-6.17 1.664-2.761-1.628 12.427-3.174 8.808-7.216 25.021-8.828 1.71.973-3.969 1.503-5.395 2.766 10.354-5.066 32.769-3.914 47.326 2.811 16.895 7.896 35.873 31.232 36.622 53.189l.852.229c-.431 8.729 1.336 18.822-1.727 28.094l2.1-4.385"/><path d="m79.5 142.715-.578 2.893c2.71 3.683 4.861 7.673 8.323 10.552-2.49-4.863-4.341-6.872-7.745-13.445m6.409-.251c-1.435-1.587-2.284-3.497-3.235-5.4.909 3.345 2.771 6.219 4.504 9.143zm113.411-24.65-.605 1.52c-1.111 7.892-3.511 15.701-7.189 22.941a72.1 72.1 0 0 0 7.79-24.461M109.698 6.757c2.789-1.022 6.855-.56 9.814-1.233-3.855.324-7.693.517-11.484 1.005zM11.781 58.824c.642 5.951-4.477 8.26 1.134 4.337 3.007-6.773-1.175-1.87-1.134-4.337M5.188 86.362c1.292-3.967 1.526-6.349 2.02-8.645-3.571 4.566-1.643 5.539-2.02 8.645"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 260" class="svg gitea-debian" width="16" height="16" aria-hidden="true"><g fill="#d70751"><path d="M124.525 137.053c-4.125.058.78 2.125 6.165 2.954a55 55 0 0 0 4.04-3.479c-3.354.821-6.765.838-10.205.525m22.14-5.52c2.457-3.389 4.246-7.102 4.878-10.939-.551 2.736-2.035 5.099-3.435 7.592-7.711 4.854-.726-2.883-.004-5.824-8.29 10.436-1.138 6.257-1.439 9.171m8.174-21.265c.497-7.428-1.462-5.08-2.121-2.245.766.4 1.377 5.237 2.121 2.245M108.883 8.736c2.201.395 4.757.698 4.398 1.224 2.407-.528 2.954-1.015-4.398-1.224M113.281 9.96l-1.556.32 1.448-.127z"/><path d="M181.93 113.085c.247 6.671-1.95 9.907-3.932 15.637l-3.564 1.781c-2.919 5.666.282 3.598-1.807 8.105-4.556 4.049-13.823 12.67-16.789 13.457-2.163-.047 1.469-2.554 1.943-3.537-6.097 4.188-4.894 6.285-14.217 8.83l-.273-.607c-23.001 10.818-54.947-10.622-54.526-39.876-.246 1.857-.698 1.393-1.208 2.144-1.186-15.052 6.952-30.17 20.675-36.343 13.427-6.646 29.163-3.918 38.78 5.044-5.282-6.92-15.795-14.254-28.255-13.568-12.208.193-23.625 7.95-27.436 16.369-6.253 3.938-6.979 15.177-9.704 17.233-3.665 26.943 6.896 38.583 24.762 52.275 2.812 1.896.792 2.184 1.173 3.627-5.936-2.779-11.372-6.976-15.841-12.114 2.372 3.473 4.931 6.847 8.239 9.499-5.596-1.897-13.074-13.563-15.256-14.038 9.647 17.274 39.142 30.295 54.587 23.836-7.146.263-16.226.146-24.256-2.822-3.371-1.734-7.958-5.331-7.14-6.003 21.079 7.875 42.854 5.965 61.09-8.655 4.641-3.614 9.709-9.761 11.173-9.846-2.206 3.317.377 1.596-1.318 4.523 4.625-7.456-2.008-3.035 4.779-12.877l2.507 3.453c-.931-6.188 7.687-13.704 6.813-23.492 1.975-2.994 2.206 3.22.107 10.107 2.912-7.64.767-8.867 1.516-15.171.81 2.118 1.867 4.37 2.412 6.606-1.895-7.382 1.948-12.433 2.898-16.724-.937-.415-2.928 3.264-3.383-5.457.065-3.788 1.054-1.985 1.435-2.917-.744-.427-2.694-3.33-3.88-8.9.86-1.308 2.3 3.393 3.47 3.586-.753-4.429-2.049-7.805-2.103-11.202-3.421-7.149-1.211.953-3.985-3.069-3.641-11.357 3.021-2.637 3.47-7.796 5.52 7.995 8.667 20.387 10.11 25.519-1.103-6.258-2.883-12.32-5.058-18.185 1.677.705-2.699-12.875 2.18-3.882-5.21-19.172-22.302-37.087-38.025-45.493 1.924 1.76 4.354 3.971 3.481 4.317-7.819-4.656-6.444-5.018-7.565-6.985-6.369-2.591-6.788.208-11.007.004-12.005-6.368-14.318-5.69-25.368-9.681l.502 2.349c-7.953-2.649-9.265 1.005-17.862.009-.523-.409 2.753-1.479 5.452-1.871-7.69 1.015-7.329-1.515-14.854.279 1.855-1.301 3.815-2.162 5.793-3.269-6.271.381-14.971 3.649-12.286.677-10.235 4.569-28.403 10.976-38.597 20.535l-.321-2.142c-4.672 5.608-20.371 16.748-21.622 24.011l-1.249.291c-2.431 4.116-4.004 8.781-5.932 13.016-3.18 5.417-4.661 2.085-4.208 2.934-6.253 12.679-9.359 23.332-12.043 32.069 1.912 2.858.046 17.206.769 28.688-3.141 56.709 39.8 111.77 86.737 124.48 6.88 2.459 17.11 2.364 25.813 2.618-10.268-2.937-11.595-1.556-21.595-5.044-7.215-3.398-8.797-7.277-13.907-11.711l2.022 3.573c-10.021-3.547-5.829-4.39-13.982-6.972l2.16-2.82c-3.249-.246-8.604-5.475-10.069-8.371l-3.553.14c-4.27-5.269-6.545-9.063-6.379-12.005l-1.148 2.047c-1.301-2.235-15.709-19.759-8.234-15.679-1.389-1.271-3.235-2.067-5.237-5.703l1.522-1.739c-3.597-4.627-6.621-10.562-6.391-12.536 1.919 2.592 3.25 3.075 4.568 3.52-9.083-22.539-9.593-1.242-16.474-22.942l1.456-.116c-1.116-1.682-1.793-3.506-2.69-5.298l.633-6.313c-6.541-7.562-1.829-32.151-.887-45.637.655-5.485 5.459-11.322 9.114-20.477l-2.227-.384c4.256-7.423 24.301-29.814 33.583-28.662 4.499-5.649-.892-.02-1.772-1.443 9.878-10.223 12.984-7.222 19.65-9.061 7.19-4.268-6.17 1.664-2.761-1.628 12.427-3.174 8.808-7.216 25.021-8.828 1.71.973-3.969 1.503-5.395 2.766 10.354-5.066 32.769-3.914 47.326 2.811 16.895 7.896 35.873 31.232 36.622 53.189l.852.229c-.431 8.729 1.336 18.822-1.727 28.094l2.1-4.385"/><path d="m79.5 142.715-.578 2.893c2.71 3.683 4.861 7.673 8.323 10.552-2.49-4.863-4.341-6.872-7.745-13.445m6.409-.251c-1.435-1.587-2.284-3.497-3.235-5.4.909 3.345 2.771 6.219 4.504 9.143zm113.411-24.65-.605 1.52c-1.111 7.892-3.511 15.701-7.189 22.941a72.1 72.1 0 0 0 7.79-24.461M109.698 6.757c2.789-1.022 6.855-.56 9.814-1.233-3.855.324-7.693.517-11.484 1.005zM11.781 58.824c.642 5.951-4.477 8.26 1.134 4.337 3.007-6.773-1.175-1.87-1.134-4.337M5.188 86.362c1.292-3.967 1.526-6.349 2.02-8.645-3.571 4.566-1.643 5.539-2.02 8.645"/></g></svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 316 329" class="svg gitea-gitbucket" width="16" height="16" aria-hidden="true"><path d="M123 21.1c-44.8 2.8-84 12.8-97.1 24.6-5 4.5-5 7.1 0 11.6C41.7 71.5 96.6 82.9 150 83h10.6l5.4-5.6c11.8-12.1 21.3-12.4 32.6-1.2l5.2 5 13.3-1.7c33.8-4.2 61.5-12.7 71.8-22 5.3-4.8 5.3-7.2 0-12-10.1-9.1-39.1-18.1-70.4-21.9-28.3-3.4-65.6-4.4-95.5-2.5M23.2 80.6c.4 1.6 7 42.9 14.8 91.9 7.9 49 14.7 89.5 15.2 90.2 1.7 2.1 25.8 11.4 41.6 15.9 13 3.7 35.1 8.4 40 8.4.6 0 1.2-.6 1.2-1.3 0-.6-17.4-18.5-38.6-39.7C57.9 206.6 55 203.2 55 196s3-10.7 38.3-45.9c30.1-30 34.8-34.3 36.6-33.5 1.1.5 8.7 7.4 17 15.2l15.1 14.4v5.9c0 7.3 2.4 12.4 7.7 16.7l3.8 3v61.8l-3.8 3.4c-10.2 8.9-10.2 22.9-.1 30.7 3.1 2.3 4.9 2.8 10.8 3.1 8.2.4 11.5-1.1 16.2-7.3 2.2-3 2.9-5.1 3.2-10 .4-6.5-.2-8.3-5.3-15.4l-2.5-3.4v-26.6c0-26.7.3-31.1 2.3-31.1.5 0 5.4 4.4 10.9 9.7 9.6 9.5 9.9 10 10.8 15.7 1.7 10.3 8.9 16.6 19 16.6 7.6 0 13.5-3.9 17.4-11.7 3.2-6.4 1.6-14.3-4.3-20.6-4.1-4.4-7.3-5.7-14.9-5.7h-6.8l-12.7-12.1c-10.7-10.1-12.7-12.6-13.2-15.7-1.2-7.2-1.6-8.2-4.7-11.7-3.9-4.5-7.7-6.5-12.2-6.5-1.9 0-4.5-.4-5.8-.9s-9.9-8.2-19.3-17l-17-16-7.1-.1c-10.6 0-36-2.7-52.4-5.5-22.8-4-38.5-8.6-57.9-17.2-1.1-.5-1.3 0-.9 2.3M278.5 83.6c-8.6 3.6-28 8.8-42.5 11.4-6.9 1.2-12.9 2.6-13.5 3.1-.6.6 9.3 11.2 27.5 29.4 15.6 15.6 28.5 28.3 28.7 28.1s1.9-15.8 3.8-34.7 3.7-35.6 4-37.2c.6-3.4-.2-3.4-8-.1M255.2 259.3c-7.8 7.8-14.2 14.6-14.2 15s.7.7 1.6.7c2.2 0 23-8.9 24.2-10.3.9-1.1 3.5-18.7 2.9-19.3-.2-.2-6.7 6.1-14.5 13.9M56 283.5c0 3.4 4 9.5 8.4 12.9 6.1 4.6 19.7 10.4 31.7 13.5 16.9 4.3 32.1 6.2 53.4 6.8l19 .5-7-7.1c-6.8-6.9-7.1-7.1-12-7.1-18.9 0-55.1-7.9-80.6-17.6C62.5 283 57 281 56.6 281c-.3 0-.6 1.1-.6 2.5M262 283.4c-5.3 2.8-25 9.7-36 12.6l-11.4 2.9-7.8 7.8c-4.2 4.2-7.6 7.9-7.4 8.1.9.8 24.4-4.1 33.4-6.9 16.4-5.3 26.7-11.4 30.8-18.5 2.4-4 3.1-7.4 1.7-7.4-.5.1-1.9.7-3.3 1.4"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 316 329" class="svg gitea-gitbucket" width="16" height="16" aria-hidden="true"><path d="M123 21.1c-44.8 2.8-84 12.8-97.1 24.6-5 4.5-5 7.1 0 11.6C41.7 71.5 96.6 82.9 150 83h10.6l5.4-5.6c11.8-12.1 21.3-12.4 32.6-1.2l5.2 5 13.3-1.7c33.8-4.2 61.5-12.7 71.8-22 5.3-4.8 5.3-7.2 0-12-10.1-9.1-39.1-18.1-70.4-21.9-28.3-3.4-65.6-4.4-95.5-2.5M23.2 80.6c.4 1.6 7 42.9 14.8 91.9 7.9 49 14.7 89.5 15.2 90.2 1.7 2.1 25.8 11.4 41.6 15.9 13 3.7 35.1 8.4 40 8.4.6 0 1.2-.6 1.2-1.3 0-.6-17.4-18.5-38.6-39.7C57.9 206.6 55 203.2 55 196s3-10.7 38.3-45.9c30.1-30 34.8-34.3 36.6-33.5 1.1.5 8.7 7.4 17 15.2l15.1 14.4v5.9c0 7.3 2.4 12.4 7.7 16.7l3.8 3v61.8l-3.8 3.4c-10.2 8.9-10.2 22.9-.1 30.7 3.1 2.3 4.9 2.8 10.8 3.1 8.2.4 11.5-1.1 16.2-7.3 2.2-3 2.9-5.1 3.2-10 .4-6.5-.2-8.3-5.3-15.4l-2.5-3.4v-26.6c0-26.7.3-31.1 2.3-31.1.5 0 5.4 4.4 10.9 9.7 9.6 9.5 9.9 10 10.8 15.7 1.7 10.3 8.9 16.6 19 16.6 7.6 0 13.5-3.9 17.4-11.7 3.2-6.4 1.6-14.3-4.3-20.6-4.1-4.4-7.3-5.7-14.9-5.7h-6.8l-12.7-12.1c-10.7-10.1-12.7-12.6-13.2-15.7-1.2-7.2-1.6-8.2-4.7-11.7-3.9-4.5-7.7-6.5-12.2-6.5-1.9 0-4.5-.4-5.8-.9s-9.9-8.2-19.3-17l-17-16-7.1-.1c-10.6 0-36-2.7-52.4-5.5-22.8-4-38.5-8.6-57.9-17.2-1.1-.5-1.3 0-.9 2.3M278.5 83.6c-8.6 3.6-28 8.8-42.5 11.4-6.9 1.2-12.9 2.6-13.5 3.1-.6.6 9.3 11.2 27.5 29.4 15.6 15.6 28.5 28.3 28.7 28.1s1.9-15.8 3.8-34.7 3.7-35.6 4-37.2c.6-3.4-.2-3.4-8-.1M255.2 259.3c-7.8 7.8-14.2 14.6-14.2 15s.7.7 1.6.7c2.2 0 23-8.9 24.2-10.3.9-1.1 3.5-18.7 2.9-19.3-.2-.2-6.7 6.1-14.5 13.9M56 283.5c0 3.4 4 9.5 8.4 12.9 6.1 4.6 19.7 10.4 31.7 13.5 16.9 4.3 32.1 6.2 53.4 6.8l19 .5-7-7.1c-6.8-6.9-7.1-7.1-12-7.1-18.9 0-55.1-7.9-80.6-17.6C62.5 283 57 281 56.6 281c-.3 0-.6 1.1-.6 2.5M262 283.4c-5.3 2.8-25 9.7-36 12.6l-11.4 2.9-7.8 7.8c-4.2 4.2-7.6 7.9-7.4 8.1.9.8 24.4-4.1 33.4-6.9 16.4-5.3 26.7-11.4 30.8-18.5 2.4-4 3.1-7.4 1.7-7.4-.5.1-1.9.7-3.3 1.4"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="svg gitea-gitlab" width="16" height="16" aria-hidden="true"><path fill="#E24329" d="m31.462 12.779-.045-.115-4.35-11.35a1.14 1.14 0 0 0-.447-.541 1.16 1.16 0 0 0-1.343.071c-.187.15-.322.356-.386.587l-2.94 9.001h-11.9l-2.941-9a1.14 1.14 0 0 0-1.045-.84 1.15 1.15 0 0 0-1.13.72L.579 12.68l-.045.113a8.09 8.09 0 0 0 2.68 9.34l.016.012.038.03 6.635 4.967 3.28 2.484 1.994 1.51a1.35 1.35 0 0 0 1.627 0l1.994-1.51 3.282-2.484 6.673-4.997.018-.013a8.09 8.09 0 0 0 2.69-9.352Z"/><path fill="#FC6D26" d="m31.462 12.779-.045-.115a14.75 14.75 0 0 0-5.856 2.634l-9.553 7.24L22.1 27.14l6.673-4.997.019-.013a8.09 8.09 0 0 0 2.67-9.352Z"/><path fill="#FCA326" d="m9.908 27.14 3.275 2.485 1.994 1.51a1.35 1.35 0 0 0 1.627 0l1.994-1.51 3.282-2.484s-2.835-2.14-6.092-4.603z"/><path fill="#FC6D26" d="M6.435 15.305A14.7 14.7 0 0 0 .58 12.672l-.045.113a8.09 8.09 0 0 0 2.68 9.347l.016.012.038.03 6.635 4.967 6.105-4.603-9.573-7.233Z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="svg gitea-gitlab" width="16" height="16" aria-hidden="true"><path fill="#e24329" d="m31.462 12.779-.045-.115-4.35-11.35a1.14 1.14 0 0 0-.447-.541 1.16 1.16 0 0 0-1.343.071c-.187.15-.322.356-.386.587l-2.94 9.001h-11.9l-2.941-9a1.14 1.14 0 0 0-1.045-.84 1.15 1.15 0 0 0-1.13.72L.579 12.68l-.045.113a8.09 8.09 0 0 0 2.68 9.34l.016.012.038.03 6.635 4.967 3.28 2.484 1.994 1.51a1.35 1.35 0 0 0 1.627 0l1.994-1.51 3.282-2.484 6.673-4.997.018-.013a8.09 8.09 0 0 0 2.69-9.352Z"/><path fill="#fc6d26" d="m31.462 12.779-.045-.115a14.75 14.75 0 0 0-5.856 2.634l-9.553 7.24L22.1 27.14l6.673-4.997.019-.013a8.09 8.09 0 0 0 2.67-9.352Z"/><path fill="#fca326" d="m9.908 27.14 3.275 2.485 1.994 1.51a1.35 1.35 0 0 0 1.627 0l1.994-1.51 3.282-2.484s-2.835-2.14-6.092-4.603z"/><path fill="#fc6d26" d="M6.435 15.305A14.7 14.7 0 0 0 .58 12.672l-.045.113a8.09 8.09 0 0 0 2.68 9.347l.016.012.038.03 6.635 4.967 6.105-4.603-9.573-7.233Z"/></svg>

Before

Width:  |  Height:  |  Size: 988 B

After

Width:  |  Height:  |  Size: 988 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="gitea-google__svg gitea-google__gitea-google svg gitea-google" viewBox="0 0 24 24" width="16" height="16"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53"/><path fill="none" d="M1 1h22v22H1z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="gitea-google__svg gitea-google__gitea-google svg gitea-google" viewBox="0 0 24 24" width="16" height="16"><path fill="#4285f4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09"/><path fill="#34a853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23"/><path fill="#fbbc05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22z"/><path fill="#ea4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53"/><path fill="none" d="M1 1h22v22H1z"/></svg>

Before

Width:  |  Height:  |  Size: 821 B

After

Width:  |  Height:  |  Size: 821 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48" class="svg gitea-microsoftonline" width="16" height="16" aria-hidden="true"><path fill="url(#gitea-microsoftonline__a)" d="m20.084 3.026-.224.136a8 8 0 0 0-1.009.722l.648-.456H25L26 11l-5 5-5 3.475v4.008a8 8 0 0 0 3.857 6.844l5.264 3.186L14 40h-2.145l-3.998-2.42A8 8 0 0 1 4 30.737V17.26a8 8 0 0 1 3.86-6.846l12-7.258q.111-.068.224-.131Z"/><path fill="url(#gitea-microsoftonline__b)" d="m20.084 3.026-.224.136a8 8 0 0 0-1.009.722l.648-.456H25L26 11l-5 5-5 3.475v4.008a8 8 0 0 0 3.857 6.844l5.264 3.186L14 40h-2.145l-3.998-2.42A8 8 0 0 1 4 30.737V17.26a8 8 0 0 1 3.86-6.846l12-7.258q.111-.068.224-.131Z"/><path fill="url(#gitea-microsoftonline__c)" d="M32 19v4.48a8 8 0 0 1-3.857 6.844l-12 7.264a8 8 0 0 1-8.008.16l11.722 7.096a8 8 0 0 0 8.286 0l12-7.264A8 8 0 0 0 44 30.736V27.5L43 26z"/><path fill="url(#gitea-microsoftonline__d)" d="M32 19v4.48a8 8 0 0 1-3.857 6.844l-12 7.264a8 8 0 0 1-8.008.16l11.722 7.096a8 8 0 0 0 8.286 0l12-7.264A8 8 0 0 0 44 30.736V27.5L43 26z"/><path fill="url(#gitea-microsoftonline__e)" d="m40.14 10.415-12-7.258a8 8 0 0 0-8.042-.139l-.238.144A8 8 0 0 0 16 10.008v9.483l3.86-2.334a8 8 0 0 1 8.28 0l12 7.258A8 8 0 0 1 43.997 31q.004-.132.004-.263V17.26a8 8 0 0 0-3.86-6.845Z"/><path fill="url(#gitea-microsoftonline__f)" d="m40.14 10.415-12-7.258a8 8 0 0 0-8.042-.139l-.238.144A8 8 0 0 0 16 10.008v9.483l3.86-2.334a8 8 0 0 1 8.28 0l12 7.258A8 8 0 0 1 43.997 31q.004-.132.004-.263V17.26a8 8 0 0 0-3.86-6.845Z"/><path fill="url(#gitea-microsoftonline__g)" d="M4.004 30.998"/><path fill="url(#gitea-microsoftonline__h)" d="M4.004 30.998"/><defs><radialGradient id="gitea-microsoftonline__a" cx="0" cy="0" r="1" gradientTransform="rotate(110.528 5.021 11.358)scale(33.3657 58.1966)" gradientUnits="userSpaceOnUse"><stop offset=".064" stop-color="#AE7FE2"/><stop offset="1" stop-color="#0078D4"/></radialGradient><radialGradient id="gitea-microsoftonline__c" cx="0" cy="0" r="1" gradientTransform="matrix(30.7198 -4.51832 2.98465 20.29248 10.43 36.351)" gradientUnits="userSpaceOnUse"><stop offset=".134" stop-color="#D59DFF"/><stop offset="1" stop-color="#5E438F"/></radialGradient><radialGradient id="gitea-microsoftonline__e" cx="0" cy="0" r="1" gradientTransform="matrix(-24.1583 -6.12555 10.3118 -40.66824 41.055 26.504)" gradientUnits="userSpaceOnUse"><stop offset=".058" stop-color="#50E6FF"/><stop offset="1" stop-color="#436DCD"/></radialGradient><radialGradient id="gitea-microsoftonline__g" cx="0" cy="0" r="1" gradientTransform="matrix(-24.1583 -6.12555 10.3118 -40.66824 41.055 26.504)" gradientUnits="userSpaceOnUse"><stop offset=".058" stop-color="#50E6FF"/><stop offset="1" stop-color="#436DCD"/></radialGradient><linearGradient id="gitea-microsoftonline__b" x1="17.512" x2="12.751" y1="37.868" y2="29.635" gradientUnits="userSpaceOnUse"><stop stop-color="#114A8B"/><stop offset="1" stop-color="#0078D4" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__d" x1="40.357" x2="35.255" y1="25.377" y2="32.692" gradientUnits="userSpaceOnUse"><stop stop-color="#493474"/><stop offset="1" stop-color="#8C66BA" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__f" x1="16.976" x2="24.487" y1="3.057" y2="3.057" gradientUnits="userSpaceOnUse"><stop stop-color="#2D3F80"/><stop offset="1" stop-color="#436DCD" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__h" x1="16.976" x2="24.487" y1="3.057" y2="3.057" gradientUnits="userSpaceOnUse"><stop stop-color="#2D3F80"/><stop offset="1" stop-color="#436DCD" stop-opacity="0"/></linearGradient></defs></svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48" class="svg gitea-microsoftonline" width="16" height="16" aria-hidden="true"><path fill="url(#gitea-microsoftonline__a)" d="m20.084 3.026-.224.136a8 8 0 0 0-1.009.722l.648-.456H25L26 11l-5 5-5 3.475v4.008a8 8 0 0 0 3.857 6.844l5.264 3.186L14 40h-2.145l-3.998-2.42A8 8 0 0 1 4 30.737V17.26a8 8 0 0 1 3.86-6.846l12-7.258q.111-.068.224-.131Z"/><path fill="url(#gitea-microsoftonline__b)" d="m20.084 3.026-.224.136a8 8 0 0 0-1.009.722l.648-.456H25L26 11l-5 5-5 3.475v4.008a8 8 0 0 0 3.857 6.844l5.264 3.186L14 40h-2.145l-3.998-2.42A8 8 0 0 1 4 30.737V17.26a8 8 0 0 1 3.86-6.846l12-7.258q.111-.068.224-.131Z"/><path fill="url(#gitea-microsoftonline__c)" d="M32 19v4.48a8 8 0 0 1-3.857 6.844l-12 7.264a8 8 0 0 1-8.008.16l11.722 7.096a8 8 0 0 0 8.286 0l12-7.264A8 8 0 0 0 44 30.736V27.5L43 26z"/><path fill="url(#gitea-microsoftonline__d)" d="M32 19v4.48a8 8 0 0 1-3.857 6.844l-12 7.264a8 8 0 0 1-8.008.16l11.722 7.096a8 8 0 0 0 8.286 0l12-7.264A8 8 0 0 0 44 30.736V27.5L43 26z"/><path fill="url(#gitea-microsoftonline__e)" d="m40.14 10.415-12-7.258a8 8 0 0 0-8.042-.139l-.238.144A8 8 0 0 0 16 10.008v9.483l3.86-2.334a8 8 0 0 1 8.28 0l12 7.258A8 8 0 0 1 43.997 31q.004-.132.004-.263V17.26a8 8 0 0 0-3.86-6.845Z"/><path fill="url(#gitea-microsoftonline__f)" d="m40.14 10.415-12-7.258a8 8 0 0 0-8.042-.139l-.238.144A8 8 0 0 0 16 10.008v9.483l3.86-2.334a8 8 0 0 1 8.28 0l12 7.258A8 8 0 0 1 43.997 31q.004-.132.004-.263V17.26a8 8 0 0 0-3.86-6.845Z"/><path fill="url(#gitea-microsoftonline__g)" d="M4.004 30.998"/><path fill="url(#gitea-microsoftonline__h)" d="M4.004 30.998"/><defs><radialGradient id="gitea-microsoftonline__a" cx="0" cy="0" r="1" gradientTransform="rotate(110.528 5.021 11.358)scale(33.3657 58.1966)" gradientUnits="userSpaceOnUse"><stop offset=".064" stop-color="#ae7fe2"/><stop offset="1" stop-color="#0078d4"/></radialGradient><radialGradient id="gitea-microsoftonline__c" cx="0" cy="0" r="1" gradientTransform="rotate(-8.367 253.693 -53.118)scale(31.0503 20.5108)" gradientUnits="userSpaceOnUse"><stop offset=".134" stop-color="#d59dff"/><stop offset="1" stop-color="#5e438f"/></radialGradient><radialGradient id="gitea-microsoftonline__e" cx="0" cy="0" r="1" gradientTransform="rotate(194.228 22.182 10.69)scale(24.9228 41.9552)" gradientUnits="userSpaceOnUse"><stop offset=".058" stop-color="#50e6ff"/><stop offset="1" stop-color="#436dcd"/></radialGradient><radialGradient id="gitea-microsoftonline__g" cx="0" cy="0" r="1" gradientTransform="rotate(194.228 22.182 10.69)scale(24.9228 41.9552)" gradientUnits="userSpaceOnUse"><stop offset=".058" stop-color="#50e6ff"/><stop offset="1" stop-color="#436dcd"/></radialGradient><linearGradient id="gitea-microsoftonline__b" x1="17.512" x2="12.751" y1="37.868" y2="29.635" gradientUnits="userSpaceOnUse"><stop stop-color="#114a8b"/><stop offset="1" stop-color="#0078d4" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__d" x1="40.357" x2="35.255" y1="25.377" y2="32.692" gradientUnits="userSpaceOnUse"><stop stop-color="#493474"/><stop offset="1" stop-color="#8c66ba" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__f" x1="16.976" x2="24.487" y1="3.057" y2="3.057" gradientUnits="userSpaceOnUse"><stop stop-color="#2d3f80"/><stop offset="1" stop-color="#436dcd" stop-opacity="0"/></linearGradient><linearGradient id="gitea-microsoftonline__h" x1="16.976" x2="24.487" y1="3.057" y2="3.057" gradientUnits="userSpaceOnUse"><stop stop-color="#2d3f80"/><stop offset="1" stop-color="#436dcd" stop-opacity="0"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 7" class="svg gitea-npm" width="16" height="16" aria-hidden="true"><path fill="#CB3837" d="M0 0h18v6H9v1H5V6H0zm1 5h2V2h1v3h1V1H1zm5-4v5h2V5h2V1zm2 1h1v2H8zm3-1v4h2V2h1v3h1V2h1v3h1V1z"/><path fill="#fff" d="M1 5h2V2h1v3h1V1H1zM6 1v5h2V5h2V1zm3 3H8V2h1zM11 1v4h2V2h1v3h1V2h1v3h1V1z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 7" class="svg gitea-npm" width="16" height="16" aria-hidden="true"><path fill="#cb3837" d="M0 0h18v6H9v1H5V6H0zm1 5h2V2h1v3h1V1H1zm5-4v5h2V5h2V1zm2 1h1v2H8zm3-1v4h2V2h1v3h1V2h1v3h1V1z"/><path fill="#fff" d="M1 5h2V2h1v3h1V1H1zM6 1v5h2V5h2V1zm3 3H8V2h1zM11 1v4h2V2h1v3h1V2h1v3h1V1z"/></svg>

Before

Width:  |  Height:  |  Size: 345 B

After

Width:  |  Height:  |  Size: 345 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 700 700" class="svg gitea-onedev" width="16" height="16" aria-hidden="true"><path d="M315.5 99.6c-29.5 4-55.8 12-81.2 24.8L223 130l-5.2-4c-14.9-11.3-37.6-14.9-55.8-9-19.1 6.3-35.1 22.2-41.1 41-2.7 8.3-3.6 22.9-1.9 31.2 1.5 8 5 16.5 9.1 22.5 3.1 4.7 3.1 4.8 1.4 7.8C106 260 95.1 294.4 92 337.7c-1.1 15.7-.1 40.2 2.1 53l1.1 6.5-4.9 4.4c-2.8 2.3-7.5 7.6-10.6 11.6-19.4 25.5-24.7 57.9-14.4 88.3 9.2 26.9 31.2 48.8 58.4 58.1 20.6 6.9 40.6 7 61.1.1l6.7-2.2 10.5 7.1c45.6 31 92 45.5 146 45.5 33 0 61.6-5.2 91-16.4 67.6-25.8 122.9-81.1 148.4-148.4l2.7-7.2 7.7-3.8c9.1-4.5 21.1-15.7 25.9-24.3 21.1-37.5-1-84.3-43.2-91.7-19.9-3.5-39.3 2.7-53.9 17.2-7.1 7.1-11.7 14.5-15.3 24.7-3.4 9.4-3.8 25.8-.9 35.3 2.8 9.5 8.5 19.3 15.3 26.4 7.2 7.6 7.2 6 0 20.5-8.9 18.1-20.3 34.1-35.2 49.5-34.6 35.7-78.2 56.3-128.3 60.3-42.8 3.4-89.3-8.9-125-33-1.1-.8-1-1.7.8-5.2 12.1-23.6 13.5-53.7 3.9-78-8.7-21.8-27.5-41.6-48.6-51.2-9-4.1-22.7-7.4-34-8.3l-9.1-.7-.8-9.6c-3.5-46.9 13.5-99.8 45.5-141.7 6.5-8.6 24.3-26.7 33.6-34.2 43.8-35.6 101.3-52.8 158.1-47.2 39.9 3.9 79 19.1 110.6 43 16.9 12.8 37.5 34.9 48.6 52l4.3 6.7-3.3 5.2c-2.9 4.7-3.3 6.3-3.6 13.4-.3 7.3-.1 8.6 2.5 13.6 3.2 6.1 10.2 12 16.3 13.9 22.8 6.8 43-16.9 32.6-38.2-3.1-6.4-9.3-12.2-14.7-13.8-2.5-.8-4.1-2.1-5.2-4.3-.9-1.7-3.2-5.8-5.1-9.2l-3.5-6 3.6-5c17.7-24.4 15.8-57.5-4.4-79.4-8-8.6-15.5-13.6-25.9-17.2-19.8-6.8-38.9-4.2-56.5 7.8l-7.8 5.3-15.3-7.4c-27.9-13.4-55-21.3-84-24.4-13.3-1.5-48.1-1.2-60.3.5"/><path d="M271.8 271.1c-13.9 2.1-30.5 17.3-40.5 37.4-18.3 36.4-13.4 81.5 9.8 91.5 15.2 6.5 34.5-2.7 48.6-23.2 5.5-8 9.7-15.7 9-16.5-.3-.2-2 .3-3.8 1.2-2.4 1.3-5.1 1.6-10.5 1.3-6.1-.3-7.9-.8-11.6-3.4-8.9-6.2-12.4-19.1-7.9-29 2.4-5.2 9-10.8 14.7-12.4 9.1-2.6 20 1.4 25.2 9.2l2.7 4.2.3-12.4c.4-18.9-3.4-31.6-12.4-40.5-6.3-6.3-14.2-8.8-23.6-7.4M420.5 271c-11.6 1.9-20.2 11.3-24.9 27-2.1 6.9-3.1 20-2.2 27.4l.8 5.7 2.1-3.2c10.2-15 31.6-14 39.9 2 6 11.5 1.5 25.1-10.4 31.2-5 2.5-15 2.6-20 .1l-3.6-1.9 1.4 3.3c6.1 14.5 20 30.1 32.3 36.1 5.7 2.8 14.4 4 20.4 2.9 5.2-1 12.1-6.1 16.1-11.9 18.1-26.4 8.1-79-20-105.8-10.8-10.2-21.6-14.6-31.9-12.9M322.5 431.9c-16.1 1.6-23.5 6.1-23.5 14.3 0 11.4 13 21.1 34 25.4 10.2 2 31.2 1.5 40.5-1 13.5-3.7 23.8-10.3 27.6-17.7 4.9-9.7-.2-17.1-13.8-20-6.1-1.2-54.2-2-64.8-1"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 700" class="svg gitea-onedev" width="16" height="16" aria-hidden="true"><path d="M315.5 99.6c-29.5 4-55.8 12-81.2 24.8L223 130l-5.2-4c-14.9-11.3-37.6-14.9-55.8-9-19.1 6.3-35.1 22.2-41.1 41-2.7 8.3-3.6 22.9-1.9 31.2 1.5 8 5 16.5 9.1 22.5 3.1 4.7 3.1 4.8 1.4 7.8C106 260 95.1 294.4 92 337.7c-1.1 15.7-.1 40.2 2.1 53l1.1 6.5-4.9 4.4c-2.8 2.3-7.5 7.6-10.6 11.6-19.4 25.5-24.7 57.9-14.4 88.3 9.2 26.9 31.2 48.8 58.4 58.1 20.6 6.9 40.6 7 61.1.1l6.7-2.2 10.5 7.1c45.6 31 92 45.5 146 45.5 33 0 61.6-5.2 91-16.4 67.6-25.8 122.9-81.1 148.4-148.4l2.7-7.2 7.7-3.8c9.1-4.5 21.1-15.7 25.9-24.3 21.1-37.5-1-84.3-43.2-91.7-19.9-3.5-39.3 2.7-53.9 17.2-7.1 7.1-11.7 14.5-15.3 24.7-3.4 9.4-3.8 25.8-.9 35.3 2.8 9.5 8.5 19.3 15.3 26.4 7.2 7.6 7.2 6 0 20.5-8.9 18.1-20.3 34.1-35.2 49.5-34.6 35.7-78.2 56.3-128.3 60.3-42.8 3.4-89.3-8.9-125-33-1.1-.8-1-1.7.8-5.2 12.1-23.6 13.5-53.7 3.9-78-8.7-21.8-27.5-41.6-48.6-51.2-9-4.1-22.7-7.4-34-8.3l-9.1-.7-.8-9.6c-3.5-46.9 13.5-99.8 45.5-141.7 6.5-8.6 24.3-26.7 33.6-34.2 43.8-35.6 101.3-52.8 158.1-47.2 39.9 3.9 79 19.1 110.6 43 16.9 12.8 37.5 34.9 48.6 52l4.3 6.7-3.3 5.2c-2.9 4.7-3.3 6.3-3.6 13.4-.3 7.3-.1 8.6 2.5 13.6 3.2 6.1 10.2 12 16.3 13.9 22.8 6.8 43-16.9 32.6-38.2-3.1-6.4-9.3-12.2-14.7-13.8-2.5-.8-4.1-2.1-5.2-4.3-.9-1.7-3.2-5.8-5.1-9.2l-3.5-6 3.6-5c17.7-24.4 15.8-57.5-4.4-79.4-8-8.6-15.5-13.6-25.9-17.2-19.8-6.8-38.9-4.2-56.5 7.8l-7.8 5.3-15.3-7.4c-27.9-13.4-55-21.3-84-24.4-13.3-1.5-48.1-1.2-60.3.5"/><path d="M271.8 271.1c-13.9 2.1-30.5 17.3-40.5 37.4-18.3 36.4-13.4 81.5 9.8 91.5 15.2 6.5 34.5-2.7 48.6-23.2 5.5-8 9.7-15.7 9-16.5-.3-.2-2 .3-3.8 1.2-2.4 1.3-5.1 1.6-10.5 1.3-6.1-.3-7.9-.8-11.6-3.4-8.9-6.2-12.4-19.1-7.9-29 2.4-5.2 9-10.8 14.7-12.4 9.1-2.6 20 1.4 25.2 9.2l2.7 4.2.3-12.4c.4-18.9-3.4-31.6-12.4-40.5-6.3-6.3-14.2-8.8-23.6-7.4M420.5 271c-11.6 1.9-20.2 11.3-24.9 27-2.1 6.9-3.1 20-2.2 27.4l.8 5.7 2.1-3.2c10.2-15 31.6-14 39.9 2 6 11.5 1.5 25.1-10.4 31.2-5 2.5-15 2.6-20 .1l-3.6-1.9 1.4 3.3c6.1 14.5 20 30.1 32.3 36.1 5.7 2.8 14.4 4 20.4 2.9 5.2-1 12.1-6.1 16.1-11.9 18.1-26.4 8.1-79-20-105.8-10.8-10.2-21.6-14.6-31.9-12.9M322.5 431.9c-16.1 1.6-23.5 6.1-23.5 14.3 0 11.4 13 21.1 34 25.4 10.2 2 31.2 1.5 40.5-1 13.5-3.7 23.8-10.3 27.6-17.7 4.9-9.7-.2-17.1-13.8-20-6.1-1.2-54.2-2-64.8-1"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 2400 2400" class="svg gitea-openid" width="16" height="16" aria-hidden="true"><path fill="#ff7c00" d="m1270 218.3-173.1 84.3-.7 981.8c-.3 540 .2 981.4 1.1 981l174.5-81.8 172.3-80.8v-984.4c0-541.7-.2-984.7-.4-984.4z"/><path fill="#aaa" d="M981.9 785.5c-425.3 63.2-766.5 264.1-889 523a491.5 491.5 0 0 0-43.6 146c-4.2 29.2-4.7 95-1.2 124 19 152.6 115.2 299.9 273.2 418.8 147.7 111 350.5 196.5 568.6 239.7 59 11.6 179 29 200.5 29 2.3 0 3-23.2 3-109.1v-109.2l-5.1-1-37.9-6a1182 1182 0 0 1-305.4-90.6c-122.2-55.7-225.1-137.7-284.6-226.4-107.5-160.5-81.3-344.3 70-491.3 57-55.5 115.4-95.2 199.5-136.1a1112.6 1112.6 0 0 1 269.4-89.2l29.7-6c3.7-1.2 4-8.6 4-111.5V779.5l-6.3.2a823 823 0 0 0-44.8 5.8m525 104c0 103 .2 110.4 4.1 111.6l29.5 6a1221.6 1221.6 0 0 1 207.7 61.3A1088 1088 0 0 1 1862 1123c4.6 3.7 1.4 5.8-88 56-51.1 28.5-93 52.7-93 53.4 0 1.9 671.6 146.8 673.2 145.2 1.2-1.2-45.5-496-47-497.6-.2-.2-38.5 21-85 47.2l-89.6 50.2c-4.2 2-8.8.2-27.9-10.7-130.8-75-289.6-132.2-460.8-166.1a1871 1871 0 0 0-132.9-21.1c-4 0-4.2 6.7-4.2 110z"/><path fill="#cbaa7c" d="M1094.5 2156.9c0 60.6.3 85.5.5 55 .5-30.2.5-79.9 0-110.3-.2-30.2-.5-5.3-.5 55.3"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2400 2400" class="svg gitea-openid" width="16" height="16" aria-hidden="true"><path fill="#ff7c00" d="m1270 218.3-173.1 84.3-.7 981.8c-.3 540 .2 981.4 1.1 981l174.5-81.8 172.3-80.8v-984.4c0-541.7-.2-984.7-.4-984.4z"/><path fill="#aaa" d="M981.9 785.5c-425.3 63.2-766.5 264.1-889 523a491.5 491.5 0 0 0-43.6 146c-4.2 29.2-4.7 95-1.2 124 19 152.6 115.2 299.9 273.2 418.8 147.7 111 350.5 196.5 568.6 239.7 59 11.6 179 29 200.5 29 2.3 0 3-23.2 3-109.1v-109.2l-5.1-1-37.9-6a1182 1182 0 0 1-305.4-90.6c-122.2-55.7-225.1-137.7-284.6-226.4-107.5-160.5-81.3-344.3 70-491.3 57-55.5 115.4-95.2 199.5-136.1a1112.6 1112.6 0 0 1 269.4-89.2l29.7-6c3.7-1.2 4-8.6 4-111.5V779.5l-6.3.2a823 823 0 0 0-44.8 5.8m525 104c0 103 .2 110.4 4.1 111.6l29.5 6a1221.6 1221.6 0 0 1 207.7 61.3A1088 1088 0 0 1 1862 1123c4.6 3.7 1.4 5.8-88 56-51.1 28.5-93 52.7-93 53.4 0 1.9 671.6 146.8 673.2 145.2 1.2-1.2-45.5-496-47-497.6-.2-.2-38.5 21-85 47.2l-89.6 50.2c-4.2 2-8.8.2-27.9-10.7-130.8-75-289.6-132.2-460.8-166.1a1871 1871 0 0 0-132.9-21.1c-4 0-4.2 6.7-4.2 110z"/><path fill="#cbaa7c" d="M1094.5 2156.9c0 60.6.3 85.5.5 55 .5-30.2.5-79.9 0-110.3-.2-30.2-.5-5.3-.5 55.3"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 59.5 59.5" class="svg gitea-swift" width="16" height="16" aria-hidden="true"><path fill="#F05138" d="M59.387 16.45a83 83 0 0 0-.027-1.792c-.034-1.301-.111-2.614-.343-3.9-.234-1.308-.618-2.523-1.222-3.71a12.46 12.46 0 0 0-5.452-5.452C51.156.992 49.94.609 48.635.374c-1.287-.232-2.6-.308-3.902-.343a86 86 0 0 0-1.792-.027Q41.876-.001 40.813 0H18.578q-1.064-.001-2.127.004c-.598.004-1.196.01-1.793.027q-.488.012-.978.036c-.978.047-1.959.133-2.924.307-.98.176-1.908.436-2.811.81A12.5 12.5 0 0 0 3.89 3.89a12.5 12.5 0 0 0-2.294 3.158C.992 8.235.61 9.45.374 10.758c-.231 1.286-.308 2.599-.343 3.9a86 86 0 0 0-.027 1.792Q-.002 17.515 0 18.578v22.234q-.001 1.064.004 2.129c.004.597.01 1.194.027 1.79.035 1.302.112 2.615.343 3.902.235 1.306.618 2.522 1.222 3.71a12.457 12.457 0 0 0 5.453 5.453c1.186.603 2.401.986 3.707 1.22 1.287.232 2.6.309 3.902.344q.896.023 1.793.026 1.063.006 2.127.004h22.235q1.065.002 2.128-.004.897-.003 1.792-.026c1.302-.035 2.615-.112 3.902-.344 1.306-.234 2.521-.617 3.708-1.221a12.46 12.46 0 0 0 5.452-5.453c.604-1.187.988-2.403 1.223-3.71.23-1.286.308-2.599.342-3.9.017-.597.023-1.194.027-1.791q.006-1.065.004-2.129V18.578q.001-1.065-.004-2.128"/><path fill="#fff" d="m47.061 36.661-.004-.005c.066-.223.133-.446.19-.675 2.466-9.82-3.55-21.432-13.731-27.545 4.461 6.048 6.434 13.373 4.681 19.78-.156.572-.344 1.12-.552 1.653-.225-.148-.51-.316-.89-.526 0 0-10.128-6.253-21.104-17.312-.288-.29 5.853 8.776 12.822 16.14-3.283-1.843-12.434-8.5-18.227-13.802.712 1.186 1.559 2.33 2.49 3.43 4.837 6.135 11.145 13.704 18.703 19.517-5.31 3.25-12.814 3.502-20.285.003a30.7 30.7 0 0 1-5.193-3.098c3.162 5.058 8.033 9.423 13.96 11.97 7.07 3.039 14.1 2.833 19.337.05l-.004.007.079-.047q.323-.172.637-.358c2.516-1.306 7.485-2.63 10.152 2.559.653 1.27 2.041-5.46-3.062-11.739z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 59.5 59.5" class="svg gitea-swift" width="16" height="16" aria-hidden="true"><path fill="#f05138" d="M59.387 16.45a83 83 0 0 0-.027-1.792c-.034-1.301-.111-2.614-.343-3.9-.234-1.308-.618-2.523-1.222-3.71a12.46 12.46 0 0 0-5.452-5.452C51.156.992 49.94.609 48.635.374c-1.287-.232-2.6-.308-3.902-.343a86 86 0 0 0-1.792-.027Q41.876-.001 40.813 0H18.578q-1.064-.001-2.127.004c-.598.004-1.196.01-1.793.027q-.488.012-.978.036c-.978.047-1.959.133-2.924.307-.98.176-1.908.436-2.811.81A12.5 12.5 0 0 0 3.89 3.89a12.5 12.5 0 0 0-2.294 3.158C.992 8.235.61 9.45.374 10.758c-.231 1.286-.308 2.599-.343 3.9a86 86 0 0 0-.027 1.792Q-.002 17.515 0 18.578v22.234q-.001 1.064.004 2.129c.004.597.01 1.194.027 1.79.035 1.302.112 2.615.343 3.902.235 1.306.618 2.522 1.222 3.71a12.457 12.457 0 0 0 5.453 5.453c1.186.603 2.401.986 3.707 1.22 1.287.232 2.6.309 3.902.344q.896.023 1.793.026 1.063.006 2.127.004h22.235q1.065.002 2.128-.004.897-.003 1.792-.026c1.302-.035 2.615-.112 3.902-.344 1.306-.234 2.521-.617 3.708-1.221a12.46 12.46 0 0 0 5.452-5.453c.604-1.187.988-2.403 1.223-3.71.23-1.286.308-2.599.342-3.9.017-.597.023-1.194.027-1.791q.006-1.065.004-2.129V18.578q.001-1.065-.004-2.128"/><path fill="#fff" d="m47.061 36.661-.004-.005c.066-.223.133-.446.19-.675 2.466-9.82-3.55-21.432-13.731-27.545 4.461 6.048 6.434 13.373 4.681 19.78-.156.572-.344 1.12-.552 1.653-.225-.148-.51-.316-.89-.526 0 0-10.128-6.253-21.104-17.312-.288-.29 5.853 8.776 12.822 16.14-3.283-1.843-12.434-8.5-18.227-13.802.712 1.186 1.559 2.33 2.49 3.43 4.837 6.135 11.145 13.704 18.703 19.517-5.31 3.25-12.814 3.502-20.285.003a30.7 30.7 0 0 1-5.193-3.098c3.162 5.058 8.033 9.423 13.96 11.97 7.07 3.039 14.1 2.833 19.337.05l-.004.007.079-.047q.323-.172.637-.358c2.516-1.306 7.485-2.63 10.152 2.559.653 1.27 2.041-5.46-3.062-11.739z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" viewBox="0 0 255 263" class="svg gitea-vagrant" width="16" height="16" aria-hidden="true"><path fill="#1159CC" d="M254.22 20.234 196.03 53.47l-1.64 20.618-44.19 99.772-26.27 17.34 3.18 71.6 49.53-28.55 77.58-189.946zM92.45 56.933V34.051l-.238-.136-38.483 19.102 1.642 23.034L103.4 180.6l26.02-14.71-2.31-28.09z"/><path fill="#127EFF" d="m219.56 0-57.75 33.814h-.04v23.119L127.11 137.8v27.02l-23.12 13.41L57.788 74.146V53.81L92.45 33.848 34.668 0 .006 20.234v24.783L78.022 234.49l49.088 28.31v-71.16l23.09-13.41-.27-.17 46.51-103.914V53.81l57.78-33.576z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" viewBox="0 0 255 263" class="svg gitea-vagrant" width="16" height="16" aria-hidden="true"><path fill="#1159cc" d="M254.22 20.234 196.03 53.47l-1.64 20.618-44.19 99.772-26.27 17.34 3.18 71.6 49.53-28.55 77.58-189.946zM92.45 56.933V34.051l-.238-.136-38.483 19.102 1.642 23.034L103.4 180.6l26.02-14.71-2.31-28.09z"/><path fill="#127eff" d="m219.56 0-57.75 33.814h-.04v23.119L127.11 137.8v27.02l-23.12 13.41L57.788 74.146V53.81L92.45 33.848 34.668 0 .006 20.234v24.783L78.022 234.49l49.088 28.31v-71.16l23.09-13.41-.27-.17 46.51-103.914V53.81l57.78-33.576z"/></svg>

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 632 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-sparkle" width="16" height="16" aria-hidden="true"><path d="M7.198.57c.275-.752 1.34-.752 1.615 0l.849 2.317a5.82 5.82 0 0 0 3.462 3.463l2.317.848c.753.275.753 1.34 0 1.615l-2.317.849a5.82 5.82 0 0 0-3.462 3.462l-.849 2.317c-.275.753-1.34.753-1.615 0l-.848-2.317a5.82 5.82 0 0 0-3.463-3.462L.57 8.813c-.752-.275-.752-1.34 0-1.615l2.317-.848A5.82 5.82 0 0 0 6.35 2.887zm.562 2.833A7.32 7.32 0 0 1 3.403 7.76l-.673.246.673.246a7.32 7.32 0 0 1 4.357 4.356l.246.673.246-.673a7.32 7.32 0 0 1 4.356-4.356l.673-.246-.673-.246a7.32 7.32 0 0 1-4.356-4.357l-.246-.673z"/></svg>

After

Width:  |  Height:  |  Size: 646 B

View File

@ -467,7 +467,9 @@ func CommonRoutes() *web.Router {
g.MatchPath("HEAD", "/<group:*>/repodata/<filename>", rpm.CheckRepositoryFileExistence) g.MatchPath("HEAD", "/<group:*>/repodata/<filename>", rpm.CheckRepositoryFileExistence)
g.MatchPath("GET", "/<group:*>/repodata/<filename>", rpm.GetRepositoryFile) g.MatchPath("GET", "/<group:*>/repodata/<filename>", rpm.GetRepositoryFile)
g.MatchPath("PUT", "/<group:*>/upload", reqPackageAccess(perm.AccessModeWrite), rpm.UploadPackageFile) g.MatchPath("PUT", "/<group:*>/upload", reqPackageAccess(perm.AccessModeWrite), rpm.UploadPackageFile)
// this URL pattern is only used internally in the RPM index, it is generated by us, the filename part is not really used (can be anything)
g.MatchPath("HEAD,GET", "/<group:*>/package/<name>/<version>/<architecture>", rpm.DownloadPackageFile) g.MatchPath("HEAD,GET", "/<group:*>/package/<name>/<version>/<architecture>", rpm.DownloadPackageFile)
g.MatchPath("HEAD,GET", "/<group:*>/package/<name>/<version>/<architecture>/<filename>", rpm.DownloadPackageFile)
g.MatchPath("DELETE", "/<group:*>/package/<name>/<version>/<architecture>", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile) g.MatchPath("DELETE", "/<group:*>/package/<name>/<version>/<architecture>", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile)
}, reqPackageAccess(perm.AccessModeRead)) }, reqPackageAccess(perm.AccessModeRead))

View File

@ -51,7 +51,7 @@ func ListOrGetPackages(ctx *context.Context) {
DownloadPackageFile(ctx) DownloadPackageFile(ctx)
return return
} }
ctx.NotFound(nil) http.NotFound(ctx.Resp, ctx.Req)
} }
func EnumeratePackages(ctx *context.Context) { func EnumeratePackages(ctx *context.Context) {

View File

@ -53,15 +53,23 @@ type RegistrationIndexPageItem struct {
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#catalog-entry // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#catalog-entry
type CatalogEntry struct { type CatalogEntry struct {
CatalogLeafURL string `json:"@id"` CatalogLeafURL string `json:"@id"`
PackageContentURL string `json:"packageContent"`
ID string `json:"id"`
Version string `json:"version"`
Description string `json:"description"`
ReleaseNotes string `json:"releaseNotes"`
Authors string `json:"authors"` Authors string `json:"authors"`
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"` Copyright string `json:"copyright"`
ProjectURL string `json:"projectURL"`
DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"` DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
Description string `json:"description"`
IconURL string `json:"iconUrl"`
ID string `json:"id"`
IsPrerelease bool `json:"isPrerelease"`
Language string `json:"language"`
LicenseURL string `json:"licenseUrl"`
PackageContentURL string `json:"packageContent"`
ProjectURL string `json:"projectUrl"`
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
Summary string `json:"summary"`
Tags string `json:"tags"`
Version string `json:"version"`
ReleaseNotes string `json:"releaseNotes"`
Published time.Time `json:"published"`
} }
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency-group // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency-group
@ -109,15 +117,24 @@ func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageD
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version), PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
CatalogEntry: &CatalogEntry{ CatalogEntry: &CatalogEntry{
CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version), Authors: metadata.Authors,
ID: pd.Package.Name, Copyright: metadata.Copyright,
Version: pd.Version.Version, DependencyGroups: createDependencyGroups(pd),
Description: metadata.Description, Description: metadata.Description,
ReleaseNotes: metadata.ReleaseNotes, IconURL: metadata.IconURL,
Authors: metadata.Authors, ID: pd.Package.Name,
ProjectURL: metadata.ProjectURL, IsPrerelease: pd.Version.IsPrerelease(),
DependencyGroups: createDependencyGroups(pd), Language: metadata.Language,
LicenseURL: metadata.LicenseURL,
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
ProjectURL: metadata.ProjectURL,
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
Summary: metadata.Summary,
Tags: metadata.Tags,
Version: pd.Version.Version,
ReleaseNotes: metadata.ReleaseNotes,
Published: pd.Version.CreatedUnix.AsLocalTime(),
}, },
} }
} }
@ -145,22 +162,42 @@ func createDependencyGroups(pd *packages_model.PackageDescriptor) []*PackageDepe
// https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf
type RegistrationLeafResponse struct { type RegistrationLeafResponse struct {
RegistrationLeafURL string `json:"@id"` RegistrationLeafURL string `json:"@id"`
Type []string `json:"@type"` Type []string `json:"@type"`
Listed bool `json:"listed"` PackageContentURL string `json:"packageContent"`
PackageContentURL string `json:"packageContent"` RegistrationIndexURL string `json:"registration"`
Published time.Time `json:"published"` CatalogEntry CatalogEntry `json:"catalogEntry"`
RegistrationIndexURL string `json:"registration"`
} }
func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse { func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse {
registrationLeafURL := l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version)
packageDownloadURL := l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version)
metadata := pd.Metadata.(*nuget_module.Metadata)
return &RegistrationLeafResponse{ return &RegistrationLeafResponse{
Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"}, RegistrationLeafURL: registrationLeafURL,
Listed: true,
Published: pd.Version.CreatedUnix.AsLocalTime(),
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version),
RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name), RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name),
PackageContentURL: packageDownloadURL,
Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"},
CatalogEntry: CatalogEntry{
CatalogLeafURL: registrationLeafURL,
Authors: metadata.Authors,
Copyright: metadata.Copyright,
DependencyGroups: createDependencyGroups(pd),
Description: metadata.Description,
IconURL: metadata.IconURL,
ID: pd.Package.Name,
IsPrerelease: pd.Version.IsPrerelease(),
Language: metadata.Language,
LicenseURL: metadata.LicenseURL,
PackageContentURL: packageDownloadURL,
ProjectURL: metadata.ProjectURL,
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
Summary: metadata.Summary,
Tags: metadata.Tags,
Version: pd.Version.Version,
ReleaseNotes: metadata.ReleaseNotes,
Published: pd.Version.CreatedUnix.AsLocalTime(),
},
} }
} }
@ -188,13 +225,24 @@ type SearchResultResponse struct {
// https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
type SearchResult struct { type SearchResult struct {
ID string `json:"id"` Authors string `json:"authors"`
Version string `json:"version"` Copyright string `json:"copyright"`
Versions []*SearchResultVersion `json:"versions"` DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"`
Description string `json:"description"` Description string `json:"description"`
Authors string `json:"authors"` IconURL string `json:"iconUrl"`
ProjectURL string `json:"projectURL"` ID string `json:"id"`
RegistrationIndexURL string `json:"registration"` IsPrerelease bool `json:"isPrerelease"`
Language string `json:"language"`
LicenseURL string `json:"licenseUrl"`
ProjectURL string `json:"projectUrl"`
RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"`
Summary string `json:"summary"`
Tags string `json:"tags"`
Title string `json:"title"`
TotalDownloads int64 `json:"totalDownloads"`
Version string `json:"version"`
Versions []*SearchResultVersion `json:"versions"`
RegistrationIndexURL string `json:"registration"`
} }
// https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result
@ -230,11 +278,12 @@ func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages
func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor) *SearchResult { func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor) *SearchResult {
latest := pds[0] latest := pds[0]
versions := make([]*SearchResultVersion, 0, len(pds)) versions := make([]*SearchResultVersion, 0, len(pds))
totalDownloads := int64(0)
for _, pd := range pds { for _, pd := range pds {
if latest.SemVer.LessThan(pd.SemVer) { if latest.SemVer.LessThan(pd.SemVer) {
latest = pd latest = pd
} }
totalDownloads += pd.Version.DownloadCount
versions = append(versions, &SearchResultVersion{ versions = append(versions, &SearchResultVersion{
RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version),
Version: pd.Version.Version, Version: pd.Version.Version,
@ -244,12 +293,23 @@ func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor)
metadata := latest.Metadata.(*nuget_module.Metadata) metadata := latest.Metadata.(*nuget_module.Metadata)
return &SearchResult{ return &SearchResult{
ID: latest.Package.Name, Authors: metadata.Authors,
Version: latest.Version.Version, Copyright: metadata.Copyright,
Versions: versions, Description: metadata.Description,
Description: metadata.Description, DependencyGroups: createDependencyGroups(latest),
Authors: metadata.Authors, IconURL: metadata.IconURL,
ProjectURL: metadata.ProjectURL, ID: latest.Package.Name,
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name), IsPrerelease: latest.Version.IsPrerelease(),
Language: metadata.Language,
LicenseURL: metadata.LicenseURL,
ProjectURL: metadata.ProjectURL,
RequireLicenseAcceptance: metadata.RequireLicenseAcceptance,
Summary: metadata.Summary,
Tags: metadata.Tags,
Title: metadata.Title,
TotalDownloads: totalDownloads,
Version: latest.Version.Version,
Versions: versions,
RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name),
} }
} }

View File

@ -145,7 +145,7 @@ func repoAssignment() func(ctx *context.APIContext) {
) )
// Check if the user is the same as the repository owner. // Check if the user is the same as the repository owner.
if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) { if ctx.IsSigned && strings.EqualFold(ctx.Doer.LowerName, userName) {
owner = ctx.Doer owner = ctx.Doer
} else { } else {
owner, err = user_model.GetUserByName(ctx, userName) owner, err = user_model.GetUserByName(ctx, userName)

View File

@ -276,7 +276,7 @@ func GetRepoPermissions(ctx *context.APIContext) {
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
collaboratorUsername := ctx.PathParam("collaborator") collaboratorUsername := ctx.PathParam("collaborator")
if !ctx.Doer.IsAdmin && ctx.Doer.LowerName != strings.ToLower(collaboratorUsername) && !ctx.IsUserRepoAdmin() { if !ctx.Doer.IsAdmin && !strings.EqualFold(ctx.Doer.LowerName, collaboratorUsername) && !ctx.IsUserRepoAdmin() {
ctx.APIError(http.StatusForbidden, "Only admins can query all permissions, repo admins can query all repo permissions, collaborators can query only their own") ctx.APIError(http.StatusForbidden, "Only admins can query all permissions, repo admins can query all repo permissions, collaborators can query only their own")
return return
} }

View File

@ -812,7 +812,8 @@ func GetContentsExt(ctx *context.APIContext) {
// required: true // required: true
// - name: filepath // - name: filepath
// in: path // in: path
// description: path of the dir, file, symlink or submodule in the repo // description: path of the dir, file, symlink or submodule in the repo. Swagger requires path parameter to be "required",
// you can leave it empty or pass a single dot (".") to get the root directory.
// type: string // type: string
// required: true // required: true
// - name: ref // - name: ref
@ -823,7 +824,8 @@ func GetContentsExt(ctx *context.APIContext) {
// - name: includes // - name: includes
// in: query // in: query
// description: By default this API's response only contains file's metadata. Use comma-separated "includes" options to retrieve more fields. // description: By default this API's response only contains file's metadata. Use comma-separated "includes" options to retrieve more fields.
// Option "file_content" will try to retrieve the file content, option "lfs_metadata" will try to retrieve LFS metadata. // Option "file_content" will try to retrieve the file content, "lfs_metadata" will try to retrieve LFS metadata,
// "commit_metadata" will try to retrieve commit metadata, and "commit_message" will try to retrieve commit message.
// type: string // type: string
// required: false // required: false
// responses: // responses:
@ -832,6 +834,9 @@ func GetContentsExt(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
if treePath := ctx.PathParam("*"); treePath == "." || treePath == "/" {
ctx.SetPathParam("*", "") // workaround for swagger, it requires path parameter to be "required", but we need to list root directory
}
opts := files_service.GetContentsOrListOptions{TreePath: ctx.PathParam("*")} opts := files_service.GetContentsOrListOptions{TreePath: ctx.PathParam("*")}
for includeOpt := range strings.SplitSeq(ctx.FormString("includes"), ",") { for includeOpt := range strings.SplitSeq(ctx.FormString("includes"), ",") {
if includeOpt == "" { if includeOpt == "" {
@ -842,6 +847,10 @@ func GetContentsExt(ctx *context.APIContext) {
opts.IncludeSingleFileContent = true opts.IncludeSingleFileContent = true
case "lfs_metadata": case "lfs_metadata":
opts.IncludeLfsMetadata = true opts.IncludeLfsMetadata = true
case "commit_metadata":
opts.IncludeCommitMetadata = true
case "commit_message":
opts.IncludeCommitMessage = true
default: default:
ctx.APIError(http.StatusBadRequest, fmt.Sprintf("unknown include option %q", includeOpt)) ctx.APIError(http.StatusBadRequest, fmt.Sprintf("unknown include option %q", includeOpt))
return return
@ -883,7 +892,11 @@ func GetContents(ctx *context.APIContext) {
// "$ref": "#/responses/ContentsResponse" // "$ref": "#/responses/ContentsResponse"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
ret := getRepoContents(ctx, files_service.GetContentsOrListOptions{TreePath: ctx.PathParam("*"), IncludeSingleFileContent: true}) ret := getRepoContents(ctx, files_service.GetContentsOrListOptions{
TreePath: ctx.PathParam("*"),
IncludeSingleFileContent: true,
IncludeCommitMetadata: true,
})
if ctx.Written() { if ctx.Written() {
return return
} }

View File

@ -669,7 +669,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
newRepoName = *opts.Name newRepoName = *opts.Name
} }
// Check if repository name has been changed and not just a case change // Check if repository name has been changed and not just a case change
if repo.LowerName != strings.ToLower(newRepoName) { if !strings.EqualFold(repo.LowerName, newRepoName) {
if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil { if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
switch { switch {
case repo_model.IsErrRepoAlreadyExist(err): case repo_model.IsErrRepoAlreadyExist(err):

View File

@ -6,6 +6,7 @@ package common
import ( import (
goctx "context" goctx "context"
"errors" "errors"
"sync"
activities_model "code.gitea.io/gitea/models/activities" activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -22,8 +23,7 @@ type StopwatchTmplInfo struct {
Seconds int64 Seconds int64
} }
func getActiveStopwatch(goCtx goctx.Context) *StopwatchTmplInfo { func getActiveStopwatch(ctx *context.Context) *StopwatchTmplInfo {
ctx := context.GetWebContext(goCtx)
if ctx.Doer == nil { if ctx.Doer == nil {
return nil return nil
} }
@ -48,8 +48,7 @@ func getActiveStopwatch(goCtx goctx.Context) *StopwatchTmplInfo {
} }
} }
func notificationUnreadCount(goCtx goctx.Context) int64 { func notificationUnreadCount(ctx *context.Context) int64 {
ctx := context.GetWebContext(goCtx)
if ctx.Doer == nil { if ctx.Doer == nil {
return 0 return 0
} }
@ -66,10 +65,19 @@ func notificationUnreadCount(goCtx goctx.Context) int64 {
return count return count
} }
func PageTmplFunctions(ctx *context.Context) { type pageGlobalDataType struct {
if ctx.IsSigned { IsSigned bool
// defer the function call to the last moment when the tmpl renders IsSiteAdmin bool
ctx.Data["NotificationUnreadCount"] = notificationUnreadCount
ctx.Data["GetActiveStopwatch"] = getActiveStopwatch GetNotificationUnreadCount func() int64
} GetActiveStopwatch func() *StopwatchTmplInfo
}
func PageGlobalData(ctx *context.Context) {
var data pageGlobalDataType
data.IsSigned = ctx.Doer != nil
data.IsSiteAdmin = ctx.Doer != nil && ctx.Doer.IsAdmin
data.GetNotificationUnreadCount = sync.OnceValue(func() int64 { return notificationUnreadCount(ctx) })
data.GetActiveStopwatch = sync.OnceValue(func() *StopwatchTmplInfo { return getActiveStopwatch(ctx) })
ctx.Data["PageGlobalData"] = data
} }

View File

@ -4,7 +4,6 @@
package auth package auth
import ( import (
"errors"
"fmt" "fmt"
"html" "html"
"html/template" "html/template"
@ -15,7 +14,7 @@ import (
"code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/auth/httpauth"
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -108,9 +107,8 @@ func InfoOAuth(ctx *context.Context) {
var accessTokenScope auth.AccessTokenScope var accessTokenScope auth.AccessTokenScope
if auHead := ctx.Req.Header.Get("Authorization"); auHead != "" { if auHead := ctx.Req.Header.Get("Authorization"); auHead != "" {
auths := strings.Fields(auHead) if parsed, ok := httpauth.ParseAuthorizationHeader(auHead); ok && parsed.BearerToken != nil {
if len(auths) == 2 && (auths[0] == "token" || strings.ToLower(auths[0]) == "bearer") { accessTokenScope, _ = auth_service.GetOAuthAccessTokenScopeAndUserID(ctx, parsed.BearerToken.Token)
accessTokenScope, _ = auth_service.GetOAuthAccessTokenScopeAndUserID(ctx, auths[1])
} }
} }
@ -127,18 +125,12 @@ func InfoOAuth(ctx *context.Context) {
ctx.JSON(http.StatusOK, response) ctx.JSON(http.StatusOK, response)
} }
func parseBasicAuth(ctx *context.Context) (username, password string, err error) {
authHeader := ctx.Req.Header.Get("Authorization")
if authType, authData, ok := strings.Cut(authHeader, " "); ok && strings.EqualFold(authType, "Basic") {
return base.BasicAuthDecode(authData)
}
return "", "", errors.New("invalid basic authentication")
}
// IntrospectOAuth introspects an oauth token // IntrospectOAuth introspects an oauth token
func IntrospectOAuth(ctx *context.Context) { func IntrospectOAuth(ctx *context.Context) {
clientIDValid := false clientIDValid := false
if clientID, clientSecret, err := parseBasicAuth(ctx); err == nil { authHeader := ctx.Req.Header.Get("Authorization")
if parsed, ok := httpauth.ParseAuthorizationHeader(authHeader); ok && parsed.BasicAuth != nil {
clientID, clientSecret := parsed.BasicAuth.Username, parsed.BasicAuth.Password
app, err := auth.GetOAuth2ApplicationByClientID(ctx, clientID) app, err := auth.GetOAuth2ApplicationByClientID(ctx, clientID)
if err != nil && !auth.IsErrOauthClientIDInvalid(err) { if err != nil && !auth.IsErrOauthClientIDInvalid(err) {
// this is likely a database error; log it and respond without details // this is likely a database error; log it and respond without details
@ -170,9 +162,7 @@ func IntrospectOAuth(ctx *context.Context) {
if err == nil && app != nil { if err == nil && app != nil {
response.Active = true response.Active = true
response.Scope = grant.Scope response.Scope = grant.Scope
response.Issuer = setting.AppURL response.RegisteredClaims = oauth2_provider.NewJwtRegisteredClaimsFromUser(app.ClientID, grant.UserID, nil /*exp*/)
response.Audience = []string{app.ClientID}
response.Subject = strconv.FormatInt(grant.UserID, 10)
} }
if user, err := user_model.GetUserByID(ctx, grant.UserID); err == nil { if user, err := user_model.GetUserByID(ctx, grant.UserID); err == nil {
response.Username = user.Name response.Username = user.Name
@ -432,7 +422,14 @@ func GrantApplicationOAuth(ctx *context.Context) {
// OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities // OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities
func OIDCWellKnown(ctx *context.Context) { func OIDCWellKnown(ctx *context.Context) {
ctx.Data["SigningKey"] = oauth2_provider.DefaultSigningKey if !setting.OAuth2.Enabled {
http.NotFound(ctx.Resp, ctx.Req)
return
}
jwtRegisteredClaims := oauth2_provider.NewJwtRegisteredClaimsFromUser("well-known", 0, nil)
ctx.Data["OidcIssuer"] = jwtRegisteredClaims.Issuer // use the consistent issuer from the JWT registered claims
ctx.Data["OidcBaseUrl"] = strings.TrimSuffix(setting.AppURL, "/")
ctx.Data["SigningKeyMethodAlg"] = oauth2_provider.DefaultSigningKey.SigningMethod().Alg()
ctx.JSONTemplate("user/auth/oidc_wellknown") ctx.JSONTemplate("user/auth/oidc_wellknown")
} }
@ -465,16 +462,16 @@ func AccessTokenOAuth(ctx *context.Context) {
form := *web.GetForm(ctx).(*forms.AccessTokenForm) form := *web.GetForm(ctx).(*forms.AccessTokenForm)
// if there is no ClientID or ClientSecret in the request body, fill these fields by the Authorization header and ensure the provided field matches the Authorization header // if there is no ClientID or ClientSecret in the request body, fill these fields by the Authorization header and ensure the provided field matches the Authorization header
if form.ClientID == "" || form.ClientSecret == "" { if form.ClientID == "" || form.ClientSecret == "" {
authHeader := ctx.Req.Header.Get("Authorization") if authHeader := ctx.Req.Header.Get("Authorization"); authHeader != "" {
if authType, authData, ok := strings.Cut(authHeader, " "); ok && strings.EqualFold(authType, "Basic") { parsed, ok := httpauth.ParseAuthorizationHeader(authHeader)
clientID, clientSecret, err := base.BasicAuthDecode(authData) if !ok || parsed.BasicAuth == nil {
if err != nil {
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{ handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{
ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidRequest, ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidRequest,
ErrorDescription: "cannot parse basic auth header", ErrorDescription: "cannot parse basic auth header",
}) })
return return
} }
clientID, clientSecret := parsed.BasicAuth.Username, parsed.BasicAuth.Password
// validate that any fields present in the form match the Basic auth header // validate that any fields present in the form match the Basic auth header
if form.ClientID != "" && form.ClientID != clientID { if form.ClientID != "" && form.ClientID != clientID {
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{ handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{

View File

@ -249,7 +249,7 @@ func ViewPost(ctx *context_module.Context) {
ID: v.ID, ID: v.ID,
Name: v.Name, Name: v.Name,
Status: v.Status.String(), Status: v.Status.String(),
CanRerun: v.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions), CanRerun: resp.State.Run.CanRerun,
Duration: v.Duration().String(), Duration: v.Duration().String(),
}) })
} }
@ -445,7 +445,7 @@ func Rerun(ctx *context_module.Context) {
return return
} }
} }
ctx.JSON(http.StatusOK, struct{}{}) ctx.JSONOK()
return return
} }
@ -460,12 +460,12 @@ func Rerun(ctx *context_module.Context) {
} }
} }
ctx.JSON(http.StatusOK, struct{}{}) ctx.JSONOK()
} }
func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shouldBlock bool) error { func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shouldBlock bool) error {
status := job.Status status := job.Status
if !status.IsDone() { if !status.IsDone() || !job.Run.Status.IsDone() {
return nil return nil
} }

View File

@ -166,10 +166,13 @@ func Graph(ctx *context.Context) {
ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Username"] = ctx.Repo.Owner.Name
ctx.Data["Reponame"] = ctx.Repo.Repository.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name
divOnly := ctx.FormBool("div-only")
queryParams := ctx.Req.URL.Query()
queryParams.Del("div-only")
paginator := context.NewPagination(int(graphCommitsCount), setting.UI.GraphMaxCommitNum, page, 5) paginator := context.NewPagination(int(graphCommitsCount), setting.UI.GraphMaxCommitNum, page, 5)
paginator.AddParamFromRequest(ctx.Req) paginator.AddParamFromQuery(queryParams)
ctx.Data["Page"] = paginator ctx.Data["Page"] = paginator
if ctx.FormBool("div-only") { if divOnly {
ctx.HTML(http.StatusOK, tplGraphDiv) ctx.HTML(http.StatusOK, tplGraphDiv)
return return
} }

View File

@ -443,6 +443,10 @@ func ViewPullMergeBox(ctx *context.Context) {
preparePullViewPullInfo(ctx, issue) preparePullViewPullInfo(ctx, issue)
preparePullViewReviewAndMerge(ctx, issue) preparePullViewReviewAndMerge(ctx, issue)
ctx.Data["PullMergeBoxReloading"] = issue.PullRequest.IsChecking() ctx.Data["PullMergeBoxReloading"] = issue.PullRequest.IsChecking()
// TODO: it should use a dedicated struct to render the pull merge box, to make sure all data is prepared correctly
ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID)
ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
ctx.HTML(http.StatusOK, tplPullMergeBox) ctx.HTML(http.StatusOK, tplPullMergeBox)
} }

View File

@ -165,7 +165,7 @@ func handleSettingsPostUpdate(ctx *context.Context) {
newRepoName := form.RepoName newRepoName := form.RepoName
// Check if repository name has been changed. // Check if repository name has been changed.
if repo.LowerName != strings.ToLower(newRepoName) { if !strings.EqualFold(repo.LowerName, newRepoName) {
// Close the GitRepo if open // Close the GitRepo if open
if ctx.Repo.GitRepo != nil { if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close() ctx.Repo.GitRepo.Close()

View File

@ -198,7 +198,6 @@ type webhookParams struct {
URL string URL string
ContentType webhook.HookContentType ContentType webhook.HookContentType
Secret string
HTTPMethod string HTTPMethod string
WebhookForm forms.WebhookForm WebhookForm forms.WebhookForm
Meta any Meta any
@ -237,7 +236,7 @@ func createWebhook(ctx *context.Context, params webhookParams) {
URL: params.URL, URL: params.URL,
HTTPMethod: params.HTTPMethod, HTTPMethod: params.HTTPMethod,
ContentType: params.ContentType, ContentType: params.ContentType,
Secret: params.Secret, Secret: params.WebhookForm.Secret,
HookEvent: ParseHookEvent(params.WebhookForm), HookEvent: ParseHookEvent(params.WebhookForm),
IsActive: params.WebhookForm.Active, IsActive: params.WebhookForm.Active,
Type: params.Type, Type: params.Type,
@ -290,7 +289,7 @@ func editWebhook(ctx *context.Context, params webhookParams) {
w.URL = params.URL w.URL = params.URL
w.ContentType = params.ContentType w.ContentType = params.ContentType
w.Secret = params.Secret w.Secret = params.WebhookForm.Secret
w.HookEvent = ParseHookEvent(params.WebhookForm) w.HookEvent = ParseHookEvent(params.WebhookForm)
w.IsActive = params.WebhookForm.Active w.IsActive = params.WebhookForm.Active
w.HTTPMethod = params.HTTPMethod w.HTTPMethod = params.HTTPMethod
@ -336,7 +335,6 @@ func giteaHookParams(ctx *context.Context) webhookParams {
Type: webhook_module.GITEA, Type: webhook_module.GITEA,
URL: form.PayloadURL, URL: form.PayloadURL,
ContentType: contentType, ContentType: contentType,
Secret: form.Secret,
HTTPMethod: form.HTTPMethod, HTTPMethod: form.HTTPMethod,
WebhookForm: form.WebhookForm, WebhookForm: form.WebhookForm,
} }
@ -364,7 +362,6 @@ func gogsHookParams(ctx *context.Context) webhookParams {
Type: webhook_module.GOGS, Type: webhook_module.GOGS,
URL: form.PayloadURL, URL: form.PayloadURL,
ContentType: contentType, ContentType: contentType,
Secret: form.Secret,
WebhookForm: form.WebhookForm, WebhookForm: form.WebhookForm,
} }
} }

View File

@ -6,6 +6,7 @@ package repo
import ( import (
"html/template" "html/template"
"net/http" "net/http"
"path"
"strings" "strings"
pull_model "code.gitea.io/gitea/models/pull" pull_model "code.gitea.io/gitea/models/pull"
@ -111,7 +112,7 @@ func transformDiffTreeForWeb(renderedIconPool *fileicon.RenderedIconPool, diffTr
item := &WebDiffFileItem{FullName: file.HeadPath, DiffStatus: file.Status} item := &WebDiffFileItem{FullName: file.HeadPath, DiffStatus: file.Status}
item.IsViewed = filesViewedState[item.FullName] == pull_model.Viewed item.IsViewed = filesViewedState[item.FullName] == pull_model.Viewed
item.NameHash = git.HashFilePathForWebUI(item.FullName) item.NameHash = git.HashFilePathForWebUI(item.FullName)
item.FileIcon = fileicon.RenderEntryIconHTML(renderedIconPool, &fileicon.EntryInfo{FullName: file.HeadPath, EntryMode: file.HeadMode}) item.FileIcon = fileicon.RenderEntryIconHTML(renderedIconPool, &fileicon.EntryInfo{BaseName: path.Base(file.HeadPath), EntryMode: file.HeadMode})
switch file.HeadMode { switch file.HeadMode {
case git.EntryModeTree: case git.EntryModeTree:

View File

@ -12,6 +12,7 @@ import (
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"path"
"strings" "strings"
"time" "time"
@ -260,7 +261,9 @@ func prepareDirectoryFileIcons(ctx *context.Context, files []git.CommitInfo) {
renderedIconPool := fileicon.NewRenderedIconPool() renderedIconPool := fileicon.NewRenderedIconPool()
fileIcons := map[string]template.HTML{} fileIcons := map[string]template.HTML{}
for _, f := range files { for _, f := range files {
fileIcons[f.Entry.Name()] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFromGitTreeEntry(f.Entry)) fullPath := path.Join(ctx.Repo.TreePath, f.Entry.Name())
entryInfo := fileicon.EntryInfoFromGitTreeEntry(ctx.Repo.Commit, fullPath, f.Entry)
fileIcons[f.Entry.Name()] = fileicon.RenderEntryIconHTML(renderedIconPool, entryInfo)
} }
fileIcons[".."] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFolder()) fileIcons[".."] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFolder())
ctx.Data["FileIcons"] = fileIcons ctx.Data["FileIcons"] = fileIcons

Some files were not shown because too many files have changed in this diff Show More