Browse Source

Merge remote-tracking branch 'origin/main' into notext

* origin/main:
  Interpolate runs-on with variables when scheduling tasks (#30640)
  Initial support for colorblindness-friendly themes (#30625)
  Fix flash message for flex-container (#30657)
  Perform Newest sort type correctly when sorting issues (#30644)
  Fix project name wrapping, remove horizontal margin on header (#30631)
  Add a db consistency check to remove runners that do not belong to a repository (#30614)
  Fix wrong table name (#30557)
  Fix compare api swagger (#30648)
  [skip ci] Updated translations via Crowdin
  Fix queue test (#30646)
  Enable jquery-related eslint rules that have no violations (#30632)
  Enable more `revive` linter rules (#30608)
  Remove obsolete CSS text classes (#30576)
  Hide diff stats on empty PRs (#30629)
  [skip ci] Updated licenses and gitignores
  Use correct hash for "git update-index" (#30626)
  Fix repo home UI when there is no repo description (#30552)
  Fix dropdown text ellipsis (#30628)
  fix(api): refactor branch and tag existence checks (#30618)
  Add --skip-db option to dump command (#30613)
pull/30506/head
silverwind 1 week ago
parent
commit
453c63ddc5
No account linked to committer's email address
100 changed files with 302 additions and 256 deletions
  1. 4
    4
      .eslintrc.yaml
  2. 32
    23
      .golangci.yml
  3. 34
    24
      cmd/dump.go
  4. 1
    1
      cmd/hook.go
  5. 2
    1
      custom/conf/app.example.ini
  6. 2
    3
      docs/content/administration/config-cheat-sheet.en-us.md
  7. 2
    3
      docs/content/administration/config-cheat-sheet.zh-cn.md
  8. 1
    1
      docs/content/administration/customizing-gitea.en-us.md
  9. 0
    11
      docs/content/help/faq.en-us.md
  10. 0
    11
      docs/content/help/faq.zh-cn.md
  11. 16
    6
      models/actions/run.go
  12. 24
    2
      models/actions/runner.go
  13. 5
    0
      models/actions/variable.go
  14. 0
    1
      models/asymkey/gpg_key_commit_verification.go
  15. 0
    2
      models/auth/oauth2_test.go
  16. 0
    1
      models/db/engine.go
  17. 0
    2
      models/issues/review.go
  18. 0
    5
      models/migrations/base/db.go
  19. 0
    0
      models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml
  20. 2
    0
      models/migrations/migrations.go
  21. 0
    2
      models/migrations/v1_11/v111.go
  22. 3
    3
      models/migrations/v1_18/v230.go
  23. 3
    3
      models/migrations/v1_18/v230_test.go
  24. 2
    2
      models/migrations/v1_20/v250.go
  25. 10
    0
      models/migrations/v1_23/v298.go
  26. 0
    1
      models/migrations/v1_6/v71.go
  27. 0
    1
      models/migrations/v1_9/v85.go
  28. 1
    2
      models/organization/team.go
  29. 0
    2
      models/project/board.go
  30. 0
    1
      models/repo/user_repo.go
  31. 1
    2
      models/user/user.go
  32. 6
    6
      modules/auth/password/password.go
  33. 3
    3
      modules/git/batch_reader.go
  34. 1
    2
      modules/git/commit_reader.go
  35. 0
    1
      modules/git/pipeline/lfs_nogogit.go
  36. 4
    4
      modules/git/repo_commit.go
  37. 0
    1
      modules/git/submodule.go
  38. 0
    2
      modules/indexer/code/bleve/bleve.go
  39. 2
    2
      modules/indexer/issues/dboptions.go
  40. 0
    1
      modules/indexer/issues/elasticsearch/elasticsearch.go
  41. 0
    1
      modules/log/event_format.go
  42. 0
    2
      modules/markup/markdown/markdown_test.go
  43. 16
    16
      modules/packages/rubygems/marshal.go
  44. 0
    1
      modules/process/manager_stacktraces.go
  45. 11
    7
      modules/queue/workergroup.go
  46. 0
    2
      modules/queue/workerqueue.go
  47. 23
    10
      modules/queue/workerqueue_test.go
  48. 0
    1
      modules/repository/temp.go
  49. 3
    3
      modules/setting/config_provider.go
  50. 1
    1
      modules/setting/oauth2.go
  51. 1
    1
      modules/setting/setting.go
  52. 1
    2
      modules/setting/time.go
  53. 0
    1
      modules/setting/ui.go
  54. 12
    6
      modules/templates/helper.go
  55. 2
    3
      modules/templates/htmlrenderer.go
  56. 1
    2
      modules/templates/mailer.go
  57. 3
    3
      modules/util/util_test.go
  58. 10
    0
      options/license/HPND-UC-export-US
  59. 32
    0
      options/license/NCL
  60. 0
    1
      options/locale/locale_cs-CZ.ini
  61. 0
    1
      options/locale/locale_de-DE.ini
  62. 0
    1
      options/locale/locale_el-GR.ini
  63. 2
    1
      options/locale/locale_en-US.ini
  64. 0
    1
      options/locale/locale_es-ES.ini
  65. 0
    1
      options/locale/locale_fa-IR.ini
  66. 0
    1
      options/locale/locale_fi-FI.ini
  67. 0
    1
      options/locale/locale_fr-FR.ini
  68. 0
    1
      options/locale/locale_hu-HU.ini
  69. 0
    1
      options/locale/locale_id-ID.ini
  70. 0
    1
      options/locale/locale_is-IS.ini
  71. 0
    1
      options/locale/locale_it-IT.ini
  72. 0
    1
      options/locale/locale_ja-JP.ini
  73. 0
    1
      options/locale/locale_ko-KR.ini
  74. 0
    1
      options/locale/locale_lv-LV.ini
  75. 0
    1
      options/locale/locale_nl-NL.ini
  76. 0
    1
      options/locale/locale_pl-PL.ini
  77. 0
    1
      options/locale/locale_pt-BR.ini
  78. 0
    1
      options/locale/locale_pt-PT.ini
  79. 0
    1
      options/locale/locale_ru-RU.ini
  80. 0
    1
      options/locale/locale_si-LK.ini
  81. 0
    1
      options/locale/locale_sk-SK.ini
  82. 0
    1
      options/locale/locale_sv-SE.ini
  83. 0
    1
      options/locale/locale_tr-TR.ini
  84. 0
    1
      options/locale/locale_uk-UA.ini
  85. 0
    1
      options/locale/locale_zh-CN.ini
  86. 0
    1
      options/locale/locale_zh-HK.ini
  87. 0
    1
      options/locale/locale_zh-TW.ini
  88. 0
    1
      routers/api/actions/artifacts.go
  89. 2
    2
      routers/api/packages/alpine/alpine.go
  90. 2
    2
      routers/api/packages/conan/conan.go
  91. 2
    2
      routers/api/packages/conda/conda.go
  92. 3
    3
      routers/api/packages/container/container.go
  93. 2
    2
      routers/api/packages/cran/cran.go
  94. 2
    2
      routers/api/packages/debian/debian.go
  95. 2
    2
      routers/api/packages/generic/generic.go
  96. 2
    2
      routers/api/packages/goproxy/goproxy.go
  97. 2
    2
      routers/api/packages/nuget/nuget.go
  98. 2
    2
      routers/api/packages/rpm/rpm.go
  99. 2
    2
      routers/api/packages/rubygems/rubygems.go
  100. 0
    0
      routers/api/v1/repo/compare.go

+ 4
- 4
.eslintrc.yaml View File

@@ -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]

+ 32
- 23
.golangci.yml View File

@@ -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

+ 34
- 24
cmd/dump.go View File

@@ -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)

+ 1
- 1
cmd/hook.go View File

@@ -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 {

+ 2
- 1
custom/conf/app.example.ini View File

@@ -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.

+ 2
- 3
docs/content/administration/config-cheat-sheet.en-us.md View File

@@ -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

+ 2
- 3
docs/content/administration/config-cheat-sheet.zh-cn.md View File

@@ -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表情符号。

+ 1
- 1
docs/content/administration/customizing-gitea.en-us.md View File

@@ -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-<theme-name>.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 `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`
2. Add `<theme-name>` 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).


+ 0
- 11
docs/content/help/faq.en-us.md View File

@@ -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.

+ 0
- 11
docs/content/help/faq.zh-cn.md View File

@@ -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服务器。

+ 16
- 6
models/actions/run.go View File

@@ -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
}

+ 24
- 2
models/actions/runner.go View File

@@ -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()
}

+ 5
- 0
models/actions/variable.go View File

@@ -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 {

+ 0
- 1
models/asymkey/gpg_key_commit_verification.go View File

@@ -110,7 +110,6 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific
Reason: "gpg.error.no_committer_account",
}
}

}
}


+ 0
- 2
models/auth/oauth2_test.go View File

@@ -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})

+ 0
- 1
models/db/engine.go View File

@@ -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

+ 0
- 2
models/issues/review.go View File

@@ -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")
}

+ 0
- 5
models/migrations/base/db.go View File

@@ -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")
}

models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/o_auth2_application.yml → models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml View File


+ 2
- 0
models/migrations/migrations.go View File

@@ -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

+ 0
- 2
models/migrations/v1_11/v111.go View File

@@ -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

+ 3
- 3
models/migrations/v1_18/v230.go View File

@@ -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))
}

+ 3
- 3
models/migrations/v1_18/v230_test.go View File

@@ -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
}


+ 2
- 2
models/migrations/v1_20/v250.go View File

@@ -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
}

+ 10
- 0
models/migrations/v1_23/v298.go View File

@@ -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")
}

+ 0
- 1
models/migrations/v1_6/v71.go View File

@@ -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)
}

}
}


