diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 24a0aa1907a6c..0d2f955319509 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -310,7 +310,7 @@ rules: jquery/no-merge: [2] jquery/no-param: [2] jquery/no-parent: [0] - jquery/no-parents: [0] + jquery/no-parents: [2] jquery/no-parse-html: [2] jquery/no-prop: [2] jquery/no-proxy: [2] @@ -319,8 +319,8 @@ rules: jquery/no-show: [2] jquery/no-size: [2] jquery/no-sizzle: [2] - jquery/no-slide: [0] - jquery/no-submit: [0] + jquery/no-slide: [2] + jquery/no-submit: [2] jquery/no-text: [2] jquery/no-toggle: [2] jquery/no-trigger: [0] @@ -458,7 +458,7 @@ rules: no-jquery/no-other-utils: [2] no-jquery/no-param: [2] no-jquery/no-parent: [0] - no-jquery/no-parents: [0] + no-jquery/no-parents: [2] no-jquery/no-parse-html-literal: [0] no-jquery/no-parse-html: [2] no-jquery/no-parse-json: [2] diff --git a/.golangci.yml b/.golangci.yml index 27fee20f75ae6..238f6cb837e65 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,13 +1,14 @@ linters: + enable-all: false + disable-all: true + fast: false enable: - bidichk - # - deadcode # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - depguard - dupl - errcheck - forbidigo - gocritic - # - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time. - gofmt - gofumpt - gosimple @@ -17,20 +18,18 @@ linters: - nolintlint - revive - staticcheck - # - structcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - stylecheck - typecheck - unconvert - unused - # - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - wastedassign - enable-all: false - disable-all: true - fast: false run: timeout: 10m +output: + sort-results: true + linters-settings: stylecheck: checks: ["all", "-ST1005", "-ST1003"] @@ -47,27 +46,37 @@ linters-settings: errorCode: 1 warningCode: 1 rules: + - name: atomic + - name: bare-return - name: blank-imports + - name: constant-logical-expr - name: context-as-argument - name: context-keys-type - name: dot-imports + - name: duplicated-imports + - name: empty-lines + - name: error-naming - name: error-return - name: error-strings - - name: error-naming + - name: errorf - name: exported + - name: identical-branches - name: if-return - name: increment-decrement - - name: var-naming - - name: var-declaration + - name: indent-error-flow + - name: modifies-value-receiver - name: package-comments - name: range - name: receiver-naming + - name: redefines-builtin-id + - name: string-of-int + - name: superfluous-else - name: time-naming + - name: unconditional-recursion - name: unexported-return - - name: indent-error-flow - - name: errorf - - name: duplicated-imports - - name: modifies-value-receiver + - name: unreachable-code + - name: var-declaration + - name: var-naming gofumpt: extra-rules: true depguard: @@ -93,8 +102,8 @@ issues: max-issues-per-linter: 0 max-same-issues: 0 exclude-dirs: [node_modules, public, web_src] + exclude-case-sensitive: true exclude-rules: - # Exclude some linters from running on tests files. - path: _test\.go linters: - gocyclo @@ -112,19 +121,19 @@ issues: - path: cmd linters: - forbidigo - - linters: + - text: "webhook" + linters: - dupl - text: "webhook" - - linters: + - text: "`ID' should not be capitalized" + linters: - gocritic - text: "`ID' should not be capitalized" - - linters: + - text: "swagger" + linters: - unused - deadcode - text: "swagger" - - linters: + - text: "argument x is overwritten before first use" + linters: - staticcheck - text: "argument x is overwritten before first use" - text: "commentFormatting: put a space between `//` and comment text" linters: - gocritic diff --git a/cmd/dump.go b/cmd/dump.go index da0a51d9ce934..ececc80f72507 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -87,6 +87,10 @@ var CmdDump = &cli.Command{ Name: "skip-index", Usage: "Skip bleve index data", }, + &cli.BoolFlag{ + Name: "skip-db", + Usage: "Skip database", + }, &cli.StringFlag{ Name: "type", Usage: fmt.Sprintf(`Dump output format, default to "zip", supported types: %s`, strings.Join(dump.SupportedOutputTypes, ", ")), @@ -185,35 +189,41 @@ func runDump(ctx *cli.Context) error { } } - tmpDir := ctx.String("tempdir") - if _, err := os.Stat(tmpDir); os.IsNotExist(err) { - fatal("Path does not exist: %s", tmpDir) - } + if ctx.Bool("skip-db") { + // Ensure that we don't dump the database file that may reside in setting.AppDataPath or elsewhere. + dumper.GlobalExcludeAbsPath(setting.Database.Path) + log.Info("Skipping database") + } else { + tmpDir := ctx.String("tempdir") + if _, err := os.Stat(tmpDir); os.IsNotExist(err) { + fatal("Path does not exist: %s", tmpDir) + } - dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql") - if err != nil { - fatal("Failed to create tmp file: %v", err) - } - defer func() { - _ = dbDump.Close() - if err := util.Remove(dbDump.Name()); err != nil { - log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err) + dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql") + if err != nil { + fatal("Failed to create tmp file: %v", err) } - }() + defer func() { + _ = dbDump.Close() + if err := util.Remove(dbDump.Name()); err != nil { + log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err) + } + }() - targetDBType := ctx.String("database") - if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() { - log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType) - } else { - log.Info("Dumping database...") - } + targetDBType := ctx.String("database") + if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() { + log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType) + } else { + log.Info("Dumping database...") + } - if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil { - fatal("Failed to dump database: %v", err) - } + if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil { + fatal("Failed to dump database: %v", err) + } - if err = dumper.AddFile("gitea-db.sql", dbDump.Name()); err != nil { - fatal("Failed to include gitea-db.sql: %v", err) + if err = dumper.AddFile("gitea-db.sql", dbDump.Name()); err != nil { + fatal("Failed to include gitea-db.sql: %v", err) + } } log.Info("Adding custom configuration file from %s", setting.CustomConf) diff --git a/cmd/hook.go b/cmd/hook.go index c04591d79ec28..2a9c25add5237 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -465,7 +465,7 @@ func hookPrintResult(output, isCreate bool, branch, url string) { fmt.Fprintf(os.Stderr, " %s\n", url) } fmt.Fprintln(os.Stderr, "") - os.Stderr.Sync() + _ = os.Stderr.Sync() } func pushOptions() map[string]string { diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index b4e330184edcd..12588c1387206 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1231,7 +1231,8 @@ LEVEL = Info ;DEFAULT_THEME = gitea-auto ;; ;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`. -;THEMES = gitea-auto,gitea-light,gitea-dark +;; Leave it empty to allow users to select any theme from "{CustomPath}/public/assets/css/theme-*.css" +;THEMES = ;; ;; All available reactions users can choose on issues/prs and comments. ;; Values can be emoji alias (:smile:) or a unicode emoji. diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 9328177f5024f..b295ddf53a7a4 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -214,10 +214,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `SITEMAP_PAGING_NUM`: **20**: Number of items that are displayed in a single subsitemap. - `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph. - `CODE_COMMENT_LINES`: **4**: Number of line of codes shown for a code comment. -- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: Set the default theme for the Gitea installation. +- `DEFAULT_THEME`: **gitea-auto**: Set the default theme for the Gitea installation, custom themes could be provided by "{CustomPath}/public/assets/css/theme-*.css". - `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page. -- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes. - regardless of the value of `DEFAULT_THEME`. +- `THEMES`: **_empty_**: All available themes by "{CustomPath}/public/assets/css/theme-*.css". Allow users select personalized themes. - `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB) - `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI - `REACTIONS`: All available reactions users can choose on issues/prs and comments diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index e4945dd1c1dd9..0d08a5e51ba63 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -212,10 +212,9 @@ menu: - `SITEMAP_PAGING_NUM`: **20**: 在单个子SiteMap中显示的项数。 - `GRAPH_MAX_COMMIT_NUM`: **100**: 提交图中显示的最大commit数量。 - `CODE_COMMENT_LINES`: **4**: 在代码评论中能够显示的最大代码行数。 -- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: 在Gitea安装时候设置的默认主题。 +- `DEFAULT_THEME`: **gitea-auto**: 在Gitea安装时候设置的默认主题,自定义的主题可以通过 "{CustomPath}/public/assets/css/theme-*.css" 提供。 - `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。 -- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: 所有可用的主题。允许用户选择个性化的主题, - 而不受DEFAULT_THEME 值的影响。 +- `THEMES`: **_empty_**: 所有可用的主题(由 "{CustomPath}/public/assets/css/theme-*.css" 提供)。允许用户选择个性化的主题, - `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小(默认为8MiB)。 - `REACTIONS`: 用户可以在问题(Issue)、Pull Request(PR)以及评论中选择的所有可选的反应。 这些值可以是表情符号别名(例如::smile:)或Unicode表情符号。 diff --git a/docs/content/administration/customizing-gitea.en-us.md b/docs/content/administration/customizing-gitea.en-us.md index 7efddb2824e1d..8475f6d131430 100644 --- a/docs/content/administration/customizing-gitea.en-us.md +++ b/docs/content/administration/customizing-gitea.en-us.md @@ -381,7 +381,7 @@ To make a custom theme available to all users: 1. Add a CSS file to `$GITEA_CUSTOM/public/assets/css/theme-.css`. The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath". -2. Add `` to the comma-separated list of setting `THEMES` in `app.ini` +2. Add `` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes. Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes). diff --git a/docs/content/help/faq.en-us.md b/docs/content/help/faq.en-us.md index b3b09801256d9..ba39ec83b073b 100644 --- a/docs/content/help/faq.en-us.md +++ b/docs/content/help/faq.en-us.md @@ -178,17 +178,6 @@ At some point, a customer or third party needs access to a specific repo and onl Use [Fail2Ban](administration/fail2ban-setup.md) to monitor and stop automated login attempts or other malicious behavior based on log patterns -## How to add/use custom themes - -Gitea supports three official themes right now, `gitea-light`, `gitea-dark`, and `gitea-auto` (automatically switches between the previous two depending on operating system settings). -To add your own theme, currently the only way is to provide a complete theme (not just color overrides) - -As an example, let's say our theme is `arc-blue` (this is a real theme, and can be found [in this issue](https://github.com/go-gitea/gitea/issues/6011)) - -Name the `.css` file `theme-arc-blue.css` and add it to your custom folder in `custom/public/assets/css` - -Allow users to use it by adding `arc-blue` to the list of `THEMES` in your `app.ini` - ## SSHD vs built-in SSH SSHD is the built-in SSH server on most Unix systems. diff --git a/docs/content/help/faq.zh-cn.md b/docs/content/help/faq.zh-cn.md index 25230df70b224..ef8a149ae24d1 100644 --- a/docs/content/help/faq.zh-cn.md +++ b/docs/content/help/faq.zh-cn.md @@ -182,17 +182,6 @@ Gitea不提供内置的Pages服务器。您需要一个专用的域名来提供 使用 [Fail2Ban](administration/fail2ban-setup.md) 监视并阻止基于日志模式的自动登录尝试或其他恶意行为。 -## 如何添加/使用自定义主题 - -Gitea 目前支持三个官方主题,分别是 `gitea-light`、`gitea-dark` 和 `gitea-auto`(根据操作系统设置自动切换前两个主题)。 -要添加自己的主题,目前唯一的方法是提供一个完整的主题(不仅仅是颜色覆盖)。 - -假设我们的主题是 `arc-blue`(这是一个真实的主题,可以在[此问题](https://github.com/go-gitea/gitea/issues/6011)中找到) - -将`.css`文件命名为`theme-arc-blue.css`并将其添加到`custom/public/assets/css`文件夹中 - -通过将`arc-blue`添加到`app.ini`中的`THEMES`列表中,允许用户使用该主题 - ## SSHD vs 内建SSH SSHD是大多数Unix系统上内建的SSH服务器。 diff --git a/models/actions/run.go b/models/actions/run.go index fa9db0b554754..b75fa49f3c93e 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -98,13 +98,10 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error { return nil } - if run.Repo == nil { - repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) - if err != nil { - return err - } - run.Repo = repo + if err := run.LoadRepo(ctx); err != nil { + return err } + if err := run.Repo.LoadAttributes(ctx); err != nil { return err } @@ -120,6 +117,19 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error { return nil } +func (run *ActionRun) LoadRepo(ctx context.Context) error { + if run == nil || run.Repo != nil { + return nil + } + + repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) + if err != nil { + return err + } + run.Repo = repo + return nil +} + func (run *ActionRun) Duration() time.Duration { return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration } diff --git a/models/actions/runner.go b/models/actions/runner.go index 67f003387b112..9192925d5a455 100644 --- a/models/actions/runner.go +++ b/models/actions/runner.go @@ -270,7 +270,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { // Only affect action runners were a owner ID is set, as actions runners // could also be created on a repository. return db.GetEngine(ctx).Table("action_runner"). - Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). + Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id"). Where("`action_runner`.owner_id != ?", 0). And(builder.IsNull{"`user`.id"}). Count(new(ActionRunner)) @@ -279,7 +279,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { subQuery := builder.Select("`action_runner`.id"). From("`action_runner`"). - Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). + Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id"). Where(builder.Neq{"`action_runner`.owner_id": 0}). And(builder.IsNull{"`user`.id"}) b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`") @@ -289,3 +289,25 @@ func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { } return res.RowsAffected() } + +func CountRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Table("action_runner"). + Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id"). + Where("`action_runner`.repo_id != ?", 0). + And(builder.IsNull{"`repository`.id"}). + Count(new(ActionRunner)) +} + +func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) { + subQuery := builder.Select("`action_runner`.id"). + From("`action_runner`"). + Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id"). + Where(builder.Neq{"`action_runner`.repo_id": 0}). + And(builder.IsNull{"`repository`.id"}) + b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`") + res, err := db.GetEngine(ctx).Exec(b) + if err != nil { + return 0, err + } + return res.RowsAffected() +} diff --git a/models/actions/variable.go b/models/actions/variable.go index b0a455e675756..8aff84465901d 100644 --- a/models/actions/variable.go +++ b/models/actions/variable.go @@ -92,6 +92,11 @@ func DeleteVariable(ctx context.Context, id int64) error { func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) { variables := map[string]string{} + if err := run.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return nil, err + } + // Global globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{}) if err != nil { diff --git a/models/asymkey/gpg_key_commit_verification.go b/models/asymkey/gpg_key_commit_verification.go index 06ac31bc6f325..26fad3bb3f211 100644 --- a/models/asymkey/gpg_key_commit_verification.go +++ b/models/asymkey/gpg_key_commit_verification.go @@ -110,7 +110,6 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific Reason: "gpg.error.no_committer_account", } } - } } diff --git a/models/auth/oauth2_test.go b/models/auth/oauth2_test.go index 122d43098cc3a..0829d31d51baf 100644 --- a/models/auth/oauth2_test.go +++ b/models/auth/oauth2_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" ) -//////////////////// Application - func TestOAuth2Application_GenerateClientSecret(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) diff --git a/models/db/engine.go b/models/db/engine.go index 26abf0b96c21e..25f4066ea1380 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -227,7 +227,6 @@ func NamesToBean(names ...string) ([]any, error) { // Need to map provided names to beans... beanMap := make(map[string]any) for _, bean := range tables { - beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean beanMap[strings.ToLower(x.TableName(bean))] = bean beanMap[strings.ToLower(x.TableName(bean, true))] = bean diff --git a/models/issues/review.go b/models/issues/review.go index 92764db4d150a..3c6934b060afc 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -345,11 +345,9 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error return nil, err } } - } else if opts.ReviewerTeam != nil { review.Type = ReviewTypeRequest review.ReviewerTeamID = opts.ReviewerTeam.ID - } else { return nil, fmt.Errorf("provide either reviewer or reviewer team") } diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go index 51351cc7d3297..eb1c44a79e6f5 100644 --- a/models/migrations/base/db.go +++ b/models/migrations/base/db.go @@ -177,7 +177,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) return err } - case setting.Database.Type.IsMySQL(): // MySQL will drop all the constraints on the old table if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { @@ -228,7 +227,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { return err } sequenceMap[sequence] = sequenceData - } // CASCADE causes postgres to drop all the constraints on the old table @@ -293,9 +291,7 @@ func RecreateTable(sess *xorm.Session, bean any) error { return err } } - } - case setting.Database.Type.IsMSSQL(): // MSSQL will drop all the constraints on the old table if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { @@ -308,7 +304,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) return err } - default: log.Fatal("Unrecognized DB") } diff --git a/models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/o_auth2_application.yml b/models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml similarity index 100% rename from models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/o_auth2_application.yml rename to models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index cb3a64f48c633..220d8c2331447 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -584,6 +584,8 @@ var migrations = []Migration{ NewMigration("Add missing field of commit status summary table", v1_23.AddCommitStatusSummary2), // v297 -> v298 NewMigration("Add everyone_access_mode for repo_unit", v1_23.AddRepoUnitEveryoneAccessMode), + // v298 -> v299 + NewMigration("Drop wrongly created table o_auth2_application", v1_23.DropWronglyCreatedTable), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_11/v111.go b/models/migrations/v1_11/v111.go index 1722792a38f82..ff108479a9d4b 100644 --- a/models/migrations/v1_11/v111.go +++ b/models/migrations/v1_11/v111.go @@ -262,7 +262,6 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { for _, u := range units { var found bool for _, team := range teams { - var teamU []*TeamUnit var unitEnabled bool err = sess.Where("team_id = ?", team.ID).Find(&teamU) @@ -331,7 +330,6 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { } if !protectedBranch.EnableApprovalsWhitelist { - perm, err := getUserRepoPermission(sess, baseRepo, reviewer) if err != nil { return false, err diff --git a/models/migrations/v1_18/v230.go b/models/migrations/v1_18/v230.go index cf94926be17ca..ea5b4d02e1f26 100644 --- a/models/migrations/v1_18/v230.go +++ b/models/migrations/v1_18/v230.go @@ -9,9 +9,9 @@ import ( // AddConfidentialColumnToOAuth2ApplicationTable: add ConfidentialClient column, setting existing rows to true func AddConfidentialClientColumnToOAuth2ApplicationTable(x *xorm.Engine) error { - type OAuth2Application struct { + type oauth2Application struct { + ID int64 ConfidentialClient bool `xorm:"NOT NULL DEFAULT TRUE"` } - - return x.Sync(new(OAuth2Application)) + return x.Sync(new(oauth2Application)) } diff --git a/models/migrations/v1_18/v230_test.go b/models/migrations/v1_18/v230_test.go index 308f3a50231f6..40db4c2ffe20b 100644 --- a/models/migrations/v1_18/v230_test.go +++ b/models/migrations/v1_18/v230_test.go @@ -13,12 +13,12 @@ import ( func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { // premigration - type OAuth2Application struct { + type oauth2Application struct { ID int64 } // Prepare and load the testing database - x, deferable := base.PrepareTestEnv(t, 0, new(OAuth2Application)) + x, deferable := base.PrepareTestEnv(t, 0, new(oauth2Application)) defer deferable() if x == nil || t.Failed() { return @@ -36,7 +36,7 @@ func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { } got := []ExpectedOAuth2Application{} - if err := x.Table("o_auth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) { + if err := x.Table("oauth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) { return } diff --git a/models/migrations/v1_20/v250.go b/models/migrations/v1_20/v250.go index a09957b2917d9..86388ef0b8019 100644 --- a/models/migrations/v1_20/v250.go +++ b/models/migrations/v1_20/v250.go @@ -104,7 +104,7 @@ func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { // Convert to new metadata format - new := &MetadataNew{ + newMetadata := &MetadataNew{ Type: old.Type, IsTagged: old.IsTagged, Platform: old.Platform, @@ -119,7 +119,7 @@ func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { Manifests: manifests, } - metadataJSON, err := json.Marshal(new) + metadataJSON, err := json.Marshal(newMetadata) if err != nil { return err } diff --git a/models/migrations/v1_23/v298.go b/models/migrations/v1_23/v298.go new file mode 100644 index 0000000000000..8761a05d3dc1c --- /dev/null +++ b/models/migrations/v1_23/v298.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import "xorm.io/xorm" + +func DropWronglyCreatedTable(x *xorm.Engine) error { + return x.DropTables("o_auth2_application") +} diff --git a/models/migrations/v1_6/v71.go b/models/migrations/v1_6/v71.go index 4e50ca9219bba..586187228b305 100644 --- a/models/migrations/v1_6/v71.go +++ b/models/migrations/v1_6/v71.go @@ -61,7 +61,6 @@ func AddScratchHash(x *xorm.Engine) error { if _, err := sess.ID(tfa.ID).Cols("scratch_salt, scratch_hash").Update(tfa); err != nil { return fmt.Errorf("couldn't add in scratch_hash and scratch_salt: %w", err) } - } } diff --git a/models/migrations/v1_9/v85.go b/models/migrations/v1_9/v85.go index 9419ee1aae1db..a23d7c5d6efe1 100644 --- a/models/migrations/v1_9/v85.go +++ b/models/migrations/v1_9/v85.go @@ -81,7 +81,6 @@ func HashAppToken(x *xorm.Engine) error { if _, err := sess.ID(token.ID).Cols("token_hash, token_salt, token_last_eight, sha1").Update(token); err != nil { return fmt.Errorf("couldn't add in sha1, token_hash, token_salt and token_last_eight: %w", err) } - } } diff --git a/models/organization/team.go b/models/organization/team.go index e4e83fedeeba1..fb7f0c04939e6 100644 --- a/models/organization/team.go +++ b/models/organization/team.go @@ -226,9 +226,8 @@ func GetTeamIDsByNames(ctx context.Context, orgID int64, names []string, ignoreN if err != nil { if ignoreNonExistent { continue - } else { - return nil, err } + return nil, err } ids = append(ids, u.ID) } diff --git a/models/project/board.go b/models/project/board.go index 5f142a356c68d..7faabc52c58bf 100644 --- a/models/project/board.go +++ b/models/project/board.go @@ -110,13 +110,11 @@ func createBoardsForProjectsType(ctx context.Context, project *Project) error { var items []string switch project.BoardType { - case BoardTypeBugTriage: items = setting.Project.ProjectBoardBugTriageType case BoardTypeBasicKanban: items = setting.Project.ProjectBoardBasicKanbanType - case BoardTypeNone: fallthrough default: diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index 686224765785d..1c5412fe7da18 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -170,7 +170,6 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) // the owner of a private repo needs to be explicitly added. cond = cond.Or(builder.Eq{"`user`.id": repo.Owner.ID}) } - } else { // This is a "public" repository: // Any user that has read access, is a watcher or organization member can be requested to review diff --git a/models/user/user.go b/models/user/user.go index d459ec239e978..7056aecab0681 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -988,9 +988,8 @@ func GetUserIDsByNames(ctx context.Context, names []string, ignoreNonExistent bo if err != nil { if ignoreNonExistent { continue - } else { - return nil, err } + return nil, err } ids = append(ids, u.ID) } diff --git a/modules/auth/password/password.go b/modules/auth/password/password.go index 27074358a91c7..85f9780709c1f 100644 --- a/modules/auth/password/password.go +++ b/modules/auth/password/password.go @@ -63,16 +63,16 @@ func NewComplexity() { func setupComplexity(values []string) { if len(values) != 1 || values[0] != "off" { for _, val := range values { - if complex, ok := charComplexities[val]; ok { - validChars += complex.ValidChars - requiredList = append(requiredList, complex) + if complexity, ok := charComplexities[val]; ok { + validChars += complexity.ValidChars + requiredList = append(requiredList, complexity) } } if len(requiredList) == 0 { // No valid character classes found; use all classes as default - for _, complex := range charComplexities { - validChars += complex.ValidChars - requiredList = append(requiredList, complex) + for _, complexity := range charComplexities { + validChars += complexity.ValidChars + requiredList = append(requiredList, complexity) } } } diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go index 043dbb44bdb4f..c988d6ab86ed4 100644 --- a/modules/git/batch_reader.go +++ b/modules/git/batch_reader.go @@ -307,10 +307,10 @@ func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBu // Deal with the binary hash idx = 0 - len := objectFormat.FullLength() / 2 - for idx < len { + length := objectFormat.FullLength() / 2 + for idx < length { var read int - read, err = rd.Read(shaBuf[idx:len]) + read, err = rd.Read(shaBuf[idx:length]) n += read if err != nil { return mode, fname, sha, n, err diff --git a/modules/git/commit_reader.go b/modules/git/commit_reader.go index f1f4a0e588dec..228bbaf314d4d 100644 --- a/modules/git/commit_reader.go +++ b/modules/git/commit_reader.go @@ -49,9 +49,8 @@ readLoop: if len(line) > 0 && line[0] == ' ' { _, _ = signatureSB.Write(line[1:]) continue - } else { - pgpsig = false } + pgpsig = false } if !message { diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go index 4c6524908948e..fe320f39f3fcb 100644 --- a/modules/git/pipeline/lfs_nogogit.go +++ b/modules/git/pipeline/lfs_nogogit.go @@ -232,7 +232,6 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err errChan <- err break } - } }() diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 44273d2253ce8..f9168bef7eec1 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -251,18 +251,18 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) return nil, err } - len := objectFormat.FullLength() + length := objectFormat.FullLength() commits := []*Commit{} - shaline := make([]byte, len+1) + shaline := make([]byte, length+1) for { n, err := io.ReadFull(stdoutReader, shaline) - if err != nil || n < len { + if err != nil || n < length { if err == io.EOF { err = nil } return commits, err } - objectID, err := NewIDFromString(string(shaline[0:len])) + objectID, err := NewIDFromString(string(shaline[0:length])) if err != nil { return nil, err } diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 37813ea4c7ca5..b99c81582b70e 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -64,7 +64,6 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string { // ex: git@try.gitea.io:go-gitea/gitea match := scpSyntax.FindAllStringSubmatch(refURI, -1) if len(match) > 0 { - m := match[0] refHostname := m[2] pth := m[3] diff --git a/modules/indexer/code/bleve/bleve.go b/modules/indexer/code/bleve/bleve.go index c607d780ef968..bd844205a6e80 100644 --- a/modules/indexer/code/bleve/bleve.go +++ b/modules/indexer/code/bleve/bleve.go @@ -191,7 +191,6 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository, batch func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error { batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize) if len(changes.Updates) > 0 { - // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first! if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil { log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err) @@ -335,7 +334,6 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int if result, err = b.inner.Indexer.Search(facetRequest); err != nil { return 0, nil, nil, err } - } languagesFacet := result.Facets["languages"] for _, term := range languagesFacet.Terms.Terms() { diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go index 4a98b4588a3da..8f94088742291 100644 --- a/modules/indexer/issues/dboptions.go +++ b/modules/indexer/issues/dboptions.go @@ -68,7 +68,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp searchOpt.Paginator = opts.Paginator switch opts.SortType { - case "": + case "", "latest": searchOpt.SortBy = SortByCreatedDesc case "oldest": searchOpt.SortBy = SortByCreatedAsc @@ -86,7 +86,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp searchOpt.SortBy = SortByDeadlineDesc case "priority", "priorityrepo", "project-column-sorting": // Unsupported sort type for search - searchOpt.SortBy = SortByUpdatedDesc + fallthrough default: searchOpt.SortBy = SortByUpdatedDesc } diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go index 53b383c8d5d78..c7cb59f2cf009 100644 --- a/modules/indexer/issues/elasticsearch/elasticsearch.go +++ b/modules/indexer/issues/elasticsearch/elasticsearch.go @@ -145,7 +145,6 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( query := elastic.NewBoolQuery() if options.Keyword != "" { - searchType := esMultiMatchTypePhrasePrefix if options.IsFuzzyKeyword { searchType = esMultiMatchTypeBestFields diff --git a/modules/log/event_format.go b/modules/log/event_format.go index 524ca3dd872ed..d9dbebf831531 100644 --- a/modules/log/event_format.go +++ b/modules/log/event_format.go @@ -125,7 +125,6 @@ func EventFormatTextMessage(mode *WriterMode, event *Event, msgFormat string, ms if mode.Colorize { buf = append(buf, resetBytes...) } - } if flags&(Lshortfile|Llongfile) != 0 { if mode.Colorize { diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index d9b67e43af013..bc6ad7fb3c737 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -466,7 +466,6 @@ func TestColorPreview(t *testing.T) { res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) - } negativeTests := []string{ @@ -549,7 +548,6 @@ func TestMathBlock(t *testing.T) { res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) - } } diff --git a/modules/packages/rubygems/marshal.go b/modules/packages/rubygems/marshal.go index 8878dcf9732f5..4e6a5fc5f8baf 100644 --- a/modules/packages/rubygems/marshal.go +++ b/modules/packages/rubygems/marshal.go @@ -147,35 +147,35 @@ func (e *MarshalEncoder) marshalIntInternal(i int64) error { return e.w.WriteByte(byte(i - 5)) } - var len int + var length int if 122 < i && i <= 0xff { - len = 1 + length = 1 } else if 0xff < i && i <= 0xffff { - len = 2 + length = 2 } else if 0xffff < i && i <= 0xffffff { - len = 3 + length = 3 } else if 0xffffff < i && i <= 0x3fffffff { - len = 4 + length = 4 } else if -0x100 <= i && i < -123 { - len = -1 + length = -1 } else if -0x10000 <= i && i < -0x100 { - len = -2 + length = -2 } else if -0x1000000 <= i && i < -0x100000 { - len = -3 + length = -3 } else if -0x40000000 <= i && i < -0x1000000 { - len = -4 + length = -4 } else { return ErrInvalidIntRange } - if err := e.w.WriteByte(byte(len)); err != nil { + if err := e.w.WriteByte(byte(length)); err != nil { return err } - if len < 0 { - len = -len + if length < 0 { + length = -length } - for c := 0; c < len; c++ { + for c := 0; c < length; c++ { if err := e.w.WriteByte(byte(i >> uint(8*c) & 0xff)); err != nil { return err } @@ -244,13 +244,13 @@ func (e *MarshalEncoder) marshalArray(arr reflect.Value) error { return err } - len := arr.Len() + length := arr.Len() - if err := e.marshalIntInternal(int64(len)); err != nil { + if err := e.marshalIntInternal(int64(length)); err != nil { return err } - for i := 0; i < len; i++ { + for i := 0; i < length; i++ { if err := e.marshal(arr.Index(i).Interface()); err != nil { return err } diff --git a/modules/process/manager_stacktraces.go b/modules/process/manager_stacktraces.go index 49bd5071f698e..e260893113118 100644 --- a/modules/process/manager_stacktraces.go +++ b/modules/process/manager_stacktraces.go @@ -339,7 +339,6 @@ func (pm *Manager) ProcessStacktraces(flat, noSystem bool) ([]*Process, int, int } sort.Slice(processes, after(processes)) if !flat { - var sortChildren func(process *Process) sortChildren = func(process *Process) { diff --git a/modules/queue/workergroup.go b/modules/queue/workergroup.go index e3801ef2b2dd0..153123f883c73 100644 --- a/modules/queue/workergroup.go +++ b/modules/queue/workergroup.go @@ -63,6 +63,8 @@ func (q *WorkerPoolQueue[T]) doDispatchBatchToWorker(wg *workerGroup[T], flushCh // TODO: the logic could be improved in the future, to avoid a data-race between "doStartNewWorker" and "workerNum" // The root problem is that if we skip "doStartNewWorker" here, the "workerNum" might be decreased by other workers later // So ideally, it should check whether there are enough workers by some approaches, and start new workers if necessary. + // This data-race is not serious, as long as a new worker will be started soon to make sure there are enough workers, + // so no need to hugely refactor at the moment. q.workerNumMu.Lock() noWorker := q.workerNum == 0 if full || noWorker { @@ -136,6 +138,14 @@ func (q *WorkerPoolQueue[T]) basePushForShutdown(items ...T) bool { return true } +func resetIdleTicker(t *time.Ticker, dur time.Duration) { + t.Reset(dur) + select { + case <-t.C: + default: + } +} + // doStartNewWorker starts a new worker for the queue, the worker reads from worker's channel and handles the items. func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { wp.wg.Add(1) @@ -146,8 +156,6 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { log.Debug("Queue %q starts new worker", q.GetName()) defer log.Debug("Queue %q stops idle worker", q.GetName()) - atomic.AddInt32(&q.workerStartedCounter, 1) // Only increase counter, used for debugging - t := time.NewTicker(workerIdleDuration) defer t.Stop() @@ -169,11 +177,7 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { } q.doWorkerHandle(batch) // reset the idle ticker, and drain the tick after reset in case a tick is already triggered - t.Reset(workerIdleDuration) - select { - case <-t.C: - default: - } + resetIdleTicker(t, workerIdleDuration) // key code for TestWorkerPoolQueueWorkerIdleReset case <-t.C: q.workerNumMu.Lock() keepWorking = q.workerNum <= 1 // keep the last worker running diff --git a/modules/queue/workerqueue.go b/modules/queue/workerqueue.go index 4160622d81388..b28fd880270ab 100644 --- a/modules/queue/workerqueue.go +++ b/modules/queue/workerqueue.go @@ -40,8 +40,6 @@ type WorkerPoolQueue[T any] struct { workerMaxNum int workerActiveNum int workerNumMu sync.Mutex - - workerStartedCounter int32 } type flushType chan struct{} diff --git a/modules/queue/workerqueue_test.go b/modules/queue/workerqueue_test.go index a08b02a123bc9..d66253ff66409 100644 --- a/modules/queue/workerqueue_test.go +++ b/modules/queue/workerqueue_test.go @@ -5,8 +5,10 @@ package queue import ( "context" + "slices" "strconv" "sync" + "sync/atomic" "testing" "time" @@ -250,23 +252,34 @@ func TestWorkerPoolQueueShutdown(t *testing.T) { func TestWorkerPoolQueueWorkerIdleReset(t *testing.T) { defer test.MockVariableValue(&workerIdleDuration, 10*time.Millisecond)() - defer mockBackoffDuration(10 * time.Millisecond)() + defer mockBackoffDuration(5 * time.Millisecond)() + var q *WorkerPoolQueue[int] + var handledCount atomic.Int32 + var hasOnlyOneWorkerRunning atomic.Bool handler := func(items ...int) (unhandled []int) { - time.Sleep(50 * time.Millisecond) + handledCount.Add(int32(len(items))) + // make each work have different duration, and check the active worker number periodically + var activeNums []int + for i := 0; i < 5-items[0]%2; i++ { + time.Sleep(workerIdleDuration * 2) + activeNums = append(activeNums, q.GetWorkerActiveNumber()) + } + // When the queue never becomes empty, the existing workers should keep working + // It is not 100% true at the moment because the data-race in workergroup.go is not resolved, see that TODO */ + // If the "active worker numbers" is like [2 2 ... 1 1], it means that an existing worker exited and the no new worker is started. + if slices.Equal([]int{1, 1}, activeNums[len(activeNums)-2:]) { + hasOnlyOneWorkerRunning.Store(true) + } return nil } - - q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false) + q, _ = newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false) stop := runWorkerPoolQueue(q) - for i := 0; i < 20; i++ { + for i := 0; i < 100; i++ { assert.NoError(t, q.Push(i)) } - time.Sleep(500 * time.Millisecond) - assert.EqualValues(t, 2, q.GetWorkerNumber()) - assert.EqualValues(t, 2, q.GetWorkerActiveNumber()) - // when the queue never becomes empty, the existing workers should keep working - assert.EqualValues(t, 2, q.workerStartedCounter) + assert.Greater(t, int(handledCount.Load()), 4) // make sure there are enough items handled during the test + assert.False(t, hasOnlyOneWorkerRunning.Load(), "a slow handler should not block other workers from starting") stop() } diff --git a/modules/repository/temp.go b/modules/repository/temp.go index 53646718e09b2..04faa9db3de8e 100644 --- a/modules/repository/temp.go +++ b/modules/repository/temp.go @@ -32,7 +32,6 @@ func CreateTemporaryPath(prefix string) (string, error) { if err != nil { log.Error("Unable to create temporary directory: %s-*.git (%v)", prefix, err) return "", fmt.Errorf("Failed to create dir %s-*.git: %w", prefix, err) - } return basePath, nil } diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go index 03f27ba203f29..3138f8a63eeda 100644 --- a/modules/setting/config_provider.go +++ b/modules/setting/config_provider.go @@ -318,7 +318,7 @@ func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting any) { // StartupProblems contains the messages for various startup problems, including: setting option, file/folder, etc var StartupProblems []string -func logStartupProblem(skip int, level log.Level, format string, args ...any) { +func LogStartupProblem(skip int, level log.Level, format string, args ...any) { msg := fmt.Sprintf(format, args...) log.Log(skip+1, level, "%s", msg) StartupProblems = append(StartupProblems, msg) @@ -326,14 +326,14 @@ func logStartupProblem(skip int, level log.Level, format string, args ...any) { func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) { if rootCfg.Section(oldSection).HasKey(oldKey) { - logStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) + LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) } } // deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini func deprecatedSettingDB(rootCfg ConfigProvider, oldSection, oldKey string) { if rootCfg.Section(oldSection).HasKey(oldKey) { - logStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey) + LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey) } } diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go index 6930197b22a7e..34e1a336dc615 100644 --- a/modules/setting/oauth2.go +++ b/modules/setting/oauth2.go @@ -174,7 +174,7 @@ func GetGeneralTokenSigningSecret() []byte { } if generalSigningSecret.CompareAndSwap(old, &jwtSecret) { // FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...) - logStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes") + LogStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes") return jwtSecret } return *generalSigningSecret.Load() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 92bb0b6541b65..f056fbfc6c29a 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -235,7 +235,7 @@ var configuredPaths = make(map[string]string) func checkOverlappedPath(name, path string) { // TODO: some paths shouldn't overlap (storage.xxx.path), while some could (data path is the base path for storage path) if targetName, ok := configuredPaths[path]; ok && targetName != name { - logStartupProblem(1, log.ERROR, "Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name) + LogStartupProblem(1, log.ERROR, "Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name) } configuredPaths[path] = name } diff --git a/modules/setting/time.go b/modules/setting/time.go index 6d2aa80f5bdb9..39acba12ef14e 100644 --- a/modules/setting/time.go +++ b/modules/setting/time.go @@ -19,9 +19,8 @@ func loadTimeFrom(rootCfg ConfigProvider) { DefaultUILocation, err = time.LoadLocation(zone) if err != nil { log.Fatal("Load time zone failed: %v", err) - } else { - log.Info("Default UI Location is %v", zone) } + log.Info("Default UI Location is %v", zone) } if DefaultUILocation == nil { DefaultUILocation = time.Local diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 2f9eef93c3bc9..93855bca07b2f 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -82,7 +82,6 @@ var UI = struct { ReactionMaxUserNum: 10, MaxDisplayFileSize: 8388608, DefaultTheme: `gitea-auto`, - Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`}, Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`}, CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"}, diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 360b48c59416a..94464fe628b98 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" + "code.gitea.io/gitea/services/webtheme" ) // NewFuncMap returns functions for injecting to templates @@ -137,12 +138,7 @@ func NewFuncMap() template.FuncMap { "DisableImportLocal": func() bool { return !setting.ImportLocalPaths }, - "ThemeName": func(user *user_model.User) string { - if user == nil || user.Theme == "" { - return setting.UI.DefaultTheme - } - return user.Theme - }, + "UserThemeName": UserThemeName, "NotificationSettings": func() map[string]any { return map[string]any{ "MinTimeout": int(setting.UI.Notification.MinTimeout / time.Millisecond), @@ -261,3 +257,13 @@ func Eval(tokens ...any) (any, error) { n, err := eval.Expr(tokens...) return n.Value, err } + +func UserThemeName(user *user_model.User) string { + if user == nil || user.Theme == "" { + return setting.UI.DefaultTheme + } + if webtheme.IsThemeAvailable(user.Theme) { + return user.Theme + } + return setting.UI.DefaultTheme +} diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 40941285aad56..e7e805ed3023d 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -138,10 +138,9 @@ func wrapTmplErrMsg(msg string) { if setting.IsProd { // in prod mode, Gitea must have correct templates to run log.Fatal("Gitea can't run with template errors: %s", msg) - } else { - // in dev mode, do not need to really exit, because the template errors could be fixed by developer soon and the templates get reloaded - log.Error("There are template errors but Gitea continues to run in dev mode: %s", msg) } + // in dev mode, do not need to really exit, because the template errors could be fixed by developer soon and the templates get reloaded + log.Error("There are template errors but Gitea continues to run in dev mode: %s", msg) } type templateErrorPrettier struct { diff --git a/modules/templates/mailer.go b/modules/templates/mailer.go index f1832cba0e957..7c97e1ea89d9f 100644 --- a/modules/templates/mailer.go +++ b/modules/templates/mailer.go @@ -84,9 +84,8 @@ func Mailer(ctx context.Context) (*texttmpl.Template, *template.Template) { if err = buildSubjectBodyTemplate(subjectTemplates, bodyTemplates, tmplName, content); err != nil { if firstRun { log.Fatal("Failed to parse mail template, err: %v", err) - } else { - log.Error("Failed to parse mail template, err: %v", err) } + log.Error("Failed to parse mail template, err: %v", err) } } } diff --git a/modules/util/util_test.go b/modules/util/util_test.go index 5c5b13d04b4fc..de8f065cadc73 100644 --- a/modules/util/util_test.go +++ b/modules/util/util_test.go @@ -121,9 +121,9 @@ func Test_NormalizeEOL(t *testing.T) { } func Test_RandomInt(t *testing.T) { - int, err := CryptoRandomInt(255) - assert.True(t, int >= 0) - assert.True(t, int <= 255) + randInt, err := CryptoRandomInt(255) + assert.True(t, randInt >= 0) + assert.True(t, randInt <= 255) assert.NoError(t, err) } diff --git a/options/license/HPND-UC-export-US b/options/license/HPND-UC-export-US new file mode 100644 index 0000000000000..015556c5f97bd --- /dev/null +++ b/options/license/HPND-UC-export-US @@ -0,0 +1,10 @@ +Copyright (C) 1985, 1990 Regents of the University of California. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies. The University of California +makes no representations about the suitability of this +software for any purpose. It is provided "as is" without +express or implied warranty. Export of this software outside +of the United States of America may require an export license. diff --git a/options/license/NCL b/options/license/NCL new file mode 100644 index 0000000000000..3bfb658c267d6 --- /dev/null +++ b/options/license/NCL @@ -0,0 +1,32 @@ +Copyright (c) 2004 the University Corporation for Atmospheric +Research ("UCAR"). All rights reserved. Developed by NCAR's +Computational and Information Systems Laboratory, UCAR, +www.cisl.ucar.edu. + +Redistribution and use of the Software in source and binary forms, +with or without modification, is permitted provided that the +following conditions are met: + +- Neither the names of NCAR's Computational and Information Systems +Laboratory, the University Corporation for Atmospheric Research, +nor the names of its sponsors or contributors may be used to +endorse or promote products derived from this Software without +specific prior written permission. + +- Redistributions of source code must retain the above copyright +notices, this list of conditions, and the disclaimer below. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions, and the disclaimer below in the +documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 57c44e4b26c67..82d7867168346 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -1186,7 +1186,6 @@ action.blocked_user=Nelze provést akci, protože jste zablokování vlastníkem download_archive=Stáhnout repozitář more_operations=Další operace -no_desc=Bez popisu quick_guide=Krátká příručka clone_this_repo=Naklonovat tento repozitář cite_this_repo=Citovat tento repozitář diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index f591b755772ca..dd2b34a6f412f 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -1187,7 +1187,6 @@ action.blocked_user=Die Aktion kann nicht ausgeführt werden, da du vom Reposito download_archive=Repository herunterladen more_operations=Weitere Operationen -no_desc=Keine Beschreibung quick_guide=Kurzanleitung clone_this_repo=Dieses Repository klonen cite_this_repo=Dieses Repository zitieren diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 64db2348da389..9553ba2f3ae4e 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -1118,7 +1118,6 @@ fork=Fork download_archive=Λήψη Αποθετηρίου more_operations=Περισσότερες Λειτουργίες -no_desc=Χωρίς Περιγραφή quick_guide=Γρήγορος Οδηγός clone_this_repo=Κλωνοποίηση αυτού του αποθετηρίου cite_this_repo=Αναφορά σε αυτό το αποθετήριο diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index c602aba53dc5f..4f17b1a6db3ae 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -763,6 +763,8 @@ manage_themes = Select default theme manage_openid = Manage OpenID Addresses email_desc = Your primary email address will be used for notifications, password recovery and, provided that it is not hidden, web-based Git operations. theme_desc = This will be your default theme across the site. +theme_colorblindness_help = Colorblindness Theme Support +theme_colorblindness_prompt = Gitea just gets some themes with basic colorblindness support, which only have a few colors defined. The work is still in progress. More improvements could be done by defining more colors in the theme CSS files. primary = Primary activated = Activated requires_activation = Requires activation @@ -1193,7 +1195,6 @@ action.blocked_user = Cannot perform action because you are blocked by the repos download_archive = Download Repository more_operations = More Operations -no_desc = No Description quick_guide = Quick Guide clone_this_repo = Clone this repository cite_this_repo = Cite this repository diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index d1d680c14c59e..f3e2d93e8039a 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -1111,7 +1111,6 @@ fork=Fork download_archive=Descargar repositorio more_operations=Más operaciones -no_desc=Sin descripción quick_guide=Guía rápida clone_this_repo=Clonar este repositorio cite_this_repo=Citar este repositorio diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 54a4911e5cc99..25a3361b3f41e 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -874,7 +874,6 @@ star=ستاره دار کن fork=انشعاب download_archive=دانلود مخزن -no_desc=بدون توضیح quick_guide=راهنمای سریع clone_this_repo=همسان‌سازی این مخزن create_new_repo_command=ایجاد یک مخزن جدید در خط فرمان diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index ace676281f17e..f29ad8c6cdbf1 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -718,7 +718,6 @@ unstar=Poista tähti star=Tähti download_archive=Lataa repo -no_desc=Ei kuvausta quick_guide=Pikaopas clone_this_repo=Kloonaa tämä repo diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 61a6a98379e1e..b90039c003bb3 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -1130,7 +1130,6 @@ fork=Bifurcation download_archive=Télécharger ce dépôt more_operations=Plus d'opérations -no_desc=Aucune description quick_guide=Introduction rapide clone_this_repo=Cloner ce dépôt cite_this_repo=Citer ce dépôt diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini index bddd6dd582f5b..4e46227fea4f3 100644 --- a/options/locale/locale_hu-HU.ini +++ b/options/locale/locale_hu-HU.ini @@ -656,7 +656,6 @@ star=Csillagozás fork=Tükrözés download_archive=Tároló letöltése -no_desc=Nincs leírás quick_guide=Gyors útmutató clone_this_repo=Tároló klónozása create_new_repo_command=Egy új tároló létrehozása a parancssorból diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 92610778310fc..fe3a6d0b08ec4 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -570,7 +570,6 @@ star=Bintang fork=Garpu download_archive=Unduh Repositori -no_desc=Tidak ada Deskripsi quick_guide=Panduan Cepat clone_this_repo=Klon repositori ini create_new_repo_command=Membuat repositori baru pada baris perintah diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini index a1116eddbc0d9..f2fcfb7eda1ce 100644 --- a/options/locale/locale_is-IS.ini +++ b/options/locale/locale_is-IS.ini @@ -647,7 +647,6 @@ star=Bæta við eftirlæti fork=Tvískipta download_archive=Hlaða Miður Geymslu -no_desc=Engin Lýsing quick_guide=Stuttar Leiðbeiningar clone_this_repo=Afrita þetta hugbúnaðarsafn create_new_repo_command=Að búa til nýja geymslu með skipanalínu diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index b15a78ccf4ca6..eceda0faade29 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -936,7 +936,6 @@ star=Vota fork=Forka download_archive=Scarica Repository -no_desc=Nessuna descrizione quick_guide=Guida rapida clone_this_repo=Clona questo repository create_new_repo_command=Creazione di un nuovo repository da riga di comando diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 707b37170a317..e33a1ae173324 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -1188,7 +1188,6 @@ action.blocked_user=リポジトリのオーナーがあなたをブロックし download_archive=リポジトリをダウンロード more_operations=その他の操作 -no_desc=説明なし quick_guide=クイック ガイド clone_this_repo=このリポジトリのクローンを作成 cite_this_repo=このリポジトリを引用 diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index 3e9679575cf27..cf3188e9c0f86 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -606,7 +606,6 @@ star=좋아요 fork=포크 download_archive=저장소 다운로드 -no_desc=설명 없음 quick_guide=퀵 가이드 clone_this_repo=이 저장소 복제 create_new_repo_command=커맨드 라인에서 새 레포리지터리 생성 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 6afb488414d6d..3aed4bd6c515a 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -1119,7 +1119,6 @@ fork=Atdalīts download_archive=Lejupielādēt repozitoriju more_operations=Vairāk darbību -no_desc=Nav apraksta quick_guide=Īsa pamācība clone_this_repo=Klonēt šo repozitoriju cite_this_repo=Citēt šo repozitoriju diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index b0b081db5d5eb..f511bc5d23e37 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -934,7 +934,6 @@ star=Ster fork=Vork download_archive=Download repository -no_desc=Geen omschrijving quick_guide=Snelstart gids clone_this_repo=Kloon deze repository create_new_repo_command=Maak een nieuwe repository aan vanaf de console diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index fd5db4109fe67..b5a758514ea92 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -877,7 +877,6 @@ star=Polub fork=Forkuj download_archive=Pobierz repozytorium -no_desc=Brak opisu quick_guide=Skrócona instrukcja clone_this_repo=Klonuj repozytorium create_new_repo_command=Tworzenie nowego repozytorium z linii poleceń diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 5a058c807b0f9..2e23cde801e33 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1115,7 +1115,6 @@ fork=Fork download_archive=Baixar repositório more_operations=Mais Operações -no_desc=Nenhuma descrição quick_guide=Guia Rápido clone_this_repo=Clonar este repositório cite_this_repo=Citar este repositório diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index a90927a25557e..64798d6d65260 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -1193,7 +1193,6 @@ action.blocked_user=Não pode realizar a operação porque foi bloqueado/a pelo/ download_archive=Descarregar repositório more_operations=Mais operações -no_desc=Sem descrição quick_guide=Guia rápido clone_this_repo=Clonar este repositório cite_this_repo=Citar este repositório diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index d4098aa952030..df6df4cf9500f 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -1098,7 +1098,6 @@ fork=Форкнуть download_archive=Скачать репозиторий more_operations=Ещё действия -no_desc=Нет описания quick_guide=Краткое руководство clone_this_repo=Клонировать репозиторий cite_this_repo=Сослаться на этот репозиторий diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini index 05538af971b72..15bbcfebb2a3b 100644 --- a/options/locale/locale_si-LK.ini +++ b/options/locale/locale_si-LK.ini @@ -846,7 +846,6 @@ star=ස්ටාර් fork=දෙබලක download_archive=කෝෂ්ඨය බාගන්න -no_desc=සවිස්තරයක් නැත quick_guide=ඉක්මන් මාර්ගෝපදේශය clone_this_repo=මෙම ගබඩාව පරිගණක ක්රිඩාවට සමාන create_new_repo_command=විධාන රේඛාවේ නව ගබඩාවක් නිර්මාණය කිරීම diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini index b468b55283083..be1efa22bc9aa 100644 --- a/options/locale/locale_sk-SK.ini +++ b/options/locale/locale_sk-SK.ini @@ -964,7 +964,6 @@ star=Hviezdička download_archive=Stiahnuť repozitár more_operations=Viac operácií -no_desc=Bez popisu quick_guide=Rýchly sprievodca clone_this_repo=Klonovať tento repozitár create_new_repo_command=Vytvoriť nový repozitár v príkazovom riadku diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 5fe6288ad668f..b975636cb8ce9 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -718,7 +718,6 @@ star=Stjärnmärk fork=Förgrening download_archive=Ladda Ned Utvecklingskatalogen -no_desc=Ingen beskrivning quick_guide=Snabbguide clone_this_repo=Klona detta repo create_new_repo_command=Skapa en ny utvecklingskatalog på kommandoraden diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index 59c931afd2ca9..be89113f0d676 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -1193,7 +1193,6 @@ action.blocked_user=İşlem gerçekleştirilemiyor, depo sahibi tarafından enge download_archive=Depoyu İndir more_operations=Daha Fazla İşlem -no_desc=Açıklama Yok quick_guide=Hızlı Başlangıç Kılavuzu clone_this_repo=Bu depoyu klonla cite_this_repo=Bu depoya atıf ver diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 613f39b3c9fc6..3e38973e02537 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -882,7 +882,6 @@ star=В обрані fork=Форк download_archive=Скачати репозиторій -no_desc=Без опису quick_guide=Короткий посібник clone_this_repo=Кнонувати цей репозиторій create_new_repo_command=Створити новий репозиторій з командного рядка diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index aeba11fb9a811..a76ecafd6287c 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1193,7 +1193,6 @@ action.blocked_user=无法执行操作,因为您已被仓库所有者屏蔽。 download_archive=下载此仓库 more_operations=更多操作 -no_desc=暂无描述 quick_guide=快速帮助 clone_this_repo=克隆当前仓库 cite_this_repo=引用此仓库 diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini index 2dbdeb2bae832..fb16b82fc5bcf 100644 --- a/options/locale/locale_zh-HK.ini +++ b/options/locale/locale_zh-HK.ini @@ -344,7 +344,6 @@ unstar=取消收藏 star=收藏 fork=複製 -no_desc=暫無描述 quick_guide=快速幫助 clone_this_repo=複製當前儲存庫 create_new_repo_command=從命令列建立新儲存庫。 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 3e7bd4ae2075b..782342699078f 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -1016,7 +1016,6 @@ fork=Fork download_archive=下載此儲存庫 more_operations=更多操作 -no_desc=暫無描述 quick_guide=快速幫助 clone_this_repo=Clone 此儲存庫 cite_this_repo=引用此儲存庫 diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index d530e9cee5693..8198abb8a0d2d 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -144,7 +144,6 @@ func ArtifactContexter() func(next http.Handler) http.Handler { var task *actions.ActionTask if err == nil { - task, err = actions.GetTaskByID(req.Context(), tID) if err != nil { log.Error("Error runner api getting task by ID: %v", err) diff --git a/routers/api/packages/alpine/alpine.go b/routers/api/packages/alpine/alpine.go index dae9c3dfcb2c8..51273198074c7 100644 --- a/routers/api/packages/alpine/alpine.go +++ b/routers/api/packages/alpine/alpine.go @@ -96,12 +96,12 @@ func UploadPackageFile(ctx *context.Context) { return } - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go index c45e085a4d9f0..07ea3eda34139 100644 --- a/routers/api/packages/conan/conan.go +++ b/routers/api/packages/conan/conan.go @@ -310,12 +310,12 @@ func uploadFile(ctx *context.Context, fileFilter container.Set[string], fileKey return } - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusBadRequest, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/conda/conda.go b/routers/api/packages/conda/conda.go index 30c80fc15e057..c7e4544d52d34 100644 --- a/routers/api/packages/conda/conda.go +++ b/routers/api/packages/conda/conda.go @@ -174,12 +174,12 @@ func EnumeratePackages(ctx *context.Context) { } func UploadPackageFile(ctx *context.Context) { - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go index e5197661423b3..2cb16daebc578 100644 --- a/routers/api/packages/container/container.go +++ b/routers/api/packages/container/container.go @@ -385,9 +385,9 @@ func EndUploadBlob(ctx *context.Context) { } return } - close := true + doClose := true defer func() { - if close { + if doClose { uploader.Close() } }() @@ -427,7 +427,7 @@ func EndUploadBlob(ctx *context.Context) { apiError(ctx, http.StatusInternalServerError, err) return } - close = false + doClose = false if err := container_service.RemoveBlobUploadByID(ctx, uploader.ID); err != nil { apiError(ctx, http.StatusInternalServerError, err) diff --git a/routers/api/packages/cran/cran.go b/routers/api/packages/cran/cran.go index 2cec75294fec2..f1d616724ac22 100644 --- a/routers/api/packages/cran/cran.go +++ b/routers/api/packages/cran/cran.go @@ -151,12 +151,12 @@ func UploadBinaryPackageFile(ctx *context.Context) { } func uploadPackageFile(ctx *context.Context, compositeKey string, properties map[string]string) { - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusBadRequest, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/debian/debian.go b/routers/api/packages/debian/debian.go index 241de3ac5d915..8c05476cbc3ea 100644 --- a/routers/api/packages/debian/debian.go +++ b/routers/api/packages/debian/debian.go @@ -127,12 +127,12 @@ func UploadPackageFile(ctx *context.Context) { return } - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/generic/generic.go b/routers/api/packages/generic/generic.go index 82329311340a1..e66f3ee676c41 100644 --- a/routers/api/packages/generic/generic.go +++ b/routers/api/packages/generic/generic.go @@ -90,12 +90,12 @@ func UploadPackage(ctx *context.Context) { return } - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/goproxy/goproxy.go b/routers/api/packages/goproxy/goproxy.go index d658066bb4371..56a07dbd43ec8 100644 --- a/routers/api/packages/goproxy/goproxy.go +++ b/routers/api/packages/goproxy/goproxy.go @@ -154,12 +154,12 @@ func resolvePackage(ctx *context.Context, ownerID int64, name, version string) ( } func UploadPackage(ctx *context.Context) { - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index 09156ece6b9a9..26b0ae226e45b 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -594,13 +594,13 @@ func UploadSymbolPackage(ctx *context.Context) { func processUploadedFile(ctx *context.Context, expectedType nuget_module.PackageType) (*nuget_module.Package, *packages_module.HashedBuffer, []io.Closer) { closables := make([]io.Closer, 0, 2) - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusBadRequest, err) return nil, nil, closables } - if close { + if needToClose { closables = append(closables, upload) } diff --git a/routers/api/packages/rpm/rpm.go b/routers/api/packages/rpm/rpm.go index 4de361c214227..c59366992c365 100644 --- a/routers/api/packages/rpm/rpm.go +++ b/routers/api/packages/rpm/rpm.go @@ -117,12 +117,12 @@ func GetRepositoryFile(ctx *context.Context) { } func UploadPackageFile(ctx *context.Context) { - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go index d2fbcd01f06bf..ba5f4de0807dd 100644 --- a/routers/api/packages/rubygems/rubygems.go +++ b/routers/api/packages/rubygems/rubygems.go @@ -197,12 +197,12 @@ func DownloadPackageFile(ctx *context.Context) { // UploadPackageFile adds a file to the package. If the package does not exist, it gets created. func UploadPackageFile(ctx *context.Context) { - upload, close, err := ctx.UploadStream() + upload, needToClose, err := ctx.UploadStream() if err != nil { apiError(ctx, http.StatusBadRequest, err) return } - if close { + if needToClose { defer upload.Close() } diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go index 549b9b7fa91e8..cfd61d768c507 100644 --- a/routers/api/v1/repo/compare.go +++ b/routers/api/v1/repo/compare.go @@ -16,7 +16,7 @@ import ( // CompareDiff compare two branches or commits func CompareDiff(ctx *context.APIContext) { - // swagger:operation GET /repos/{owner}/{repo}/compare/{basehead} Get commit comparison information + // swagger:operation GET /repos/{owner}/{repo}/compare/{basehead} repository repoCompareDiff // --- // summary: Get commit comparison information // produces: diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 5e173abf88311..dfe6d31f74ec0 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -217,7 +217,6 @@ func SearchIssues(ctx *context.APIContext) { var includedAnyLabels []int64 { - labels := ctx.FormTrim("labels") var includedLabelNames []string if len(labels) > 0 { diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go index 864644e1efc83..2a896de4fe0e4 100644 --- a/routers/api/v1/repo/mirror.go +++ b/routers/api/v1/repo/mirror.go @@ -180,7 +180,6 @@ func ListPushMirrors(ctx *context.APIContext) { if err == nil { responsePushMirrors = append(responsePushMirrors, m) } - } ctx.SetLinkHeader(len(responsePushMirrors), utils.GetListOptions(ctx).PageSize) ctx.SetTotalCountHeader(count) diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index e43366ff14bd4..4129f94ac3c72 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -1061,7 +1061,6 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) isSameRepo = true headUser = ctx.Repo.Owner headBranch = headInfos[0] - } else if len(headInfos) == 2 { headUser, err = user_model.GetUserByName(ctx, headInfos[0]) if err != nil { @@ -1075,18 +1074,16 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) headBranch = headInfos[1] // The head repository can also point to the same repo isSameRepo = ctx.Repo.Owner.ID == headUser.ID - } else { ctx.NotFound() return nil, nil, nil, nil, "", "" } ctx.Repo.PullRequest.SameRepo = isSameRepo - log.Info("Base branch: %s", baseBranch) - log.Info("Repo path: %s", ctx.Repo.GitRepo.Path) + log.Trace("Repo path: %q, base branch: %q, head branch: %q", ctx.Repo.GitRepo.Path, baseBranch, headBranch) // Check if base branch is valid. - if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) { - ctx.NotFound("IsBranchExist") + if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) && !ctx.Repo.GitRepo.IsTagExist(baseBranch) { + ctx.NotFound("BaseNotExist") return nil, nil, nil, nil, "", "" } @@ -1149,7 +1146,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) } // Check if head branch is valid. - if !headGitRepo.IsBranchExist(headBranch) { + if !headGitRepo.IsBranchExist(headBranch) && !headGitRepo.IsTagExist(headBranch) { headGitRepo.Close() ctx.NotFound() return nil, nil, nil, nil, "", "" diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 17bb2085b65e4..b527e90f10b8c 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -728,7 +728,6 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions } if ctx.Repo.Repository.Owner.IsOrganization() && len(opts.TeamReviewers) > 0 { - teamReviewers := make([]*organization.Team, 0, len(opts.TeamReviewers)) for _, t := range opts.TeamReviewers { var teamReviewer *organization.Team diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 2ac0b7ebd1562..7f35a7fe4176b 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -1084,7 +1084,6 @@ func updateMirror(ctx *context.APIContext, opts api.EditRepoOption) error { // update MirrorInterval if opts.MirrorInterval != nil { - // MirrorInterval should be a duration interval, err := time.ParseDuration(*opts.MirrorInterval) if err != nil { diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index f18ea087c4d75..c7065c1d9df93 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -478,7 +478,6 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) { wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { - if git.IsErrNotExist(err) || err.Error() == "no such file or directory" { ctx.NotFound(err) } else { diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 4e59237ed3ec6..caab6b4c810f3 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -198,7 +198,6 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r UserMsg: fmt.Sprintf("branch %s is protected from force push", branchName), }) return - } } diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 41989589bebcc..db2b11a7ed4ab 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -644,7 +644,6 @@ func ArtifactsDownloadView(ctx *context_module.Context) { writer := zip.NewWriter(ctx.Resp) defer writer.Close() for _, art := range artifacts { - f, err := storage.ActionsArtifacts.Open(art.StoragePath) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 1364d7567661d..95f0cf3d71cff 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -933,7 +933,6 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles } } } - } if template.Ref != "" && !strings.HasPrefix(template.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/ @@ -1681,7 +1680,6 @@ func ViewIssue(ctx *context.Context) { if comment.ProjectID > 0 && comment.Project == nil { comment.Project = ghostProject } - } else if comment.Type == issues_model.CommentTypeAssignees || comment.Type == issues_model.CommentTypeReviewRequest { if err = comment.LoadAssigneeUserAndTeam(ctx); err != nil { ctx.ServerError("LoadAssigneeUserAndTeam", err) @@ -2610,7 +2608,6 @@ func SearchIssues(ctx *context.Context) { var includedAnyLabels []int64 { - labels := ctx.FormTrim("labels") var includedLabelNames []string if len(labels) > 0 { @@ -2994,7 +2991,6 @@ func NewComment(ctx *context.Context) { if (ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) || (ctx.IsSigned && issue.IsPoster(ctx.Doer.ID))) && (form.Status == "reopen" || form.Status == "close") && !(issue.IsPull && issue.PullRequest.HasMerged) { - // Duplication and conflict check should apply to reopen pull request. var pr *issues_model.PullRequest diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index a0a8e5410cf15..71f25db11bef1 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -443,7 +443,6 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C } if pb != nil && pb.EnableStatusCheck { - var missingRequiredChecks []string for _, requiredContext := range pb.StatusCheckContexts { contextFound := false @@ -646,7 +645,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi // Validate the given commit sha to show (if any passed) if willShowSpecifiedCommit || willShowSpecifiedCommitRange { - foundStartCommit := len(specifiedStartCommit) == 0 foundEndCommit := len(specifiedEndCommit) == 0 @@ -974,7 +972,6 @@ func UpdatePullRequest(ctx *context.Context) { ctx.Flash.Error(flashError) ctx.Redirect(issue.Link()) return - } ctx.Flash.Error(err.Error()) ctx.Redirect(issue.Link()) diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index c8d149a4829c3..a65d4866d0a48 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -318,7 +318,6 @@ func UpdateViewedFiles(ctx *context.Context) { updatedFiles := make(map[string]pull_model.ViewedState, len(data.Files)) for file, viewed := range data.Files { - // Only unviewed and viewed are possible, has-changed can not be set from the outside state := pull_model.Unviewed if viewed { diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 9c1f4faa5f633..e4e6201c24abd 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -347,7 +347,6 @@ func loadLatestCommitData(ctx *context.Context, latestCommit *git.Commit) bool { // or of directory if not in root directory. ctx.Data["LatestCommit"] = latestCommit if latestCommit != nil { - verification := asymkey_model.ParseCommitWithSignature(ctx, latestCommit) if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) { diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 49eb050dcb63e..e5ff8570cf955 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -31,6 +31,7 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" user_service "code.gitea.io/gitea/services/user" + "code.gitea.io/gitea/services/webtheme" ) const ( @@ -319,6 +320,13 @@ func Appearance(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.appearance") ctx.Data["PageIsSettingsAppearance"] = true + allThemes := webtheme.GetAvailableThemes() + if webtheme.IsThemeAvailable(setting.UI.DefaultTheme) { + allThemes = util.SliceRemoveAll(allThemes, setting.UI.DefaultTheme) + allThemes = append([]string{setting.UI.DefaultTheme}, allThemes...) // move the default theme to the top + } + ctx.Data["AllThemes"] = allThemes + var hiddenCommentTypes *big.Int val, err := user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes) if err != nil { @@ -341,11 +349,12 @@ func UpdateUIThemePost(ctx *context.Context) { ctx.Data["PageIsSettingsAppearance"] = true if ctx.HasError() { + ctx.Flash.Error(ctx.GetErrMsg()) ctx.Redirect(setting.AppSubURL + "/user/settings/appearance") return } - if !form.IsThemeExists() { + if !webtheme.IsThemeAvailable(form.Theme) { ctx.Flash.Error(ctx.Tr("settings.theme_update_error")) ctx.Redirect(setting.AppSubURL + "/user/settings/appearance") return diff --git a/routers/web/web.go b/routers/web/web.go index 994e639e200dd..c6132f0d61b95 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -652,7 +652,7 @@ func registerRoutes(m *web.Route) { m.Get("", user_setting.BlockedUsers) m.Post("", web.Bind(forms.BlockUserForm{}), user_setting.BlockedUsersPost) }) - }, reqSignIn, ctxDataSet("PageIsUserSettings", true, "AllThemes", setting.UI.Themes, "EnablePackages", setting.Packages.Enabled)) + }, reqSignIn, ctxDataSet("PageIsUserSettings", true, "EnablePackages", setting.Packages.Enabled)) m.Group("/user", func() { m.Get("/activate", auth.Activate) diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 6fb6421887e4d..1d09a222c024c 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -298,13 +298,15 @@ func handleWorkflows( TriggerEvent: dwf.TriggerEvent.Name, Status: actions_model.StatusWaiting, } - if need, err := ifNeedApproval(ctx, run, input.Repo, input.Doer); err != nil { + + need, err := ifNeedApproval(ctx, run, input.Repo, input.Doer) + if err != nil { log.Error("check if need approval for repo %d with user %d: %v", input.Repo.ID, input.Doer.ID, err) continue - } else { - run.NeedApproval = need } + run.NeedApproval = need + if err := run.LoadAttributes(ctx); err != nil { log.Error("LoadAttributes: %v", err) continue diff --git a/services/actions/schedule_tasks.go b/services/actions/schedule_tasks.go index e4e56e5122968..18f3324fd2c26 100644 --- a/services/actions/schedule_tasks.go +++ b/services/actions/schedule_tasks.go @@ -132,8 +132,14 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule) Status: actions_model.StatusWaiting, } + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + log.Error("GetVariablesOfRun: %v", err) + return err + } + // Parse the workflow specification from the cron schedule - workflows, err := jobparser.Parse(cron.Content) + workflows, err := jobparser.Parse(cron.Content, jobparser.WithVars(vars)) if err != nil { return err } diff --git a/services/auth/source/ldap/source_sync.go b/services/auth/source/ldap/source_sync.go index 0c9491cd09878..2a95326b9e8d7 100644 --- a/services/auth/source/ldap/source_sync.go +++ b/services/auth/source/ldap/source_sync.go @@ -156,7 +156,6 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error { !strings.EqualFold(usr.Email, su.Mail) || usr.FullName != fullName || !usr.IsActive { - log.Trace("SyncExternalUsers[%s]: Updating user %s", source.authSource.Name, usr.Name) opts := &user_service.UpdateOptions{ diff --git a/services/context/context.go b/services/context/context.go index 1641e995fbb94..88ab5cae0eb22 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -230,6 +230,7 @@ func Contexter() func(next http.Handler) http.Handler { // HasError returns true if error occurs in form validation. // Attention: this function changes ctx.Data and ctx.Flash +// If HasError is called, then before Redirect, the error message should be stored by ctx.Flash.Error(ctx.GetErrMsg()) again. func (ctx *Context) HasError() bool { hasErr, ok := ctx.Data["HasError"] if !ok { diff --git a/services/context/repo.go b/services/context/repo.go index b17f99eb17b4f..4836c1456c8c5 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -825,7 +825,6 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { case RepoRefBranch: ref := getRefNameFromPath(ctx, repo, path, repo.GitRepo.IsBranchExist) if len(ref) == 0 { - // check if ref is HEAD parts := strings.Split(path, "/") if parts[0] == headRefName { @@ -968,7 +967,6 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context return cancel } ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() - } else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) { ctx.Repo.IsViewTag = true ctx.Repo.TagName = refName diff --git a/services/doctor/dbconsistency.go b/services/doctor/dbconsistency.go index dfdf7b547ac0e..7cb7445148a0b 100644 --- a/services/doctor/dbconsistency.go +++ b/services/doctor/dbconsistency.go @@ -152,6 +152,12 @@ func prepareDBConsistencyChecks() []consistencyCheck { Fixer: actions_model.FixRunnersWithoutBelongingOwner, FixedMessage: "Removed", }, + { + Name: "Action Runners without existing repository", + Counter: actions_model.CountRunnersWithoutBelongingRepo, + Fixer: actions_model.FixRunnersWithoutBelongingRepo, + FixedMessage: "Removed", + }, { Name: "Topics with empty repository count", Counter: repo_model.CountOrphanedTopics, diff --git a/services/forms/user_form.go b/services/forms/user_form.go index e2e6c208f7dab..418a87b863d96 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -11,7 +11,6 @@ import ( auth_model "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web/middleware" "code.gitea.io/gitea/services/context" @@ -273,7 +272,7 @@ func (f *AddEmailForm) Validate(req *http.Request, errs binding.Errors) binding. // UpdateThemeForm form for updating a users' theme type UpdateThemeForm struct { - Theme string `binding:"Required;MaxSize(30)"` + Theme string `binding:"Required;MaxSize(255)"` } // Validate validates the field @@ -282,20 +281,6 @@ func (f *UpdateThemeForm) Validate(req *http.Request, errs binding.Errors) bindi return middleware.Validate(errs, ctx.Data, f, ctx.Locale) } -// IsThemeExists checks if the theme is a theme available in the config. -func (f UpdateThemeForm) IsThemeExists() bool { - var exists bool - - for _, v := range setting.UI.Themes { - if strings.EqualFold(v, f.Theme) { - exists = true - break - } - } - - return exists -} - // ChangePasswordForm form for changing password type ChangePasswordForm struct { OldPassword string `form:"old_password" binding:"MaxSize(255)"` diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index b05c210a0cf5c..d115686491a45 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -1044,10 +1044,10 @@ func createDiffFile(diff *Diff, line string) *DiffFile { // diff --git a/b b/b b/b b/b b/b b/b // midpoint := (len(line) + len(cmdDiffHead) - 1) / 2 - new, old := line[len(cmdDiffHead):midpoint], line[midpoint+1:] - if len(new) > 2 && len(old) > 2 && new[2:] == old[2:] { - curFile.OldName = old[2:] - curFile.Name = old[2:] + newPart, oldPart := line[len(cmdDiffHead):midpoint], line[midpoint+1:] + if len(newPart) > 2 && len(oldPart) > 2 && newPart[2:] == oldPart[2:] { + curFile.OldName = oldPart[2:] + curFile.Name = oldPart[2:] } } } @@ -1181,7 +1181,6 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi defer deferable() for _, diffFile := range diff.Files { - isVendored := optional.None[bool]() isGenerated := optional.None[bool]() if checker != nil { diff --git a/services/issue/commit.go b/services/issue/commit.go index 0a59088d127b7..0579e0f5c53e6 100644 --- a/services/issue/commit.go +++ b/services/issue/commit.go @@ -118,7 +118,6 @@ func UpdateIssuesCommit(ctx context.Context, doer *user_model.User, repo *repo_m var refIssue *issues_model.Issue var err error for _, ref := range references.FindAllIssueReferences(c.Message) { - // issue is from another repo if len(ref.Owner) > 0 && len(ref.Name) > 0 { refRepo, err = repo_model.GetRepositoryByOwnerAndName(ctx, ref.Owner, ref.Name) @@ -189,15 +188,15 @@ func UpdateIssuesCommit(ctx context.Context, doer *user_model.User, repo *repo_m continue } } - close := ref.Action == references.XRefActionCloses - if close && len(ref.TimeLog) > 0 { + isClosed := ref.Action == references.XRefActionCloses + if isClosed && len(ref.TimeLog) > 0 { if err := issueAddTime(ctx, refIssue, doer, c.Timestamp, ref.TimeLog); err != nil { return err } } - if close != refIssue.IsClosed { + if isClosed != refIssue.IsClosed { refIssue.Repo = refRepo - if err := ChangeStatus(ctx, refIssue, doer, c.Sha1, close); err != nil { + if err := ChangeStatus(ctx, refIssue, doer, c.Sha1, isClosed); err != nil { return err } } diff --git a/services/markup/processorhelper_codepreview.go b/services/markup/processorhelper_codepreview.go index ef95046128d08..0500e57e4610e 100644 --- a/services/markup/processorhelper_codepreview.go +++ b/services/markup/processorhelper_codepreview.go @@ -86,12 +86,13 @@ func renderRepoFileCodePreview(ctx context.Context, opts markup.RenderCodePrevie lineNums := make([]int, 0, lineCount) lineCodes := make([]string, 0, lineCount) for i := opts.LineStart; i <= opts.LineStop; i++ { - if line, err := reader.ReadString('\n'); err != nil && line == "" { + line, err := reader.ReadString('\n') + if err != nil && line == "" { break - } else { - lineNums = append(lineNums, i) - lineCodes = append(lineCodes, line) } + + lineNums = append(lineNums, i) + lineCodes = append(lineCodes, line) } realLineStop := max(opts.LineStart, opts.LineStart+len(lineNums)-1) highlightLines := code.HighlightSearchResultCode(opts.FilePath, language, lineNums, strings.Join(lineCodes, "")) diff --git a/services/migrations/gitea_downloader.go b/services/migrations/gitea_downloader.go index d402a238f27a3..272bf02e11bae 100644 --- a/services/migrations/gitea_downloader.go +++ b/services/migrations/gitea_downloader.go @@ -410,7 +410,6 @@ func (g *GiteaDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, err return nil, false, fmt.Errorf("error while listing issues: %w", err) } for _, issue := range issues { - labels := make([]*base.Label, 0, len(issue.Labels)) for i := range issue.Labels { labels = append(labels, g.convertGiteaLabel(issue.Labels[i])) diff --git a/services/migrations/gitlab.go b/services/migrations/gitlab.go index bbc44e958ad26..065b687fa6877 100644 --- a/services/migrations/gitlab.go +++ b/services/migrations/gitlab.go @@ -421,7 +421,6 @@ func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, er return nil, false, fmt.Errorf("error while listing issues: %w", err) } for _, issue := range issues { - labels := make([]*base.Label, 0, len(issue.Labels)) for _, l := range issue.Labels { labels = append(labels, &base.Label{ diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index fa23986c54eae..f5eaeaf091de1 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -523,13 +523,13 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { theCommits.Commits = theCommits.Commits[:setting.UI.FeedMaxCommitNum] } - if newCommit, err := gitRepo.GetCommit(newCommitID); err != nil { + newCommit, err := gitRepo.GetCommit(newCommitID) + if err != nil { log.Error("SyncMirrors [repo: %-v]: unable to get commit %s: %v", m.Repo, newCommitID, err) continue - } else { - theCommits.HeadCommit = repo_module.CommitToPushCommit(newCommit) } + theCommits.HeadCommit = repo_module.CommitToPushCommit(newCommit) theCommits.CompareURL = m.Repo.ComposeCompareURL(oldCommitID, newCommitID) notify_service.SyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{ @@ -557,7 +557,6 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Error("SyncMirrors [repo: %-v]: unable to update repository 'updated_unix': %v", m.Repo, err) return false } - } log.Trace("SyncMirrors [repo: %-v]: Successfully updated", m.Repo) diff --git a/services/pull/merge.go b/services/pull/merge.go index e37540a96fcaf..00f23e1e3ae23 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -231,9 +231,9 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U if err = ref.Issue.LoadRepo(ctx); err != nil { return err } - close := ref.RefAction == references.XRefActionCloses - if close != ref.Issue.IsClosed { - if err = issue_service.ChangeStatus(ctx, ref.Issue, doer, pr.MergedCommitID, close); err != nil { + isClosed := ref.RefAction == references.XRefActionCloses + if isClosed != ref.Issue.IsClosed { + if err = issue_service.ChangeStatus(ctx, ref.Issue, doer, pr.MergedCommitID, isClosed); err != nil { // Allow ErrDependenciesLeft if !issues_model.IsErrDependenciesLeft(err) { return err diff --git a/services/pull/pull.go b/services/pull/pull.go index 185a1895c9fb8..764be5c6e39cc 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -807,7 +807,6 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ if err != nil { log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err) return "" - } if len(commits) == 0 { break diff --git a/services/repository/adopt.go b/services/repository/adopt.go index b337eac38ac38..31e3e581b3134 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -357,7 +357,6 @@ func ListUnadoptedRepositories(ctx context.Context, query string, opts *db.ListO return err } repoNamesToCheck = repoNamesToCheck[:0] - } return filepath.SkipDir }); err != nil { diff --git a/services/repository/contributors_graph.go b/services/repository/contributors_graph.go index b0d6de99ca902..b0748f8ee308d 100644 --- a/services/repository/contributors_graph.go +++ b/services/repository/contributors_graph.go @@ -187,7 +187,6 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int Stats: &commitStats, } extendedCommitStats = append(extendedCommitStats, res) - } _ = stdoutReader.Close() return nil diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 9fcd335c55a6a..d70b1e8d54e77 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -136,14 +136,18 @@ func (t *TemporaryUploadRepository) LsFiles(filenames ...string) ([]string, erro // RemoveFilesFromIndex removes the given files from the index func (t *TemporaryUploadRepository) RemoveFilesFromIndex(filenames ...string) error { + objFmt, err := t.gitRepo.GetObjectFormat() + if err != nil { + return fmt.Errorf("unable to get object format for temporary repo: %q, error: %w", t.repo.FullName(), err) + } stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) stdIn := new(bytes.Buffer) for _, file := range filenames { if file != "" { - stdIn.WriteString("0 0000000000000000000000000000000000000000\t") - stdIn.WriteString(file) - stdIn.WriteByte('\000') + // man git-update-index: input syntax (1): mode SP sha1 TAB path + // mode=0 means "remove from index", then hash part "does not matter as long as it is well formatted." + _, _ = fmt.Fprintf(stdIn, "0 %s\t%s\x00", objFmt.EmptyObjectID(), file) } } @@ -154,8 +158,7 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(filenames ...string) er Stdout: stdOut, Stderr: stdErr, }); err != nil { - log.Error("Unable to update-index for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String()) - return fmt.Errorf("Unable to update-index for temporary repo: %s Error: %w\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String()) + return fmt.Errorf("unable to update-index for temporary repo: %q, error: %w\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String()) } return nil } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index f029a9aefe96b..d0e3075eae6ad 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -208,7 +208,6 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use return nil, fmt.Errorf("ConvertToSHA1: Invalid last commit ID: %w", err) } opts.LastCommitID = lastCommitID.String() - } for _, file := range opts.Files { @@ -360,7 +359,6 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep Path: file.Options.treePath, } } - } } diff --git a/services/user/delete.go b/services/user/delete.go index 889da3eb67490..39c6ef052dca7 100644 --- a/services/user/delete.go +++ b/services/user/delete.go @@ -105,7 +105,6 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) if purge || (setting.Service.UserDeleteWithCommentsMaxTime != 0 && u.CreatedUnix.AsTime().Add(setting.Service.UserDeleteWithCommentsMaxTime).After(time.Now())) { - // Delete Comments const batchSize = 50 for { diff --git a/services/user/update_test.go b/services/user/update_test.go index 7ed764b539521..c2ff26a1405f7 100644 --- a/services/user/update_test.go +++ b/services/user/update_test.go @@ -94,7 +94,7 @@ func TestUpdateAuth(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 28}) - copy := *user + userCopy := *user assert.NoError(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ LoginName: optional.Some("new-login"), @@ -106,8 +106,8 @@ func TestUpdateAuth(t *testing.T) { MustChangePassword: optional.Some(true), })) assert.True(t, user.MustChangePassword) - assert.NotEqual(t, copy.Passwd, user.Passwd) - assert.NotEqual(t, copy.Salt, user.Salt) + assert.NotEqual(t, userCopy.Passwd, user.Passwd) + assert.NotEqual(t, userCopy.Salt, user.Salt) assert.NoError(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ ProhibitLogin: optional.Some(true), diff --git a/services/webhook/discord.go b/services/webhook/discord.go index 659754d5e0530..3883ac9eb8782 100644 --- a/services/webhook/discord.go +++ b/services/webhook/discord.go @@ -274,14 +274,12 @@ func newDiscordRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook func parseHookPullRequestEventType(event webhook_module.HookEventType) (string, error) { switch event { - case webhook_module.HookEventPullRequestReviewApproved: return "approved", nil case webhook_module.HookEventPullRequestReviewRejected: return "rejected", nil case webhook_module.HookEventPullRequestReviewComment: return "comment", nil - default: return "", errors.New("unknown event type") } diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go index 0329804a8bdce..5dcfdcb0ddc3c 100644 --- a/services/webhook/matrix.go +++ b/services/webhook/matrix.go @@ -179,7 +179,6 @@ func (m matrixConvertor) Push(p *api.PushPayload) (MatrixPayload, error) { if i < len(p.Commits)-1 { text += "
" } - } return m.newPayload(text, p.Commits...) diff --git a/services/webtheme/webtheme.go b/services/webtheme/webtheme.go new file mode 100644 index 0000000000000..dc801e1ff7ef9 --- /dev/null +++ b/services/webtheme/webtheme.go @@ -0,0 +1,74 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package webtheme + +import ( + "sort" + "strings" + "sync" + + "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/public" + "code.gitea.io/gitea/modules/setting" +) + +var ( + availableThemes []string + availableThemesSet container.Set[string] + themeOnce sync.Once +) + +func initThemes() { + availableThemes = nil + defer func() { + availableThemesSet = container.SetOf(availableThemes...) + if !availableThemesSet.Contains(setting.UI.DefaultTheme) { + setting.LogStartupProblem(1, log.ERROR, "Default theme %q is not available, please correct the '[ui].DEFAULT_THEME' setting in the config file", setting.UI.DefaultTheme) + } + }() + cssFiles, err := public.AssetFS().ListFiles("/assets/css") + if err != nil { + log.Error("Failed to list themes: %v", err) + availableThemes = []string{setting.UI.DefaultTheme} + return + } + var foundThemes []string + for _, name := range cssFiles { + name, ok := strings.CutPrefix(name, "theme-") + if !ok { + continue + } + name, ok = strings.CutSuffix(name, ".css") + if !ok { + continue + } + foundThemes = append(foundThemes, name) + } + if len(setting.UI.Themes) > 0 { + allowedThemes := container.SetOf(setting.UI.Themes...) + for _, theme := range foundThemes { + if allowedThemes.Contains(theme) { + availableThemes = append(availableThemes, theme) + } + } + } else { + availableThemes = foundThemes + } + sort.Strings(availableThemes) + if len(availableThemes) == 0 { + setting.LogStartupProblem(1, log.ERROR, "No theme candidate in asset files, but Gitea requires there should be at least one usable theme") + availableThemes = []string{setting.UI.DefaultTheme} + } +} + +func GetAvailableThemes() []string { + themeOnce.Do(initThemes) + return availableThemes +} + +func IsThemeAvailable(name string) bool { + themeOnce.Do(initThemes) + return availableThemesSet.Contains(name) +} diff --git a/templates/admin/layout_head.tmpl b/templates/admin/layout_head.tmpl index c1f5fb331404e..7cc6624d5046c 100644 --- a/templates/admin/layout_head.tmpl +++ b/templates/admin/layout_head.tmpl @@ -1,11 +1,9 @@ {{template "base/head" .ctxData}}
-
- {{template "base/alert" .ctxData}} -
{{template "admin/navbar" .ctxData}}
+ {{template "base/alert" .ctxData}} {{/* block: admin-setting-content */}} {{if false}}{{/* to make html structure "likely" complete to prevent IDE warnings */}} diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 2de8f582355aa..174267fd2fd40 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -1,5 +1,5 @@ - + {{if .Title}}{{.Title}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}} diff --git a/templates/base/head_style.tmpl b/templates/base/head_style.tmpl index 0793eaca20dc4..f97e1880ce92c 100644 --- a/templates/base/head_style.tmpl +++ b/templates/base/head_style.tmpl @@ -1,2 +1,2 @@ - + diff --git a/templates/org/team/members.tmpl b/templates/org/team/members.tmpl index 5719328a273af..7e9a59a6bfb45 100644 --- a/templates/org/team/members.tmpl +++ b/templates/org/team/members.tmpl @@ -46,7 +46,7 @@
{{else}}
- {{ctx.Locale.Tr "org.teams.members.none"}} + {{ctx.Locale.Tr "org.teams.members.none"}}
{{end}}
diff --git a/templates/org/team/repositories.tmpl b/templates/org/team/repositories.tmpl index 98b4854eb84fd..f5d68ce41633d 100644 --- a/templates/org/team/repositories.tmpl +++ b/templates/org/team/repositories.tmpl @@ -48,7 +48,7 @@
{{else}}
- {{ctx.Locale.Tr "org.teams.repos.none"}} + {{ctx.Locale.Tr "org.teams.repos.none"}}
{{end}} diff --git a/templates/org/team/sidebar.tmpl b/templates/org/team/sidebar.tmpl index b9e55dd587d14..ac41cda71641d 100644 --- a/templates/org/team/sidebar.tmpl +++ b/templates/org/team/sidebar.tmpl @@ -22,7 +22,7 @@ {{if .Team.Description}} {{.Team.Description}} {{else}} - {{ctx.Locale.Tr "org.teams.no_desc"}} + {{ctx.Locale.Tr "org.teams.no_desc"}} {{end}} {{if eq .Team.LowerName "owners"}} diff --git a/templates/projects/list.tmpl b/templates/projects/list.tmpl index ec02e9a6fc953..b2f48fe2c9c47 100644 --- a/templates/projects/list.tmpl +++ b/templates/projects/list.tmpl @@ -41,9 +41,9 @@
{{range .Projects}}
  • -

    +

    {{svg .IconName 16}} - {{.Title}} + {{.Title}}

    diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index f9b85360e0e3a..3e000660e2859 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -1,8 +1,8 @@ {{$canWriteProject := and .CanWriteProjects (or (not .Repository) (not .Repository.IsArchived))}} -
    -
    -

    {{.Project.Title}}

    +
    +
    +

    {{.Project.Title}}

    {{if $canWriteProject}}
    -