diff --git a/.drone.yml b/.drone.yml index 88ef4a7a9cf3..10444d689f54 100644 --- a/.drone.yml +++ b/.drone.yml @@ -854,6 +854,67 @@ steps: exclude: - pull_request +--- +kind: pipeline +name: docker-linux-amd64-release-branch + +platform: + os: linux + arch: amd64 + +depends_on: + - testing-amd64 + - testing-arm64 + +trigger: + ref: + - "refs/heads/release/v*" + event: + exclude: + - cron + +steps: + - name: fetch-tags + image: docker:git + commands: + - git fetch --tags --force + + - name: publish + pull: always + image: techknowlogick/drone-docker:latest + settings: + auto_tag: false + tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64 + repo: gitea/gitea + build_args: + - GOPROXY=https://goproxy.cn + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + + - name: publish-rootless + image: techknowlogick/drone-docker:latest + settings: + dockerfile: Dockerfile.rootless + auto_tag: false + tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64-rootless + repo: gitea/gitea + build_args: + - GOPROXY=https://goproxy.cn + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + --- kind: pipeline type: docker @@ -1010,6 +1071,68 @@ steps: event: exclude: - pull_request + +--- +kind: pipeline +name: docker-linux-arm64-release-branch + +platform: + os: linux + arch: arm64 + +depends_on: + - testing-amd64 + - testing-arm64 + +trigger: + ref: + - "refs/heads/release/v*" + event: + exclude: + - cron + +steps: + - name: fetch-tags + image: docker:git + commands: + - git fetch --tags --force + + - name: publish + pull: always + image: techknowlogick/drone-docker:latest + settings: + auto_tag: false + tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64 + repo: gitea/gitea + build_args: + - GOPROXY=https://goproxy.cn + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + + - name: publish-rootless + image: techknowlogick/drone-docker:latest + settings: + dockerfile: Dockerfile.rootless + auto_tag: false + tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64-rootless + repo: gitea/gitea + build_args: + - GOPROXY=https://goproxy.cn + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + --- kind: pipeline type: docker @@ -1090,6 +1213,7 @@ steps: trigger: ref: - refs/heads/main + - "refs/heads/release/v*" event: exclude: - cron @@ -1097,6 +1221,8 @@ trigger: depends_on: - docker-linux-amd64-release - docker-linux-arm64-release + - docker-linux-amd64-release-branch + - docker-linux-arm64-release-branch --- kind: pipeline @@ -1130,6 +1256,8 @@ depends_on: - docker-linux-arm64-release - docker-linux-amd64-release-version - docker-linux-arm64-release-version + - docker-linux-amd64-release-branch + - docker-linux-arm64-release-branch - docker-manifest - docker-manifest-version - docs diff --git a/.gitattributes b/.gitattributes index 4e83849e03e7..12c45dbc6a07 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1,9 @@ * text=auto eol=lf -/vendor/** -text -eol linguist-vendored -/public/vendor/** -text -eol linguist-vendored -/web_src/js/vendor/** -text -eol linguist-vendored -/templates/**/*.tmpl linguist-language=Handlebars +*.tmpl linguist-language=Handlebars /.eslintrc linguist-language=YAML /.stylelintrc linguist-language=YAML +/public/vendor/** -text -eol linguist-vendored +/vendor/** -text -eol linguist-vendored /web_src/fomantic/build/** linguist-generated +/web_src/js/vendor/** -text -eol linguist-vendored Dockerfile.* linguist-language=Dockerfile diff --git a/docker/manifest.rootless.tmpl b/docker/manifest.rootless.tmpl index 1d14041ff276..955941647077 100644 --- a/docker/manifest.rootless.tmpl +++ b/docker/manifest.rootless.tmpl @@ -1,4 +1,4 @@ -image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-rootless +image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless {{#if build.tags}} tags: {{#each build.tags}} @@ -8,12 +8,12 @@ tags: {{/if}} manifests: - - image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-linux-amd64-rootless + image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64-rootless platform: architecture: amd64 os: linux - - image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-linux-arm64-rootless + image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64-rootless platform: architecture: arm64 os: linux diff --git a/docker/manifest.tmpl b/docker/manifest.tmpl index 43a57f7f2722..4cd4ea4ea2d8 100644 --- a/docker/manifest.tmpl +++ b/docker/manifest.tmpl @@ -1,4 +1,4 @@ -image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}} +image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}} {{#if build.tags}} tags: {{#each build.tags}} @@ -8,13 +8,13 @@ tags: {{/if}} manifests: - - image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{else}}dev-{{/if}}linux-amd64 + image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64 platform: architecture: amd64 os: linux - - image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{else}}dev-{{/if}}linux-arm64 + image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64 platform: architecture: arm64 os: linux - variant: v8 \ No newline at end of file + variant: v8 diff --git a/docs/content/doc/installation/with-docker-rootless.en-us.md b/docs/content/doc/installation/with-docker-rootless.en-us.md index b5bc660afbc1..e3de969122ed 100644 --- a/docs/content/doc/installation/with-docker-rootless.en-us.md +++ b/docs/content/doc/installation/with-docker-rootless.en-us.md @@ -32,7 +32,7 @@ image as a service. Since there is no database available, one can be initialized Create a directory for `data` and `config` then paste the following content into a file named `docker-compose.yml`. Note that the volume should be owned by the user/group with the UID/GID specified in the config file. By default Gitea in docker will use uid:1000 gid:1000. If needed you can set ownership on those folders with the command: `sudo chown 1000:1000 config/ data/` If you don't give the volume correct permissions, the container may not start. -For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:dev-rootless` would be an appropriate tag. +For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:dev-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev-rootless`) ```yaml version: "2" diff --git a/docs/content/doc/installation/with-docker.en-us.md b/docs/content/doc/installation/with-docker.en-us.md index 3462d8f377a1..261369c128bf 100644 --- a/docs/content/doc/installation/with-docker.en-us.md +++ b/docs/content/doc/installation/with-docker.en-us.md @@ -34,7 +34,7 @@ image as a service. Since there is no database available, one can be initialized Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`. Note that the volume should be owned by the user/group with the UID/GID specified in the config file. If you don't give the volume correct permissions, the container may not start. -For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:dev` tag. +For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:dev` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev`) ```yaml version: "3" diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 90e872e63562..80a2c6716de5 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -129,7 +129,7 @@ Admin operations: - `--custom-profile-url`: Use a custom Profile URL (option for GitLab/GitHub). - `--custom-email-url`: Use a custom Email URL (option for GitHub). - `--icon-url`: Custom icon URL for OAuth2 login source. - - `--override-local-2fa`: Allow source to override local 2FA. (Optional) + - `--skip-local-2fa`: Allow source to override local 2FA. (Optional) - `--scopes`: Additional scopes to request for this OAuth2 source. (Optional) - `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional) - `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional) @@ -152,7 +152,7 @@ Admin operations: - `--custom-profile-url`: Use a custom Profile URL (option for GitLab/GitHub). - `--custom-email-url`: Use a custom Email URL (option for GitHub). - `--icon-url`: Custom icon URL for OAuth2 login source. - - `--override-local-2fa`: Allow source to override local 2FA. (Optional) + - `--skip-local-2fa`: Allow source to override local 2FA. (Optional) - `--scopes`: Additional scopes to request for this OAuth2 source. - `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional) - `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional) diff --git a/integrations/api_oauth2_apps_test.go b/integrations/api_oauth2_apps_test.go index e51549568a6a..2c08338b25b9 100644 --- a/integrations/api_oauth2_apps_test.go +++ b/integrations/api_oauth2_apps_test.go @@ -43,7 +43,7 @@ func testAPICreateOAuth2Application(t *testing.T) { DecodeJSON(t, resp, &createdApp) assert.EqualValues(t, appBody.Name, createdApp.Name) - assert.Len(t, createdApp.ClientSecret, 44) + assert.Len(t, createdApp.ClientSecret, 56) assert.Len(t, createdApp.ClientID, 36) assert.NotEmpty(t, createdApp.Created) assert.EqualValues(t, appBody.RedirectURIs[0], createdApp.RedirectURIs[0]) diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index e7030fce2898..2341e0862025 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -6,13 +6,13 @@ package auth import ( "crypto/sha256" + "encoding/base32" "encoding/base64" "fmt" "net/url" "strings" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/secret" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -57,12 +57,22 @@ func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { return util.IsStringInSlice(redirectURI, app.RedirectURIs, true) } +// Base32 characters, but lowercased. +const lowerBase32Chars = "abcdefghijklmnopqrstuvwxyz234567" + +// base32 encoder that uses lowered characters without padding. +var base32Lower = base32.NewEncoding(lowerBase32Chars).WithPadding(base32.NoPadding) + // GenerateClientSecret will generate the client secret and returns the plaintext and saves the hash at the database func (app *OAuth2Application) GenerateClientSecret() (string, error) { - clientSecret, err := secret.New() + rBytes, err := util.CryptoRandomBytes(32) if err != nil { return "", err } + // Add a prefix to the base32, this is in order to make it easier + // for code scanners to grab sensitive tokens. + clientSecret := "gto_" + base32Lower.EncodeToString(rBytes) + hashedSecret, err := bcrypt.GenerateFromPassword([]byte(clientSecret), bcrypt.DefaultCost) if err != nil { return "", err @@ -394,10 +404,14 @@ func (grant *OAuth2Grant) GenerateNewAuthorizationCode(redirectURI, codeChalleng } func (grant *OAuth2Grant) generateNewAuthorizationCode(e db.Engine, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) { - var codeSecret string - if codeSecret, err = secret.New(); err != nil { + rBytes, err := util.CryptoRandomBytes(32) + if err != nil { return &OAuth2AuthorizationCode{}, err } + // Add a prefix to the base32, this is in order to make it easier + // for code scanners to grab sensitive tokens. + codeSecret := "gta_" + base32Lower.EncodeToString(rBytes) + code = &OAuth2AuthorizationCode{ Grant: grant, GrantID: grant.ID, diff --git a/modules/secret/secret.go b/modules/secret/secret.go index 6b410f238197..e7edc7a95e52 100644 --- a/modules/secret/secret.go +++ b/modules/secret/secret.go @@ -13,20 +13,8 @@ import ( "encoding/hex" "errors" "io" - - "code.gitea.io/gitea/modules/util" ) -// New creates a new secret -func New() (string, error) { - return NewWithLength(44) -} - -// NewWithLength creates a new secret for a given length -func NewWithLength(length int64) (string, error) { - return util.CryptoRandomString(length) -} - // AesEncrypt encrypts text and given key with AES. func AesEncrypt(key, text []byte) ([]byte, error) { block, err := aes.NewCipher(key) diff --git a/modules/secret/secret_test.go b/modules/secret/secret_test.go index f3a88eecc825..b1c99d851363 100644 --- a/modules/secret/secret_test.go +++ b/modules/secret/secret_test.go @@ -10,17 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestNew(t *testing.T) { - result, err := New() - assert.NoError(t, err) - assert.True(t, len(result) == 44) - - result2, err := New() - assert.NoError(t, err) - // check if secrets - assert.NotEqual(t, result, result2) -} - func TestEncryptDecrypt(t *testing.T) { var hex string var str string diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index faeb3efb0177..86debf9c87e2 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -268,6 +268,7 @@ search=検索 code=コード search.fuzzy=あいまい search.match=一致 +code_search_unavailable=現在コード検索は利用できません。 サイト管理者にお問い合わせください。 repo_no_results=一致するリポジトリが見つかりません。 user_no_results=一致するユーザーが見つかりません。 org_no_results=一致する組織が見つかりません。 @@ -1262,6 +1263,7 @@ issues.filter_sort.moststars=スターが多い順 issues.filter_sort.feweststars=スターが少ない順 issues.filter_sort.mostforks=フォークが多い順 issues.filter_sort.fewestforks=フォークが少ない順 +issues.keyword_search_unavailable=現在キーワード検索は利用できません。 サイト管理者にお問い合わせください。 issues.action_open=オープン issues.action_close=クローズ issues.action_label=ラベル @@ -1707,6 +1709,8 @@ search.search_repo=リポジトリを検索 search.fuzzy=あいまい search.match=一致 search.results=%[3]s 内での "%[1]s" の検索結果 +search.code_no_results=検索ワードに一致するソースコードが見つかりません。 +search.code_search_unavailable=現在コード検索は利用できません。 サイト管理者にお問い合わせください。 settings=設定 settings.desc=設定では、リポジトリの設定を管理することができます。 diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index a8a132bc941a..64e9c5c20822 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -822,7 +822,7 @@ func SignInOAuthCallback(ctx *context.Context) { u, gothUser, err := oAuth2UserLoginCallback(authSource, ctx.Req, ctx.Resp) if err != nil { if user_model.IsErrUserProhibitLogin(err) { - uplerr := err.(*user_model.ErrUserProhibitLogin) + uplerr := err.(user_model.ErrUserProhibitLogin) log.Info("Failed authentication attempt for %s from %s: %v", uplerr.Name, ctx.RemoteAddr(), err) ctx.Data["Title"] = ctx.Tr("auth.prohibit_login") ctx.HTML(http.StatusOK, "user/auth/prohibit_login") diff --git a/services/mailer/mail.go b/services/mailer/mail.go index e5aa2500837b..d5f3f2ac0379 100644 --- a/services/mailer/mail.go +++ b/services/mailer/mail.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" texttmpl "text/template" + "time" "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" @@ -298,13 +299,15 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient } // Make sure to compose independent messages to avoid leaking user emails + msgID := createReference(ctx.Issue, ctx.Comment, ctx.ActionType) + reference := createReference(ctx.Issue, nil, models.ActionType(0)) + msgs := make([]*Message, 0, len(recipients)) for _, recipient := range recipients { msg := NewMessageFrom([]string{recipient.Email}, ctx.Doer.DisplayName(), setting.MailService.FromEmail, subject, mailBody.String()) msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info) - msg.SetHeader("Message-ID", "<"+createReference(ctx.Issue, ctx.Comment)+">") - reference := createReference(ctx.Issue, nil) + msg.SetHeader("Message-ID", "<"+msgID+">") msg.SetHeader("In-Reply-To", "<"+reference+">") msg.SetHeader("References", "<"+reference+">") @@ -318,7 +321,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient return msgs, nil } -func createReference(issue *models.Issue, comment *models.Comment) string { +func createReference(issue *models.Issue, comment *models.Comment, actionType models.ActionType) string { var path string if issue.IsPull { path = "pulls" @@ -329,6 +332,17 @@ func createReference(issue *models.Issue, comment *models.Comment) string { var extra string if comment != nil { extra = fmt.Sprintf("/comment/%d", comment.ID) + } else { + switch actionType { + case models.ActionCloseIssue, models.ActionClosePullRequest: + extra = fmt.Sprintf("/close/%d", time.Now().UnixNano()/1e6) + case models.ActionReopenIssue, models.ActionReopenPullRequest: + extra = fmt.Sprintf("/reopen/%d", time.Now().UnixNano()/1e6) + case models.ActionMergePullRequest: + extra = fmt.Sprintf("/merge/%d", time.Now().UnixNano()/1e6) + case models.ActionPullRequestReadyForReview: + extra = fmt.Sprintf("/ready/%d", time.Now().UnixNano()/1e6) + } } return fmt.Sprintf("%s/%s/%d%s@%s", issue.Repo.FullName(), path, issue.Index, extra, setting.Domain) diff --git a/services/mailer/mail_test.go b/services/mailer/mail_test.go index 07690063cd29..6c800e457b0c 100644 --- a/services/mailer/mail_test.go +++ b/services/mailer/mail_test.go @@ -6,7 +6,9 @@ package mailer import ( "bytes" + "fmt" "html/template" + "strings" "testing" texttmpl "text/template" @@ -15,7 +17,6 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" - "github.com/stretchr/testify/assert" ) @@ -250,3 +251,115 @@ func TestGenerateAdditionalHeaders(t *testing.T) { } } } + +func Test_createReference(t *testing.T) { + _, _, issue, comment := prepareMailerTest(t) + _, _, pullIssue, _ := prepareMailerTest(t) + pullIssue.IsPull = true + + type args struct { + issue *models.Issue + comment *models.Comment + actionType models.ActionType + } + tests := []struct { + name string + args args + prefix string + suffix string + }{ + { + name: "Open Issue", + args: args{ + issue: issue, + actionType: models.ActionCreateIssue, + }, + prefix: fmt.Sprintf("%s/issues/%d@%s", issue.Repo.FullName(), issue.Index, setting.Domain), + }, + { + name: "Open Pull", + args: args{ + issue: pullIssue, + actionType: models.ActionCreatePullRequest, + }, + prefix: fmt.Sprintf("%s/pulls/%d@%s", issue.Repo.FullName(), issue.Index, setting.Domain), + }, + { + name: "Comment Issue", + args: args{ + issue: issue, + comment: comment, + actionType: models.ActionCommentIssue, + }, + prefix: fmt.Sprintf("%s/issues/%d/comment/%d@%s", issue.Repo.FullName(), issue.Index, comment.ID, setting.Domain), + }, + { + name: "Comment Pull", + args: args{ + issue: pullIssue, + comment: comment, + actionType: models.ActionCommentPull, + }, + prefix: fmt.Sprintf("%s/pulls/%d/comment/%d@%s", issue.Repo.FullName(), issue.Index, comment.ID, setting.Domain), + }, + { + name: "Close Issue", + args: args{ + issue: issue, + actionType: models.ActionCloseIssue, + }, + prefix: fmt.Sprintf("%s/issues/%d/close/", issue.Repo.FullName(), issue.Index), + }, + { + name: "Close Pull", + args: args{ + issue: pullIssue, + actionType: models.ActionClosePullRequest, + }, + prefix: fmt.Sprintf("%s/pulls/%d/close/", issue.Repo.FullName(), issue.Index), + }, + { + name: "Reopen Issue", + args: args{ + issue: issue, + actionType: models.ActionReopenIssue, + }, + prefix: fmt.Sprintf("%s/issues/%d/reopen/", issue.Repo.FullName(), issue.Index), + }, + { + name: "Reopen Pull", + args: args{ + issue: pullIssue, + actionType: models.ActionReopenPullRequest, + }, + prefix: fmt.Sprintf("%s/pulls/%d/reopen/", issue.Repo.FullName(), issue.Index), + }, + { + name: "Merge Pull", + args: args{ + issue: pullIssue, + actionType: models.ActionMergePullRequest, + }, + prefix: fmt.Sprintf("%s/pulls/%d/merge/", issue.Repo.FullName(), issue.Index), + }, + { + name: "Ready Pull", + args: args{ + issue: pullIssue, + actionType: models.ActionPullRequestReadyForReview, + }, + prefix: fmt.Sprintf("%s/pulls/%d/ready/", issue.Repo.FullName(), issue.Index), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := createReference(tt.args.issue, tt.args.comment, tt.args.actionType) + if !strings.HasPrefix(got, tt.prefix) { + t.Errorf("createReference() = %v, want %v", got, tt.prefix) + } + if !strings.HasSuffix(got, tt.suffix) { + t.Errorf("createReference() = %v, want %v", got, tt.prefix) + } + }) + } +} diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 9edb6258d82d..da085c0d8db0 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -12,7 +12,6 @@ import ( "os" "path/filepath" "strings" - "sync" "time" "code.gitea.io/gitea/models" @@ -42,9 +41,9 @@ type GiteaLocalUploader struct { repoOwner string repoName string repo *repo_model.Repository - labels sync.Map - milestones sync.Map - issues sync.Map + labels map[string]*models.Label + milestones map[string]int64 + issues map[int64]*models.Issue gitRepo *git.Repository prHeadCache map[string]struct{} userMap map[int64]int64 // external user id mapping to user id @@ -59,6 +58,9 @@ func NewGiteaLocalUploader(ctx context.Context, doer *user_model.User, repoOwner doer: doer, repoOwner: repoOwner, repoName: repoName, + labels: make(map[string]*models.Label), + milestones: make(map[string]int64), + issues: make(map[int64]*models.Issue), prHeadCache: make(map[string]struct{}), userMap: make(map[int64]int64), prCache: make(map[int64]*models.PullRequest), @@ -201,7 +203,7 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err } for _, ms := range mss { - g.milestones.Store(ms.Name, ms.ID) + g.milestones[ms.Name] = ms.ID } return nil } @@ -223,7 +225,7 @@ func (g *GiteaLocalUploader) CreateLabels(labels ...*base.Label) error { return err } for _, lb := range lbs { - g.labels.Store(lb.Name, lb) + g.labels[lb.Name] = lb } return nil } @@ -333,19 +335,13 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error { for _, issue := range issues { var labels []*models.Label for _, label := range issue.Labels { - lb, ok := g.labels.Load(label.Name) + lb, ok := g.labels[label.Name] if ok { - labels = append(labels, lb.(*models.Label)) + labels = append(labels, lb) } } - var milestoneID int64 - if issue.Milestone != "" { - milestone, ok := g.milestones.Load(issue.Milestone) - if ok { - milestoneID = milestone.(int64) - } - } + milestoneID := g.milestones[issue.Milestone] if issue.Created.IsZero() { if issue.Closed != nil { @@ -404,7 +400,7 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error { } for _, is := range iss { - g.issues.Store(is.Index, is) + g.issues[is.Index] = is } } @@ -416,16 +412,14 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error { cms := make([]*models.Comment, 0, len(comments)) for _, comment := range comments { var issue *models.Issue - issueInter, ok := g.issues.Load(comment.IssueIndex) + issue, ok := g.issues[comment.IssueIndex] if !ok { var err error issue, err = models.GetIssueByIndex(g.repo.ID, comment.IssueIndex) if err != nil { return err } - g.issues.Store(comment.IssueIndex, issue) - } else { - issue = issueInter.(*models.Issue) + g.issues[comment.IssueIndex] = issue } if comment.Created.IsZero() { @@ -487,7 +481,7 @@ func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error return err } for _, pr := range gprs { - g.issues.Store(pr.Issue.Index, pr.Issue) + g.issues[pr.Issue.Index] = pr.Issue pull.AddToTaskQueue(pr) } return nil @@ -496,19 +490,13 @@ func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullRequest, error) { var labels []*models.Label for _, label := range pr.Labels { - lb, ok := g.labels.Load(label.Name) + lb, ok := g.labels[label.Name] if ok { - labels = append(labels, lb.(*models.Label)) + labels = append(labels, lb) } } - var milestoneID int64 - if pr.Milestone != "" { - milestone, ok := g.milestones.Load(pr.Milestone) - if ok { - milestoneID = milestone.(int64) - } - } + milestoneID := g.milestones[pr.Milestone] // download patch file err := func() error { @@ -700,18 +688,15 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { cms := make([]*models.Review, 0, len(reviews)) for _, review := range reviews { var issue *models.Issue - issueInter, ok := g.issues.Load(review.IssueIndex) + issue, ok := g.issues[review.IssueIndex] if !ok { var err error issue, err = models.GetIssueByIndex(g.repo.ID, review.IssueIndex) if err != nil { return err } - g.issues.Store(review.IssueIndex, issue) - } else { - issue = issueInter.(*models.Issue) + g.issues[review.IssueIndex] = issue } - if review.CreatedAt.IsZero() { review.CreatedAt = time.Unix(int64(issue.CreatedUnix), 0) } diff --git a/templates/repo/issue/labels/label_load_template.tmpl b/templates/repo/issue/labels/label_load_template.tmpl index 037069c29bee..e75a7bef5f01 100644 --- a/templates/repo/issue/labels/label_load_template.tmpl +++ b/templates/repo/issue/labels/label_load_template.tmpl @@ -1,12 +1,6 @@
-

{{.i18n.Tr "repo.issues.label_templates.info"}}


@@ -20,6 +14,7 @@
{{$template}}
({{$labels}})
{{end}}
+ {{svg "octicon-triangle-down" 18 "dropdown icon"}}
diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 76ca5dff7da4..6cf70abdf772 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -4,6 +4,13 @@ // otherwise some part of the popup will be hidden by viewport boundary max-height: 45vh; max-width: 60vw; + + &.ui.right { + // Override `.ui.attached.header .right:not(.dropdown) height: 30px;` which would otherwise lead to + // the status popup box having its height fixed at 30px. See https://github.com/go-gitea/gitea/issues/18498 + height: auto; + } + overflow: auto; padding: 0;