+ 0
- 1
models/migrations/v1_9/v85.go View File

@@ -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)
}

}
}


+ 1
- 2
models/organization/team.go View File

@@ -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)
}

+ 0
- 2
models/project/board.go View File

@@ -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:

+ 0
- 1
models/repo/user_repo.go View File

@@ -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

+ 1
- 2
models/user/user.go View File

@@ -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)
}

+ 6
- 6
modules/auth/password/password.go View File

@@ -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)
}
}
}

+ 3
- 3
modules/git/batch_reader.go View File

@@ -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

+ 1
- 2
modules/git/commit_reader.go View File

@@ -49,9 +49,8 @@ readLoop:
if len(line) > 0 && line[0] == ' ' {
_, _ = signatureSB.Write(line[1:])
continue
} else {
pgpsig = false
}
pgpsig = false
}

if !message {

+ 0
- 1
modules/git/pipeline/lfs_nogogit.go View File

@@ -232,7 +232,6 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
errChan <- err
break
}

}
}()


+ 4
- 4
modules/git/repo_commit.go View File

@@ -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
}

+ 0
- 1
modules/git/submodule.go View File

@@ -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]

+ 0
- 2
modules/indexer/code/bleve/bleve.go View File

@@ -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() {

+ 2
- 2
modules/indexer/issues/dboptions.go View File

@@ -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
}

+ 0
- 1
modules/indexer/issues/elasticsearch/elasticsearch.go View File

@@ -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

+ 0
- 1
modules/log/event_format.go View File

@@ -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 {

+ 0
- 2
modules/markup/markdown/markdown_test.go View File

@@ -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)

}
}


+ 16
- 16
modules/packages/rubygems/marshal.go View File

@@ -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
}

+ 0
- 1
modules/process/manager_stacktraces.go View File

@@ -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) {

+ 11
- 7
modules/queue/workergroup.go View File

@@ -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

+ 0
- 2
modules/queue/workerqueue.go View File

@@ -40,8 +40,6 @@ type WorkerPoolQueue[T any] struct {
workerMaxNum int
workerActiveNum int
workerNumMu sync.Mutex

workerStartedCounter int32
}

type flushType chan struct{}

+ 23
- 10
modules/queue/workerqueue_test.go View File

@@ -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()
}

+ 0
- 1
modules/repository/temp.go View File

@@ -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
}

+ 3
- 3
modules/setting/config_provider.go View File

@@ -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)
}
}


+ 1
- 1
modules/setting/oauth2.go View File

@@ -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()

+ 1
- 1
modules/setting/setting.go View File

@@ -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
}

+ 1
- 2
modules/setting/time.go View File

@@ -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

+ 0
- 1
modules/setting/ui.go View File

@@ -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:"},

+ 12
- 6
modules/templates/helper.go View File

@@ -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
}

+ 2
- 3
modules/templates/htmlrenderer.go View File

@@ -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 {

+ 1
- 2
modules/templates/mailer.go View File

@@ -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)
}
}
}

+ 3
- 3
modules/util/util_test.go View File

@@ -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)
}


+ 10
- 0
options/license/HPND-UC-export-US View File

@@ -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.

+ 32
- 0
options/license/NCL View File

@@ -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.

+ 0
- 1
options/locale/locale_cs-CZ.ini View File

@@ -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ář

+ 0
- 1
options/locale/locale_de-DE.ini View File

@@ -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

+ 0
- 1
options/locale/locale_el-GR.ini View File

@@ -1118,7 +1118,6 @@ fork=Fork
download_archive=Λήψη Αποθετηρίου
more_operations=Περισσότερες Λειτουργίες

no_desc=Χωρίς Περιγραφή
quick_guide=Γρήγορος Οδηγός
clone_this_repo=Κλωνοποίηση αυτού του αποθετηρίου
cite_this_repo=Αναφορά σε αυτό το αποθετήριο

+ 2
- 1
options/locale/locale_en-US.ini View File

@@ -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

+ 0
- 1
options/locale/locale_es-ES.ini View File

@@ -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

+ 0
- 1
options/locale/locale_fa-IR.ini View File

@@ -874,7 +874,6 @@ star=ستاره دار کن
fork=انشعاب
download_archive=دانلود مخزن

no_desc=بدون توضیح
quick_guide=راهنمای سریع
clone_this_repo=همسان‌سازی این مخزن
create_new_repo_command=ایجاد یک مخزن جدید در خط فرمان

+ 0
- 1
options/locale/locale_fi-FI.ini View File

@@ -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


+ 0
- 1
options/locale/locale_fr-FR.ini View File

@@ -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

+ 0
- 1
options/locale/locale_hu-HU.ini View File

@@ -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

+ 0
- 1
options/locale/locale_id-ID.ini View File

@@ -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

+ 0
- 1
options/locale/locale_is-IS.ini View File

@@ -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

+ 0
- 1
options/locale/locale_it-IT.ini View File

@@ -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

+ 0
- 1
options/locale/locale_ja-JP.ini View File

@@ -1188,7 +1188,6 @@ action.blocked_user=リポジトリのオーナーがあなたをブロックし
download_archive=リポジトリをダウンロード
more_operations=その他の操作

no_desc=説明なし
quick_guide=クイック ガイド
clone_this_repo=このリポジトリのクローンを作成
cite_this_repo=このリポジトリを引用

+ 0
- 1
options/locale/locale_ko-KR.ini View File

@@ -606,7 +606,6 @@ star=좋아요
fork=포크
download_archive=저장소 다운로드

no_desc=설명 없음
quick_guide=퀵 가이드
clone_this_repo=이 저장소 복제
create_new_repo_command=커맨드 라인에서 새 레포리지터리 생성

+ 0
- 1
options/locale/locale_lv-LV.ini View File

@@ -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

+ 0
- 1
options/locale/locale_nl-NL.ini View File

@@ -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

+ 0
- 1
options/locale/locale_pl-PL.ini View File

@@ -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ń

+ 0
- 1
options/locale/locale_pt-BR.ini View File

@@ -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

+ 0
- 1
options/locale/locale_pt-PT.ini View File

@@ -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

+ 0
- 1
options/locale/locale_ru-RU.ini View File

@@ -1098,7 +1098,6 @@ fork=Форкнуть
download_archive=Скачать репозиторий
more_operations=Ещё действия

no_desc=Нет описания
quick_guide=Краткое руководство
clone_this_repo=Клонировать репозиторий
cite_this_repo=Сослаться на этот репозиторий

+ 0
- 1
options/locale/locale_si-LK.ini View File

@@ -846,7 +846,6 @@ star=ස්ටාර්
fork=දෙබලක
download_archive=කෝෂ්ඨය බාගන්න

no_desc=සවිස්තරයක් නැත
quick_guide=ඉක්මන් මාර්ගෝපදේශය
clone_this_repo=මෙම ගබඩාව පරිගණක ක්රිඩාවට සමාන
create_new_repo_command=විධාන රේඛාවේ නව ගබඩාවක් නිර්මාණය කිරීම

+ 0
- 1
options/locale/locale_sk-SK.ini View File

@@ -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

+ 0
- 1
options/locale/locale_sv-SE.ini View File

@@ -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

+ 0
- 1
options/locale/locale_tr-TR.ini View File

@@ -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

+ 0
- 1
options/locale/locale_uk-UA.ini View File

@@ -882,7 +882,6 @@ star=В обрані
fork=Форк
download_archive=Скачати репозиторій

no_desc=Без опису
quick_guide=Короткий посібник
clone_this_repo=Кнонувати цей репозиторій
create_new_repo_command=Створити новий репозиторій з командного рядка

+ 0
- 1
options/locale/locale_zh-CN.ini View File

@@ -1193,7 +1193,6 @@ action.blocked_user=无法执行操作,因为您已被仓库所有者屏蔽。
download_archive=下载此仓库
more_operations=更多操作

no_desc=暂无描述
quick_guide=快速帮助
clone_this_repo=克隆当前仓库
cite_this_repo=引用此仓库

+ 0
- 1
options/locale/locale_zh-HK.ini View File

@@ -344,7 +344,6 @@ unstar=取消收藏
star=收藏
fork=複製

no_desc=暫無描述
quick_guide=快速幫助
clone_this_repo=複製當前儲存庫
create_new_repo_command=從命令列建立新儲存庫。

+ 0
- 1
options/locale/locale_zh-TW.ini View File

@@ -1016,7 +1016,6 @@ fork=Fork
download_archive=下載此儲存庫
more_operations=更多操作

no_desc=暫無描述
quick_guide=快速幫助
clone_this_repo=Clone 此儲存庫
cite_this_repo=引用此儲存庫

+ 0
- 1
routers/api/actions/artifacts.go View File

@@ -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)

+ 2
- 2
routers/api/packages/alpine/alpine.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/conan/conan.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/conda/conda.go View File

@@ -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()
}


+ 3
- 3
routers/api/packages/container/container.go View File

@@ -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)

+ 2
- 2
routers/api/packages/cran/cran.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/debian/debian.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/generic/generic.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/goproxy/goproxy.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/nuget/nuget.go View File

@@ -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)
}


+ 2
- 2
routers/api/packages/rpm/rpm.go View File

@@ -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()
}


+ 2
- 2
routers/api/packages/rubygems/rubygems.go View File

@@ -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()
}


+ 0
- 0
routers/api/v1/repo/compare.go View File


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

Loading…
Cancel
Save