Merge remote-tracking branch 'upstream/main' into limit-repo-size

This commit is contained in:
DmitryFrolovTri
2023-05-03 14:40:58 +00:00
477 changed files with 7190 additions and 5990 deletions
+3 -1
View File
@@ -4,7 +4,9 @@ tmp_dir = ".air"
[build]
cmd = "make backend"
bin = "gitea"
delay = 1000
include_ext = ["go", "tmpl"]
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
include_file = ["main.go"]
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
exclude_regex = ["_test.go$", "_gen.go$"]
+8 -111
View File
@@ -59,7 +59,7 @@ steps:
- name: lint-backend-windows
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
commands:
- make golangci-lint-windows vet
- make lint-go-windows lint-go-vet
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
@@ -756,11 +756,11 @@ steps:
# TODO: We should probably build all dependencies into a test image
- name: test-e2e
image: mcr.microsoft.com/playwright:v1.32.1-focal
image: mcr.microsoft.com/playwright:v1.32.3-focal
commands:
- curl -sLO https://go.dev/dl/go1.20.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
- apt-get -qq update && apt-get -qqy install jq build-essential
- curl -fsSL "https://go.dev/dl/$(curl -s 'https://go.dev/dl/?mode=json' | jq -r '.[].version' | sort -Vr | head -1).linux-amd64.tar.gz" | tar -xz -C /usr/local
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
- apt-get -qq update && apt-get -qqy install build-essential
- ./build/test-env-prepare.sh
- su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-sqlite"
environment:
@@ -773,109 +773,6 @@ steps:
- name: deps
path: /go
---
kind: pipeline
name: update_translations
platform:
os: linux
arch: arm64
trigger:
branch:
- main
event:
- cron
cron:
- update_translations
steps:
- name: download
image: jonasfranz/crowdin
pull: always
settings:
download: true
export_dir: options/locale/
ignore_branch: true
project_identifier: gitea
environment:
CROWDIN_KEY:
from_secret: crowdin_key
- name: update
image: alpine:3.17
pull: always
commands:
- ./build/update-locales.sh
- name: push
image: appleboy/drone-git-push
pull: always
settings:
author_email: "teabot@gitea.io"
author_name: GiteaBot
branch: main
commit: true
commit_message: "[skip ci] Updated translations via Crowdin"
remote: "git@github.com:go-gitea/gitea.git"
environment:
DRONE_COMMIT_AUTHOR_EMAIL: "teabot@gitea.io"
DRONE_COMMIT_AUTHOR: GiteaBot
GIT_PUSH_SSH_KEY:
from_secret: git_push_ssh_key
- name: upload_translations
image: jonasfranz/crowdin
pull: always
settings:
files:
locale_en-US.ini: options/locale/locale_en-US.ini
ignore_branch: true
project_identifier: gitea
environment:
CROWDIN_KEY:
from_secret: crowdin_key
---
kind: pipeline
type: docker
name: update_gitignore_and_licenses
platform:
os: linux
arch: arm64
trigger:
branch:
- main
event:
- cron
cron:
- update_gitignore_and_licenses
steps:
- name: download
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- timeout -s ABRT 40m make generate-license generate-gitignore
- name: push
image: appleboy/drone-git-push
pull: always
settings:
author_email: "teabot@gitea.io"
author_name: "GiteaBot"
branch: main
commit: true
commit_message: "[skip ci] Updated licenses and gitignores"
remote: "git@github.com:go-gitea/gitea.git"
environment:
DRONE_COMMIT_AUTHOR_EMAIL: "teabot@gitea.io"
DRONE_COMMIT_AUTHOR: "GiteaBot"
GIT_PUSH_SSH_KEY:
from_secret: git_push_ssh_key
---
kind: pipeline
type: docker
@@ -1369,7 +1266,7 @@ steps:
pull: always
settings:
auto_tag: false
tags: dev-linux-amd64
tags: nightly-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
@@ -1391,7 +1288,7 @@ steps:
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
tags: dev-linux-amd64-rootless
tags: nightly-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
@@ -1711,7 +1608,7 @@ steps:
pull: always
settings:
auto_tag: false
tags: dev-linux-arm64
tags: nightly-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
@@ -1733,7 +1630,7 @@ steps:
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
tags: dev-linux-arm64-rootless
tags: nightly-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
+96 -2
View File
@@ -12,6 +12,7 @@ plugins:
- eslint-plugin-unicorn
- eslint-plugin-import
- eslint-plugin-jquery
- eslint-plugin-no-jquery
- eslint-plugin-sonarjs
- eslint-plugin-custom-elements
@@ -65,7 +66,7 @@ rules:
curly: [0]
custom-elements/expose-class-on-global: [0]
custom-elements/extends-correct-class: [2]
custom-elements/file-name-matches-element: [0]
custom-elements/file-name-matches-element: [2]
custom-elements/no-constructor: [2]
custom-elements/no-customized-built-in-elements: [2]
custom-elements/no-dom-traversal-in-attributechangedcallback: [2]
@@ -270,6 +271,99 @@ rules:
no-invalid-this: [0]
no-irregular-whitespace: [2]
no-iterator: [2]
no-jquery/no-ajax-events: [2]
no-jquery/no-ajax: [0]
no-jquery/no-and-self: [2]
no-jquery/no-animate-toggle: [2]
no-jquery/no-animate: [2]
no-jquery/no-append-html: [0]
no-jquery/no-attr: [0]
no-jquery/no-bind: [2]
no-jquery/no-box-model: [2]
no-jquery/no-browser: [2]
no-jquery/no-camel-case: [2]
no-jquery/no-class-state: [0]
no-jquery/no-class: [0]
no-jquery/no-clone: [2]
no-jquery/no-closest: [0]
no-jquery/no-constructor-attributes: [2]
no-jquery/no-contains: [2]
no-jquery/no-context-prop: [2]
no-jquery/no-css: [0]
no-jquery/no-data: [0]
no-jquery/no-deferred: [2]
no-jquery/no-delegate: [2]
no-jquery/no-each-collection: [0]
no-jquery/no-each-util: [0]
no-jquery/no-each: [0]
no-jquery/no-error-shorthand: [2]
no-jquery/no-error: [2]
no-jquery/no-escape-selector: [2]
no-jquery/no-event-shorthand: [2]
no-jquery/no-extend: [2]
no-jquery/no-fade: [2]
no-jquery/no-filter: [0]
no-jquery/no-find-collection: [0]
no-jquery/no-find-util: [2]
no-jquery/no-find: [0]
no-jquery/no-fx-interval: [2]
no-jquery/no-global-eval: [2]
no-jquery/no-global-selector: [0]
no-jquery/no-grep: [2]
no-jquery/no-has: [2]
no-jquery/no-hold-ready: [2]
no-jquery/no-html: [0]
no-jquery/no-in-array: [2]
no-jquery/no-is-array: [2]
no-jquery/no-is-empty-object: [2]
no-jquery/no-is-function: [2]
no-jquery/no-is-numeric: [2]
no-jquery/no-is-plain-object: [2]
no-jquery/no-is-window: [2]
no-jquery/no-is: [0]
no-jquery/no-jquery-constructor: [0]
no-jquery/no-live: [2]
no-jquery/no-load-shorthand: [2]
no-jquery/no-load: [2]
no-jquery/no-map-collection: [0]
no-jquery/no-map-util: [2]
no-jquery/no-map: [0]
no-jquery/no-merge: [2]
no-jquery/no-node-name: [2]
no-jquery/no-noop: [2]
no-jquery/no-now: [2]
no-jquery/no-on-ready: [2]
no-jquery/no-other-methods: [0]
no-jquery/no-other-utils: [2]
no-jquery/no-param: [2]
no-jquery/no-parent: [0]
no-jquery/no-parents: [0]
no-jquery/no-parse-html-literal: [0]
no-jquery/no-parse-html: [2]
no-jquery/no-parse-json: [2]
no-jquery/no-parse-xml: [2]
no-jquery/no-prop: [0]
no-jquery/no-proxy: [2]
no-jquery/no-ready-shorthand: [2]
no-jquery/no-ready: [2]
no-jquery/no-selector-prop: [2]
no-jquery/no-serialize: [2]
no-jquery/no-size: [2]
no-jquery/no-sizzle: [0]
no-jquery/no-slide: [2]
no-jquery/no-sub: [2]
no-jquery/no-support: [2]
no-jquery/no-text: [0]
no-jquery/no-trigger: [0]
no-jquery/no-trim: [2]
no-jquery/no-type: [2]
no-jquery/no-unique: [2]
no-jquery/no-unload-shorthand: [2]
no-jquery/no-val: [0]
no-jquery/no-visibility: [2]
no-jquery/no-when: [2]
no-jquery/no-wrap: [2]
no-jquery/variable-pattern: [0]
no-label-var: [2]
no-labels: [0] # handled by no-restricted-syntax
no-lone-blocks: [2]
@@ -500,7 +594,7 @@ rules:
unicorn/prefer-default-parameters: [0]
unicorn/prefer-event-key: [2]
unicorn/prefer-event-target: [2]
unicorn/prefer-export-from: [2]
unicorn/prefer-export-from: [2, {ignoreUsedVariables: true}]
unicorn/prefer-includes: [2]
unicorn/prefer-json-parse-buffer: [0]
unicorn/prefer-logical-operator-over-ternary: [2]
+2
View File
@@ -1,7 +1,9 @@
* text=auto eol=lf
*.tmpl linguist-language=Handlebars
/assets/*.json linguist-generated
/public/img/svg/*.svg linguist-generated
/public/vendor/** -text -eol linguist-vendored
/templates/swagger/v1_json.tmpl linguist-generated
/vendor/** -text -eol linguist-vendored
/web_src/fomantic/build/** linguist-generated
/web_src/js/vendor/** -text -eol linguist-vendored
+28
View File
@@ -0,0 +1,28 @@
on:
schedule:
# weekly on Monday at 0:07 UTC
- cron: "7 0 * * 1"
name: Update licenses and gitignores
jobs:
cron:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '>=1.20.1'
- name: update licenses and gitignores
run: timeout -s ABRT 40m make generate-license generate-gitignore
- name: push translations to repo
uses: appleboy/git-push-action@v0.0.2
with:
author_email: "teabot@gitea.io"
author_name: GiteaBot
branch: main
commit: true
commit_message: "[skip ci] Updated licenses and gitignores"
remote: "git@github.com:go-gitea/gitea.git"
ssh_key: ${{ secrets.DEPLOY_KEY }}
+47
View File
@@ -0,0 +1,47 @@
on:
schedule:
- cron: "7 0 * * *" # every day at 0:07 UTC
name: Pull translations from Crowdin
jobs:
crowdin_pull:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: download from crowdin
uses: docker://jonasfranz/crowdin
env:
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
PLUGIN_DOWNLOAD: true
PLUGIN_EXPORT_DIR: options/locale/
PLUGIN_IGNORE_BRANCH: true
PLUGIN_PROJECT_IDENTIFIER: gitea
- name: update locales
run: ./build/update-locales.sh
- name: push translations to repo
uses: appleboy/git-push-action@v0.0.2
with:
author_email: "teabot@gitea.io"
author_name: GiteaBot
branch: main
commit: true
commit_message: "[skip ci] Updated translations via Crowdin"
remote: "git@github.com:go-gitea/gitea.git"
ssh_key: ${{ secrets.DEPLOY_KEY }}
crowdin_push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: push translations to crowdin
uses: docker://jonasfranz/crowdin
env:
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
PLUGIN_UPLOAD: true
PLUGIN_IGNORE_BRANCH: true
PLUGIN_PROJECT_IDENTIFIER: gitea
PLUGIN_FILES: |
locale_en-US.ini: options/locale/locale_en-US.ini
PLUGIN_BRANCH: main
+1
View File
@@ -71,6 +71,7 @@ cpu.out
/tests/e2e/test-artifacts
/tests/e2e/test-snapshots
/tests/*.ini
/tests/**/*.git/**/*.sample
/node_modules
/yarn.lock
/yarn-error.log
+5 -52
View File
@@ -5,6 +5,7 @@ linters:
- depguard
- dupl
- errcheck
- forbidigo
- gocritic
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
- gofmt
@@ -22,7 +23,7 @@ linters:
- unconvert
- unused
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
# - wastedassign # disabled - https://github.com/golangci/golangci-lint/issues/2649
- wastedassign
enable-all: false
disable-all: true
fast: false
@@ -105,73 +106,25 @@ issues:
- errcheck
- dupl
- gosec
- path: cmd
linters:
- forbidigo
- linters:
- dupl
text: "webhook"
- linters:
- gocritic
text: "`ID' should not be capitalized"
- path: modules/templates/helper.go
linters:
- gocritic
- linters:
- unused
- deadcode
text: "swagger"
- path: contrib/pr/checkout.go
linters:
- errcheck
- path: models/issue.go
linters:
- errcheck
- path: models/migrations/
linters:
- errcheck
- path: modules/log/
linters:
- errcheck
- path: routers/api/v1/repo/issue_subscription.go
linters:
- dupl
- path: routers/repo/view.go
linters:
- dupl
- path: models/migrations/
linters:
- unused
- linters:
- staticcheck
text: "argument x is overwritten before first use"
- path: modules/httplib/httplib.go
linters:
- staticcheck
# Enabling this would require refactoring the methods and how they are called.
- path: models/issue_comment_list.go
linters:
- dupl
- path: models/update.go
linters:
- unused
- path: cmd/dump.go
linters:
- dupl
- path: services/webhook/webhook.go
linters:
- structcheck
- text: "commentFormatting: put a space between `//` and comment text"
linters:
- gocritic
- text: "exitAfterDefer:"
linters:
- gocritic
- path: modules/graceful/manager_windows.go
linters:
- staticcheck
text: "svc.IsAnInteractiveSession is deprecated: Use IsWindowsService instead."
- path: models/user/openid.go
linters:
- golint
- path: models/user/badge.go
linters:
- revive
text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"
+2 -1
View File
@@ -41,7 +41,7 @@ Patrick Schratz <patrick.schratz@gmail.com> (@pat-s)
Janis Estelmann <admin@oldschoolhack.me> (@KN4CK3R)
Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
Leon Hofmeister <dev.lh@web.de> (@delvh)
Leon Hofmeister <dev.lh@web.de> (@delvh)
Wim <wim@42.be> (@42wim)
Jason Song <i@wolfogre.com> (@wolfogre)
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
@@ -49,3 +49,4 @@ Yu Tian <zettat123@gmail.com> (@Zettat123)
Eddie Yang <576951401@qq.com> (@yp05327)
Dong Ge <gedong_1994@163.com> (@sillyguodong)
Xinyi Gong <hestergong@gmail.com> (@HesterG)
wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
+82 -41
View File
@@ -25,16 +25,15 @@ COMMA := ,
XGO_VERSION := go-1.20.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0
ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.43.0
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.4
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.5.0
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
DOCKER_IMAGE ?= gitea/gitea
@@ -97,6 +96,11 @@ else
endif
endif
# if version = "main" then update version to "nightly"
ifeq ($(VERSION),main)
VERSION := main-nightly
endif
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
@@ -194,9 +198,20 @@ help:
@echo " - deps-backend install backend dependencies"
@echo " - deps-tools install tool dependencies"
@echo " - lint lint everything"
@echo " - lint-fix lint everything and fix issues"
@echo " - lint-frontend lint frontend files"
@echo " - lint-frontend-fix lint frontend files and fix issues"
@echo " - lint-backend lint backend files"
@echo " - lint-backend-fix lint backend files and fix issues"
@echo " - lint-go lint go files"
@echo " - lint-go-fix lint go files and fix issues"
@echo " - lint-go-vet lint go files with vet"
@echo " - lint-js lint js files"
@echo " - lint-js-fix lint js files and fix issues"
@echo " - lint-css lint css files"
@echo " - lint-css-fix lint css files and fix issues"
@echo " - lint-md lint markdown files"
@echo " - lint-swagger lint swagger files"
@echo " - checks run various consistency checks"
@echo " - checks-frontend check frontend files"
@echo " - checks-backend check backend files"
@@ -214,9 +229,7 @@ help:
@echo " - generate-manpage generate manpage"
@echo " - generate-swagger generate the swagger spec from code comments"
@echo " - swagger-validate check if the swagger spec is valid"
@echo " - golangci-lint run golangci-lint linter"
@echo " - go-licenses regenerate go licenses"
@echo " - vet examines Go source code and reports suspicious constructs"
@echo " - tidy run go mod tidy"
@echo " - test[\#TestSpecificName] run unit test"
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
@@ -270,8 +283,12 @@ clean:
fmt:
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
@# strip whitespace after '{{' and before `}}` unless there is only whitespace before it
@$(SED_INPLACE) -e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' $(TEMPLATES)
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
@# whitespace before it
@$(SED_INPLACE) \
-e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' \
-e 's/([ ]\{1,\}/(/g' -e '/^[ ]\{1,\})/! s/[ ]\{1,\})/)/g' \
$(TEMPLATES)
.PHONY: fmt-check
fmt-check: fmt
@@ -286,12 +303,6 @@ fmt-check: fmt
misspell-check:
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
.PHONY: vet
vet:
@echo "Running go vet..."
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
.PHONY: $(TAGS_EVIDENCE)
$(TAGS_EVIDENCE):
@mkdir -p $(MAKE_EVIDENCE_DIR)
@@ -324,11 +335,6 @@ swagger-validate:
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
.PHONY: errcheck
errcheck:
@echo "Running errcheck..."
$(GO) run $(ERRCHECK_PACKAGE) $(GO_PACKAGES)
.PHONY: checks
checks: checks-frontend checks-backend
@@ -341,18 +347,69 @@ checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-valida
.PHONY: lint
lint: lint-frontend lint-backend
.PHONY: lint-fix
lint-fix: lint-frontend-fix lint-backend-fix
.PHONY: lint-frontend
lint-frontend: node_modules lint-md
lint-frontend: lint-js lint-css lint-md lint-swagger
.PHONY: lint-frontend-fix
lint-frontend-fix: lint-js-fix lint-css-fix lint-md lint-swagger
.PHONY: lint-backend
lint-backend: lint-go lint-go-vet lint-editorconfig
.PHONY: lint-backend-fix
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
.PHONY: lint-js
lint-js: node_modules
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e
.PHONY: lint-js-fix
lint-js-fix: node_modules
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e --fix
.PHONY: lint-css
lint-css: node_modules
npx stylelint --color --max-warnings=0 web_src/css
.PHONY: lint-css-fix
lint-css-fix: node_modules
npx stylelint --color --max-warnings=0 web_src/css --fix
.PHONY: lint-swagger
lint-swagger: node_modules
npx spectral lint -q -F hint $(SWAGGER_SPEC)
.PHONY: lint-md
lint-md: node_modules
npx markdownlint docs *.md
.PHONY: lint-backend
lint-backend: golangci-lint vet editorconfig-checker
.PHONY: lint-go
lint-go:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
.PHONY: lint-go-fix
lint-go-fix:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --fix
# workaround step for the lint-backend-windows CI task because 'go run' can not
# have distinct GOOS/GOARCH for its build and run steps
.PHONY: lint-go-windows
lint-go-windows:
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
golangci-lint run
.PHONY: lint-go-vet
lint-go-vet:
@echo "Running go vet..."
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
.PHONY: lint-editorconfig
lint-editorconfig:
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates
.PHONY: watch
watch:
@@ -843,7 +900,6 @@ deps-backend:
deps-tools:
$(GO) install $(AIR_PACKAGE)
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
$(GO) install $(ERRCHECK_PACKAGE)
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(GXZ_PAGAGE)
@@ -942,21 +998,6 @@ generate-manpage:
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
.PHONY: golangci-lint
golangci-lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
# workaround step for the lint-backend-windows CI task because 'go run' can not
# have distinct GOOS/GOARCH for its build and run steps
.PHONY: golangci-lint-windows
golangci-lint-windows:
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
golangci-lint run
.PHONY: editorconfig-checker
editorconfig-checker:
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates
.PHONY: docker
docker:
docker build --disable-content-trust=false -t $(DOCKER_REF) .
+5
View File
@@ -1004,6 +1004,11 @@
"path": "golang.org/x/crypto/LICENSE",
"licenseText": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
},
{
"name": "golang.org/x/image",
"path": "golang.org/x/image/LICENSE",
"licenseText": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
},
{
"name": "golang.org/x/mod/semver",
"path": "golang.org/x/mod/semver/LICENSE",
+1 -1
View File
@@ -67,7 +67,7 @@ func TestMigratePackages(t *testing.T) {
entries, err := os.ReadDir(p)
assert.NoError(t, err)
assert.EqualValues(t, 2, len(entries))
assert.Len(t, entries, 2)
assert.EqualValues(t, "01", entries[0].Name())
assert.EqualValues(t, "tmp", entries[1].Name())
}
+4 -4
View File
@@ -24,7 +24,6 @@ import (
"github.com/felixge/fgprof"
"github.com/urfave/cli"
ini "gopkg.in/ini.v1"
)
// PIDFile could be set from build tag
@@ -223,9 +222,10 @@ func setPort(port string) error {
defaultLocalURL += ":" + setting.HTTPPort + "/"
// Save LOCAL_ROOT_URL if port changed
setting.CreateOrAppendToCustomConf("server.LOCAL_ROOT_URL", func(cfg *ini.File) {
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
})
setting.CfgProvider.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
if err := setting.CfgProvider.Save(); err != nil {
return fmt.Errorf("Failed to save config file: %v", err)
}
}
return nil
}
+1
View File
@@ -1,6 +1,7 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package main
import (
+1
View File
@@ -1,6 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package main
import (
+12 -3
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# This is an update script for gitea installed via the binary distribution
# from dl.gitea.io on linux as systemd service. It performs a backup and updates
# from dl.gitea.com on linux as systemd service. It performs a backup and updates
# Gitea in place.
# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
@@ -10,6 +10,15 @@
# upgrade.sh 1.15.10
# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
# Check if gitea service is running
if ! pidof gitea &> /dev/null; then
echo "Error: gitea is not running."
exit 1
fi
# Continue with rest of the script if gitea is running
echo "Gitea is running. Continuing with rest of script..."
# apply variables from environment
: "${giteabin:="/usr/local/bin/gitea"}"
: "${giteahome:="/var/lib/gitea"}"
@@ -69,7 +78,7 @@ require curl xz sha256sum "$sudocmd"
# select version to install
if [[ -z "${giteaversion:-}" ]]; then
require jq
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.io/gitea/version.json | jq -r .latest.version)
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.com/gitea/version.json | jq -r .latest.version)
echo "Latest available version is $giteaversion"
fi
@@ -91,7 +100,7 @@ cd "$giteahome" # needed for gitea dump later
# download new binary
binname="gitea-${giteaversion}-${arch}"
binurl="https://dl.gitea.io/gitea/${giteaversion}/${binname}.xz"
binurl="https://dl.gitea.com/gitea/${giteaversion}/${binname}.xz"
echo "Downloading $binurl..."
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
+3 -5
View File
@@ -1203,10 +1203,9 @@ ROUTER = console
;; Number of line of codes shown for a code comment
;CODE_COMMENT_LINES = 4
;;
;; Value of `theme-color` meta tag, used by Android >= 5.0
;; An invalid color like "none" or "disable" will have the default style
;; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
;THEME_COLOR_META_TAG = `#6cc644`
;; Value of `theme-color` meta tag, used by some mobile browers for chrome and
;; out-of-viewport areas. Default is unset which uses body color.
;THEME_COLOR_META_TAG =
;;
;; Max size of files to be displayed (default is 8MiB)
;MAX_DISPLAY_FILE_SIZE = 8388608
@@ -2340,7 +2339,6 @@ ROUTER = console
;[other]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;SHOW_FOOTER_BRANDING = false
;; Show version information about Gitea and Go in the footer
;SHOW_FOOTER_VERSION = true
;; Show template execution time in the footer
+3 -3
View File
@@ -1,4 +1,4 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-rootless
{{#if build.tags}}
{{#unless (contains "-rc" build.tag)}}
tags:
@@ -10,12 +10,12 @@ tags:
{{/if}}
manifests:
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64-rootless
platform:
architecture: amd64
os: linux
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64-rootless
platform:
architecture: arm64
os: linux
+3 -3
View File
@@ -1,4 +1,4 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}
{{#if build.tags}}
{{#unless (contains "-rc" build.tag)}}
tags:
@@ -10,12 +10,12 @@ tags:
{{/if}}
manifests:
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64
platform:
architecture: amd64
os: linux
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64
platform:
architecture: arm64
os: linux
@@ -220,7 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
regardless of the value of `DEFAULT_THEME`.
- `THEME_COLOR_META_TAG`: **#6cc644**: Value of `theme-color` meta tag, used by Android >= 5.0. An invalid color like "none" or "disable" will have the default style. More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
- `THEME_COLOR_META_TAG`: **\<empty\>**: Value of `theme-color` meta tag, used by some mobile browers for chrome and out-of-viewport areas. Default is unset which uses body color.
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
Values can be emoji alias (:smile:) or a unicode emoji.
@@ -1391,7 +1391,6 @@ although Github don't support this form.
## Other (`other`)
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
@@ -483,5 +483,4 @@ PROXY_HOSTS = *.github.com
## Other (`other`)
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
@@ -49,6 +49,7 @@ We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/h
9. Avoid unnecessary `!important` in CSS, add comments to explain why it's necessary if it can't be avoided.
10. Avoid mixing different events in one event listener, prefer to use individual event listeners for every event.
11. Custom event names are recommended to use `ce-` prefix.
12. Gitea's tailwind-style CSS classes use `gt-` prefix (`gt-relative`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`).
### Accessibility / ARIA
+4 -3
View File
@@ -3,7 +3,7 @@ module code.gitea.io/gitea
go 1.19
require (
code.gitea.io/actions-proto-go v0.2.0
code.gitea.io/actions-proto-go v0.2.1
code.gitea.io/gitea-vet v0.2.2
code.gitea.io/sdk/gitea v0.15.1
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
@@ -104,10 +104,11 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
github.com/yuin/goldmark-meta v1.1.0
golang.org/x/crypto v0.7.0
golang.org/x/image v0.7.0
golang.org/x/net v0.8.0
golang.org/x/oauth2 v0.6.0
golang.org/x/sys v0.6.0
golang.org/x/text v0.8.0
golang.org/x/text v0.9.0
golang.org/x/tools v0.6.0
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1
@@ -290,7 +291,7 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142
replace github.com/blevesearch/zapx/v15 v15.3.6 => github.com/zeripath/zapx/v15 v15.3.6-alignment-fix
replace github.com/nektos/act => gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797
replace github.com/nektos/act => gitea.com/gitea/act v0.243.4
exclude github.com/gofrs/uuid v3.2.0+incompatible
+12 -6
View File
@@ -40,8 +40,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
code.gitea.io/actions-proto-go v0.2.0 h1:nYh9nhhfk67YA4wVNLsCzd//RCvXnljwXClJ33+HPVk=
code.gitea.io/actions-proto-go v0.2.0/go.mod h1:00ys5QDo1iHN1tHNvvddAcy2W/g+425hQya1cCSvq9A=
code.gitea.io/actions-proto-go v0.2.1 h1:ToMN/8thz2q10TuCq8dL2d8mI+/pWpJcHCvG+TELwa0=
code.gitea.io/actions-proto-go v0.2.1/go.mod h1:00ys5QDo1iHN1tHNvvddAcy2W/g+425hQya1cCSvq9A=
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
code.gitea.io/gitea-vet v0.2.2 h1:TEOV/Glf38iGmKzKP0EB++Z5OSL4zGg3RrAvlwaMuvk=
code.gitea.io/gitea-vet v0.2.2/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
@@ -52,8 +52,8 @@ codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsi
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797 h1:QdQ+pHxpbIi2qsgZbYVxqYV7trfW3P5M/T4AfpoM7iw=
gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI=
gitea.com/gitea/act v0.243.4 h1:MuBHBLCJfpa6mzwwvs4xqQynrSP2RRzpHpWfTV16PmI=
gitea.com/gitea/act v0.243.4/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI=
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681 h1:MMSPgnVULVwV9kEBgvyEUhC9v/uviZ55hPJEMjpbNR4=
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
@@ -1331,6 +1331,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -1415,6 +1417,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1533,6 +1536,7 @@ golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -1540,6 +1544,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1551,8 +1556,9 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+51
View File
@@ -0,0 +1,51 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"context"
"code.gitea.io/gitea/models/db"
)
// ActionTaskOutput represents an output of ActionTask.
// So the outputs are bound to a task, that means when a completed job has been rerun,
// the outputs of the job will be reset because the task is new.
// It's by design, to avoid the outputs of the old task to be mixed with the new task.
type ActionTaskOutput struct {
ID int64
TaskID int64 `xorm:"INDEX UNIQUE(task_id_output_key)"`
OutputKey string `xorm:"VARCHAR(255) UNIQUE(task_id_output_key)"`
OutputValue string `xorm:"MEDIUMTEXT"`
}
// FindTaskOutputByTaskID returns the outputs of the task.
func FindTaskOutputByTaskID(ctx context.Context, taskID int64) ([]*ActionTaskOutput, error) {
var outputs []*ActionTaskOutput
return outputs, db.GetEngine(ctx).Where("task_id=?", taskID).Find(&outputs)
}
// FindTaskOutputKeyByTaskID returns the keys of the outputs of the task.
func FindTaskOutputKeyByTaskID(ctx context.Context, taskID int64) ([]string, error) {
var keys []string
return keys, db.GetEngine(ctx).Table(ActionTaskOutput{}).Where("task_id=?", taskID).Cols("output_key").Find(&keys)
}
// InsertTaskOutputIfNotExist inserts a new task output if it does not exist.
func InsertTaskOutputIfNotExist(ctx context.Context, taskID int64, key, value string) error {
return db.WithTx(ctx, func(ctx context.Context) error {
sess := db.GetEngine(ctx)
if exist, err := sess.Exist(&ActionTaskOutput{TaskID: taskID, OutputKey: key}); err != nil {
return err
} else if exist {
return nil
}
_, err := sess.Insert(&ActionTaskOutput{
TaskID: taskID,
OutputKey: key,
OutputValue: value,
})
return err
})
}
+7 -4
View File
@@ -19,13 +19,16 @@ func TestIterate(t *testing.T) {
xe := unittest.GetXORMEngine()
assert.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
var repoCnt int
err := db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error {
repoCnt++
cnt, err := db.GetEngine(db.DefaultContext).Count(&repo_model.RepoUnit{})
assert.NoError(t, err)
var repoUnitCnt int
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error {
repoUnitCnt++
return nil
})
assert.NoError(t, err)
assert.EqualValues(t, 84, repoCnt)
assert.EqualValues(t, cnt, repoUnitCnt)
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
+8 -3
View File
@@ -31,15 +31,20 @@ func TestFind(t *testing.T) {
xe := unittest.GetXORMEngine()
assert.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
var repoUnitCount int
_, err := db.GetEngine(db.DefaultContext).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount)
assert.NoError(t, err)
assert.NotEmpty(t, repoUnitCount)
opts := mockListOptions{}
var repoUnits []repo_model.RepoUnit
err := db.Find(db.DefaultContext, &opts, &repoUnits)
err = db.Find(db.DefaultContext, &opts, &repoUnits)
assert.NoError(t, err)
assert.EqualValues(t, 84, len(repoUnits))
assert.Len(t, repoUnits, repoUnitCount)
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
assert.NoError(t, err)
assert.EqualValues(t, 84, cnt)
assert.EqualValues(t, repoUnitCount, cnt)
repoUnits = make([]repo_model.RepoUnit, 0, 10)
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
-2
View File
@@ -12,8 +12,6 @@ import (
"code.gitea.io/gitea/models/db"
"github.com/stretchr/testify/assert"
_ "github.com/mattn/go-sqlite3"
)
func changeDefaultFileBlockSize(n int64) (restore func()) {
+42
View File
@@ -66,3 +66,45 @@
is_prerelease: true
is_tag: false
created_unix: 946684800
- id: 6
repo_id: 57
publisher_id: 2
tag_name: "v1.0"
lower_tag_name: "v1.0"
target: "main"
title: "v1.0"
sha1: "a8a700e8c644c783ba2c6e742bb81bf91e244bff"
num_commits: 3
is_draft: false
is_prerelease: false
is_tag: false
created_unix: 946684801
- id: 7
repo_id: 57
publisher_id: 2
tag_name: "v1.1"
lower_tag_name: "v1.1"
target: "main"
title: "v1.1"
sha1: "cef06e48f2642cd0dc9597b4bea09f4b3f74aad6"
num_commits: 5
is_draft: false
is_prerelease: false
is_tag: false
created_unix: 946684802
- id: 8
repo_id: 57
publisher_id: 2
tag_name: "v2.0"
lower_tag_name: "v2.0"
target: "main"
title: "v2.0"
sha1: "7197b56fdc75b453f47c9110938cb46a303579fd"
num_commits: 6
is_draft: false
is_prerelease: false
is_tag: false
created_unix: 946684803
+32
View File
@@ -1,3 +1,4 @@
# See models/unit/unit.go for the meaning of the type
-
id: 1
repo_id: 1
@@ -575,3 +576,34 @@
repo_id: 56
type: 1
created_unix: 946684810
-
id: 85
repo_id: 57
type: 1
created_unix: 946684810
-
id: 86
repo_id: 57
type: 2
created_unix: 946684810
-
id: 87
repo_id: 57
type: 3
created_unix: 946684810
-
id: 88
repo_id: 57
type: 4
created_unix: 946684810
-
id: 89
repo_id: 57
type: 5
created_unix: 946684810
-
id: 90
repo_id: 52
type: 1
created_unix: 946684810
+15
View File
@@ -1,3 +1,4 @@
# don't forget to add fixtures in repo_unit.yml
-
id: 1
owner_id: 2
@@ -1559,6 +1560,7 @@
owner_name: user30
lower_name: empty
name: empty
default_branch: master
num_watches: 0
num_stars: 0
num_forks: 0
@@ -1647,3 +1649,16 @@
is_private: true
status: 0
num_issues: 0
-
id: 57
owner_id: 2
owner_name: user2
lower_name: repo-release
name: repo-release
default_branch: main
is_empty: false
is_archived: false
is_private: false
status: 0
num_issues: 0
+2 -2
View File
@@ -66,7 +66,7 @@
num_followers: 2
num_following: 1
num_stars: 2
num_repos: 12
num_repos: 13
num_teams: 0
num_members: 0
visibility: 0
@@ -1091,7 +1091,7 @@
max_repo_creation: -1
is_active: true
is_admin: false
is_restricted: true
is_restricted: false
allow_git_hook: false
allow_import_local: false
allow_create_organization: true
+3 -3
View File
@@ -88,12 +88,12 @@ func TestFindRenamedBranch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
branch, exist, err := git_model.FindRenamedBranch(db.DefaultContext, 1, "dev")
assert.NoError(t, err)
assert.Equal(t, true, exist)
assert.True(t, exist)
assert.Equal(t, "master", branch.To)
_, exist, err = git_model.FindRenamedBranch(db.DefaultContext, 1, "unknow")
assert.NoError(t, err)
assert.Equal(t, false, exist)
assert.False(t, exist)
}
func TestRenameBranch(t *testing.T) {
@@ -115,7 +115,7 @@ func TestRenameBranch(t *testing.T) {
return nil
}))
assert.Equal(t, true, _isDefault)
assert.True(t, _isDefault)
repo1 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
assert.Equal(t, "main", repo1.DefaultBranch)
+70 -77
View File
@@ -52,84 +52,61 @@ func (err ErrCommentNotExist) Unwrap() error {
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
type CommentType int
// define unknown comment type
const (
CommentTypeUnknown CommentType = -1
)
// CommentTypeUndefined is used to search for comments of any type
const CommentTypeUndefined CommentType = -1
// Enumerate all the comment types
const (
// 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
CommentTypeComment CommentType = iota
CommentTypeReopen // 1
CommentTypeClose // 2
CommentTypeComment CommentType = iota // 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
CommentTypeReopen // 1
CommentTypeClose // 2
CommentTypeIssueRef // 3 References.
CommentTypeCommitRef // 4 Reference from a commit (not part of a pull request)
CommentTypeCommentRef // 5 Reference from a comment
CommentTypePullRef // 6 Reference from a pull request
CommentTypeLabel // 7 Labels changed
CommentTypeMilestone // 8 Milestone changed
CommentTypeAssignees // 9 Assignees changed
CommentTypeChangeTitle // 10 Change Title
CommentTypeDeleteBranch // 11 Delete Branch
CommentTypeStartTracking // 12 Start a stopwatch for time tracking
CommentTypeStopTracking // 13 Stop a stopwatch for time tracking
CommentTypeAddTimeManual // 14 Add time manual for time tracking
CommentTypeCancelTracking // 15 Cancel a stopwatch for time tracking
CommentTypeAddedDeadline // 16 Added a due date
CommentTypeModifiedDeadline // 17 Modified the due date
CommentTypeRemovedDeadline // 18 Removed a due date
CommentTypeAddDependency // 19 Dependency added
CommentTypeRemoveDependency // 20 Dependency removed
CommentTypeCode // 21 Comment a line of code
CommentTypeReview // 22 Reviews a pull request by giving general feedback
CommentTypeLock // 23 Lock an issue, giving only collaborators access
CommentTypeUnlock // 24 Unlocks a previously locked issue
CommentTypeChangeTargetBranch // 25 Change pull request's target branch
CommentTypeDeleteTimeManual // 26 Delete time manual for time tracking
CommentTypeReviewRequest // 27 add or remove Request from one
CommentTypeMergePull // 28 merge pull request
CommentTypePullRequestPush // 29 push to PR head branch
CommentTypeProject // 30 Project changed
CommentTypeProjectBoard // 31 Project board changed
CommentTypeDismissReview // 32 Dismiss Review
CommentTypeChangeIssueRef // 33 Change issue ref
CommentTypePRScheduledToAutoMerge // 34 pr was scheduled to auto merge when checks succeed
CommentTypePRUnScheduledToAutoMerge // 35 pr was un scheduled to auto merge when checks succeed
// 3 References.
CommentTypeIssueRef
// 4 Reference from a commit (not part of a pull request)
CommentTypeCommitRef
// 5 Reference from a comment
CommentTypeCommentRef
// 6 Reference from a pull request
CommentTypePullRef
// 7 Labels changed
CommentTypeLabel
// 8 Milestone changed
CommentTypeMilestone
// 9 Assignees changed
CommentTypeAssignees
// 10 Change Title
CommentTypeChangeTitle
// 11 Delete Branch
CommentTypeDeleteBranch
// 12 Start a stopwatch for time tracking
CommentTypeStartTracking
// 13 Stop a stopwatch for time tracking
CommentTypeStopTracking
// 14 Add time manual for time tracking
CommentTypeAddTimeManual
// 15 Cancel a stopwatch for time tracking
CommentTypeCancelTracking
// 16 Added a due date
CommentTypeAddedDeadline
// 17 Modified the due date
CommentTypeModifiedDeadline
// 18 Removed a due date
CommentTypeRemovedDeadline
// 19 Dependency added
CommentTypeAddDependency
// 20 Dependency removed
CommentTypeRemoveDependency
// 21 Comment a line of code
CommentTypeCode
// 22 Reviews a pull request by giving general feedback
CommentTypeReview
// 23 Lock an issue, giving only collaborators access
CommentTypeLock
// 24 Unlocks a previously locked issue
CommentTypeUnlock
// 25 Change pull request's target branch
CommentTypeChangeTargetBranch
// 26 Delete time manual for time tracking
CommentTypeDeleteTimeManual
// 27 add or remove Request from one
CommentTypeReviewRequest
// 28 merge pull request
CommentTypeMergePull
// 29 push to PR head branch
CommentTypePullRequestPush
// 30 Project changed
CommentTypeProject
// 31 Project board changed
CommentTypeProjectBoard
// 32 Dismiss Review
CommentTypeDismissReview
// 33 Change issue ref
CommentTypeChangeIssueRef
// 34 pr was scheduled to auto merge when checks succeed
CommentTypePRScheduledToAutoMerge
// 35 pr was un scheduled to auto merge when checks succeed
CommentTypePRUnScheduledToAutoMerge
)
var commentStrings = []string{
@@ -181,7 +158,23 @@ func AsCommentType(typeName string) CommentType {
return CommentType(index)
}
}
return CommentTypeUnknown
return CommentTypeUndefined
}
func (t CommentType) HasContentSupport() bool {
switch t {
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
return true
}
return false
}
func (t CommentType) HasAttachmentSupport() bool {
switch t {
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
return true
}
return false
}
// RoleDescriptor defines comment tag type
@@ -1039,7 +1032,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
if opts.Before > 0 {
cond = cond.And(builder.Lte{"comment.updated_unix": opts.Before})
}
if opts.Type != CommentTypeUnknown {
if opts.Type != CommentTypeUndefined {
cond = cond.And(builder.Eq{"comment.type": opts.Type})
}
if opts.Line != 0 {
+10 -2
View File
@@ -56,7 +56,7 @@ func (comments CommentList) getLabelIDs() []int64 {
return ids.Values()
}
func (comments CommentList) loadLabels(ctx context.Context) error { //nolint
func (comments CommentList) loadLabels(ctx context.Context) error {
if len(comments) == 0 {
return nil
}
@@ -415,7 +415,7 @@ func (comments CommentList) getReviewIDs() []int64 {
return ids.Values()
}
func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
func (comments CommentList) loadReviews(ctx context.Context) error {
if len(comments) == 0 {
return nil
}
@@ -453,6 +453,14 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
for _, comment := range comments {
comment.Review = reviews[comment.ReviewID]
// If the comment dismisses a review, we need to load the reviewer to show whose review has been dismissed.
// Otherwise, the reviewer is the poster of the comment, so we don't need to load it.
if comment.Type == CommentTypeDismissReview {
if err := comment.Review.LoadReviewer(ctx); err != nil {
return err
}
}
}
return nil
}
+3 -2
View File
@@ -64,8 +64,9 @@ func TestFetchCodeComments(t *testing.T) {
}
func TestAsCommentType(t *testing.T) {
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType(""))
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType("nonsense"))
assert.Equal(t, issues_model.CommentType(0), issues_model.CommentTypeComment)
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType(""))
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType("nonsense"))
assert.Equal(t, issues_model.CommentTypeComment, issues_model.AsCommentType("comment"))
assert.Equal(t, issues_model.CommentTypePRUnScheduledToAutoMerge, issues_model.AsCommentType("pull_cancel_scheduled_merge"))
}
+1 -1
View File
@@ -269,7 +269,7 @@ func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
}
func (issue *Issue) loadComments(ctx context.Context) (err error) {
return issue.loadCommentsByType(ctx, CommentTypeUnknown)
return issue.loadCommentsByType(ctx, CommentTypeUndefined)
}
// LoadDiscussComments loads discuss comments
+2 -2
View File
@@ -109,11 +109,11 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2")
assert.NoError(t, err)
assert.Equal(t, true, exist)
assert.True(t, exist)
exist, err = issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "not_exist_branch")
assert.NoError(t, err)
assert.Equal(t, false, exist)
assert.False(t, exist)
}
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
+1 -1
View File
@@ -35,7 +35,7 @@ func TestAddTime(t *testing.T) {
assert.Equal(t, int64(3661), tt.Time)
comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeAddTimeManual, PosterID: 3, IssueID: 1})
assert.Equal(t, comment.Content, "1 hour 1 minute")
assert.Equal(t, "1 hour 1 minute", comment.Content)
}
func TestGetTrackedTimes(t *testing.T) {
-5
View File
@@ -165,11 +165,6 @@ func (log *TestLogger) Init(config string) error {
return nil
}
// Content returns the content accumulated in the content provider
func (log *TestLogger) Content() (string, error) {
return "", fmt.Errorf("not supported")
}
// Flush when log should be flushed
func (log *TestLogger) Flush() {
}
+1
View File
@@ -1,6 +1,7 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package base
import (
+2
View File
@@ -485,6 +485,8 @@ var migrations = []Migration{
NewMigration("Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
// v253 -> v254
NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
// v254 -> v255
NewMigration("Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
// to modify later
NewMigration("Add size limit on repository", v1_20.AddSizeLimitOnRepo),
}
+1 -1
View File
@@ -31,7 +31,7 @@ func RemoveAttachmentMissedRepo(x *xorm.Engine) error {
for i := 0; i < len(attachments); i++ {
uuid := attachments[i].UUID
if err = util.RemoveAll(filepath.Join(setting.Attachment.Path, uuid[0:1], uuid[1:2], uuid)); err != nil {
fmt.Printf("Error: %v", err)
fmt.Printf("Error: %v", err) //nolint:forbidigo
}
}
+4 -4
View File
@@ -22,10 +22,10 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
type RepoIndexerType int
const (
// RepoIndexerTypeCode code indexer
RepoIndexerTypeCode RepoIndexerType = iota // 0
// RepoIndexerTypeStats repository stats indexer
RepoIndexerTypeStats // 1
// RepoIndexerTypeCode code indexer - 0
RepoIndexerTypeCode RepoIndexerType = iota //nolint:unused
// RepoIndexerTypeStats repository stats indexer - 1
RepoIndexerTypeStats
)
// RepoIndexerStatus see models/repo_indexer.go
+2 -2
View File
@@ -8,13 +8,13 @@ import (
)
func FixRepoTopics(x *xorm.Engine) error {
type Topic struct {
type Topic struct { //nolint:unused
ID int64 `xorm:"pk autoincr"`
Name string `xorm:"UNIQUE VARCHAR(25)"`
RepoCount int
}
type RepoTopic struct {
type RepoTopic struct { //nolint:unused
RepoID int64 `xorm:"pk"`
TopicID int64 `xorm:"pk"`
}
+2 -2
View File
@@ -16,7 +16,7 @@ func ConvertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error {
return nil
}
type HookTask struct {
type HookTask struct { //nolint:unused
Typ string `xorm:"VARCHAR(16) index"`
}
@@ -42,7 +42,7 @@ func ConvertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error {
return err
}
type Webhook struct {
type Webhook struct { //nolint:unused
Type string `xorm:"VARCHAR(16) index"`
}
+18
View File
@@ -0,0 +1,18 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_20 //nolint
import (
"xorm.io/xorm"
)
func AddActionTaskOutputTable(x *xorm.Engine) error {
type ActionTaskOutput struct {
ID int64
TaskID int64 `xorm:"INDEX UNIQUE(task_id_output_key)"`
OutputKey string `xorm:"VARCHAR(255) UNIQUE(task_id_output_key)"`
OutputValue string `xorm:"MEDIUMTEXT"`
}
return x.Sync(new(ActionTaskOutput))
}
+14 -4
View File
@@ -414,10 +414,17 @@ func DeleteTeam(t *organization.Team) error {
&organization.TeamUser{OrgID: t.OrgID, TeamID: t.ID},
&organization.TeamUnit{TeamID: t.ID},
&organization.TeamInvite{TeamID: t.ID},
&issues_model.Review{Type: issues_model.ReviewTypeRequest, ReviewerTeamID: t.ID}, // batch delete the binding relationship between team and PR (request review from team)
); err != nil {
return err
}
for _, tm := range t.Members {
if err := removeInvalidOrgUser(ctx, tm.ID, t.OrgID); err != nil {
return err
}
}
// Update organization number of teams.
if _, err := db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
return err
@@ -567,16 +574,19 @@ func removeTeamMember(ctx context.Context, team *organization.Team, userID int64
}
}
return removeInvalidOrgUser(ctx, userID, team.OrgID)
}
func removeInvalidOrgUser(ctx context.Context, userID, orgID int64) error {
// Check if the user is a member of any team in the organization.
if count, err := e.Count(&organization.TeamUser{
if count, err := db.GetEngine(ctx).Count(&organization.TeamUser{
UID: userID,
OrgID: team.OrgID,
OrgID: orgID,
}); err != nil {
return err
} else if count == 0 {
return removeOrgUser(ctx, team.OrgID, userID)
return removeOrgUser(ctx, orgID, userID)
}
return nil
}
+5 -1
View File
@@ -342,11 +342,15 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
// insert units for team
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
for _, tp := range unit.AllRepoUnitTypes {
up := perm.AccessModeOwner
if tp == unit.TypeExternalTracker || tp == unit.TypeExternalWiki {
up = perm.AccessModeRead
}
units = append(units, TeamUnit{
OrgID: org.ID,
TeamID: t.ID,
Type: tp,
AccessMode: perm.AccessModeOwner,
AccessMode: up,
})
}
+7 -1
View File
@@ -226,6 +226,12 @@ func (repo *Repository) IsBroken() bool {
return repo.Status == RepositoryBroken
}
// MarkAsBrokenEmpty marks the repo as broken and empty
func (repo *Repository) MarkAsBrokenEmpty() {
repo.Status = RepositoryBroken
repo.IsEmpty = true
}
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (repo *Repository) AfterLoad() {
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
@@ -769,7 +775,7 @@ func IsRepositoryExist(ctx context.Context, u *user_model.User, repoName string)
return false, err
}
isDir, err := util.IsDir(RepoPath(u.Name, repoName))
return has && isDir, err
return has || isDir, err
}
// GetTemplateRepo populates repo.TemplateRepo for a generated repository and
+3 -3
View File
@@ -235,12 +235,12 @@ func TestSearchRepository(t *testing.T) {
{
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
count: 29,
count: 30,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
count: 34,
count: 35,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
@@ -255,7 +255,7 @@ func TestSearchRepository(t *testing.T) {
{
name: "AllPublic/PublicRepositoriesOfOrganization",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
count: 29,
count: 30,
},
{
name: "AllTemplates",
+1 -1
View File
@@ -152,7 +152,7 @@ func init() {
Query()
assert.NoError(t, err)
assert.EqualValues(t, label.int("NumIssues"), len(issueLabels), "Unexpected number of issue for label id: %d", label.int("ID"))
assert.Len(t, issueLabels, label.int("NumIssues"), "Unexpected number of issue for label id: %d", label.int("ID"))
issueIDs := make([]int, len(issueLabels))
for i, issueLabel := range issueLabels {
+10 -11
View File
@@ -1,6 +1,7 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package unittest
import (
@@ -17,7 +18,7 @@ import (
"xorm.io/xorm/schemas"
)
var fixtures *testfixtures.Loader
var fixturesLoader *testfixtures.Loader
// GetXORMEngine gets the XORM engine
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
@@ -30,11 +31,11 @@ func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
// InitFixtures initialize test fixtures for a test database
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
e := GetXORMEngine(engine...)
var testfiles func(*testfixtures.Loader) error
var fixtureOptionFiles func(*testfixtures.Loader) error
if opts.Dir != "" {
testfiles = testfixtures.Directory(opts.Dir)
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
} else {
testfiles = testfixtures.Files(opts.Files...)
fixtureOptionFiles = testfixtures.Files(opts.Files...)
}
dialect := "unknown"
switch e.Dialect().URI().DBType {
@@ -54,14 +55,14 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
testfixtures.Database(e.DB().DB),
testfixtures.Dialect(dialect),
testfixtures.DangerousSkipTestDatabaseCheck(),
testfiles,
fixtureOptionFiles,
}
if e.Dialect().URI().DBType == schemas.POSTGRES {
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
}
fixtures, err = testfixtures.New(loaderOptions...)
fixturesLoader, err = testfixtures.New(loaderOptions...)
if err != nil {
return err
}
@@ -78,11 +79,9 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
func LoadFixtures(engine ...*xorm.Engine) error {
e := GetXORMEngine(engine...)
var err error
// Database transaction conflicts could occur and result in ROLLBACK
// As a simple workaround, we just retry 20 times.
for i := 0; i < 20; i++ {
err = fixtures.Load()
if err == nil {
// (doubt) database transaction conflicts could occur and result in ROLLBACK? just try for a few times.
for i := 0; i < 5; i++ {
if err = fixturesLoader.Load(); err == nil {
break
}
time.Sleep(200 * time.Millisecond)
+1 -1
View File
@@ -17,7 +17,7 @@ type Badge struct {
}
// UserBadge represents a user badge
type UserBadge struct {
type UserBadge struct { //nolint:revive
ID int64 `xorm:"pk autoincr"`
BadgeID int64
UserID int64 `xorm:"INDEX"`
+1 -1
View File
@@ -62,7 +62,7 @@ const (
EmailNotificationsOnMention = "onmention"
// EmailNotificationsDisabled indicates that the user would not like to be notified via email.
EmailNotificationsDisabled = "disabled"
// EmailNotificationsEnabled indicates that the user would like to receive all email notifications and your own
// EmailNotificationsAndYourOwn indicates that the user would like to receive all email notifications and your own
EmailNotificationsAndYourOwn = "andyourown"
)
+8 -6
View File
@@ -5,6 +5,7 @@ package user_test
import (
"context"
"fmt"
"math/rand"
"strings"
"testing"
@@ -35,10 +36,10 @@ func TestGetUserEmailsByNames(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
// ignore none active user email
assert.Equal(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
assert.Equal(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
assert.Equal(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user7"}))
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user7"}))
}
func TestCanCreateOrganization(t *testing.T) {
@@ -64,9 +65,10 @@ func TestSearchUsers(t *testing.T) {
testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) {
users, _, err := user_model.SearchUsers(opts)
assert.NoError(t, err)
if assert.Len(t, users, len(expectedUserOrOrgIDs), opts) {
cassText := fmt.Sprintf("ids: %v, opts: %v", expectedUserOrOrgIDs, opts)
if assert.Len(t, users, len(expectedUserOrOrgIDs), "case: %s", cassText) {
for i, expectedID := range expectedUserOrOrgIDs {
assert.EqualValues(t, expectedID, users[i].ID)
assert.EqualValues(t, expectedID, users[i].ID, "case: %s", cassText)
}
}
}
@@ -118,7 +120,7 @@ func TestSearchUsers(t *testing.T) {
[]int64{1})
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsRestricted: util.OptionalBoolTrue},
[]int64{29, 30})
[]int64{29})
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsProhibitLogin: util.OptionalBoolTrue},
[]int64{30})
+8
View File
@@ -29,6 +29,14 @@ func init() {
}
}
func IsWorkflow(path string) bool {
if (!strings.HasSuffix(path, ".yaml")) && (!strings.HasSuffix(path, ".yml")) {
return false
}
return strings.HasPrefix(path, ".gitea/workflows") || strings.HasPrefix(path, ".github/workflows")
}
func ListWorkflows(commit *git.Commit) (git.Entries, error) {
tree, err := commit.SubTree(".gitea/workflows")
if _, ok := err.(git.ErrNotExist); ok {
+2
View File
@@ -18,6 +18,8 @@ import (
"github.com/nfnt/resize"
"github.com/oliamb/cutter"
_ "golang.org/x/image/webp" // for processing webp images
)
// AvatarSize returns avatar's size
+3 -1
View File
@@ -47,7 +47,9 @@ func (e *escapeStreamer) EscapeStatus() *EscapeStatus {
// Text tells the next streamer there is a text
func (e *escapeStreamer) Text(data string) error {
sb := &strings.Builder{}
pos, until, next := 0, 0, 0
var until int
var next int
pos := 0
if len(data) > len(UTF8BOM) && data[:len(UTF8BOM)] == string(UTF8BOM) {
_, _ = sb.WriteString(data[:len(UTF8BOM)])
pos = len(UTF8BOM)
-194
View File
@@ -1,194 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package context
import (
"net/http"
"strings"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web/middleware"
)
// ToggleOptions contains required or check options
type ToggleOptions struct {
SignInRequired bool
SignOutRequired bool
AdminRequired bool
DisableCSRF bool
}
// Toggle returns toggle options as middleware
func Toggle(options *ToggleOptions) func(ctx *Context) {
return func(ctx *Context) {
// Check prohibit login users.
if ctx.IsSigned {
if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, "user/auth/activate")
return
}
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
return
}
if ctx.Doer.MustChangePassword {
if ctx.Req.URL.Path != "/user/settings/change_password" {
if strings.HasPrefix(ctx.Req.UserAgent(), "git") {
ctx.Error(http.StatusUnauthorized, ctx.Tr("auth.must_change_password"))
return
}
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
return
}
} else if ctx.Req.URL.Path == "/user/settings/change_password" {
// make sure that the form cannot be accessed by users who don't need this
ctx.Redirect(setting.AppSubURL + "/")
return
}
}
// Redirect to dashboard if user tries to visit any non-login page.
if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
ctx.Redirect(setting.AppSubURL + "/")
return
}
if !options.SignOutRequired && !options.DisableCSRF && ctx.Req.Method == "POST" {
ctx.Csrf.Validate(ctx)
if ctx.Written() {
return
}
}
if options.SignInRequired {
if !ctx.IsSigned {
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/login")
return
} else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, "user/auth/activate")
return
}
}
// Redirect to log in page if auto-signin info is provided and has not signed in.
if !options.SignOutRequired && !ctx.IsSigned &&
len(ctx.GetSiteCookie(setting.CookieUserName)) > 0 {
if ctx.Req.URL.Path != "/user/events" {
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
}
ctx.Redirect(setting.AppSubURL + "/user/login")
return
}
if options.AdminRequired {
if !ctx.Doer.IsAdmin {
ctx.Error(http.StatusForbidden)
return
}
ctx.Data["PageIsAdmin"] = true
}
}
}
// ToggleAPI returns toggle options as middleware
func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
return func(ctx *APIContext) {
// Check prohibit login users.
if ctx.IsSigned {
if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "This account is not activated.",
})
return
}
if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "This account is prohibited from signing in, please contact your site administrator.",
})
return
}
if ctx.Doer.MustChangePassword {
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "You must change your password. Change it at: " + setting.AppURL + "/user/change_password",
})
return
}
}
// Redirect to dashboard if user tries to visit any non-login page.
if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
ctx.Redirect(setting.AppSubURL + "/")
return
}
if options.SignInRequired {
if !ctx.IsSigned {
// Restrict API calls with error message.
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "Only signed in user is allowed to call APIs.",
})
return
} else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, "user/auth/activate")
return
}
if ctx.IsSigned && ctx.IsBasicAuth {
if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) {
return // Skip 2FA
}
twofa, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
if err != nil {
if auth.IsErrTwoFactorNotEnrolled(err) {
return // No 2FA enrollment for this user
}
ctx.InternalServerError(err)
return
}
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
ok, err := twofa.ValidateTOTP(otpHeader)
if err != nil {
ctx.InternalServerError(err)
return
}
if !ok {
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "Only signed in user is allowed to call APIs.",
})
return
}
}
}
if options.AdminRequired {
if !ctx.Doer.IsAdmin {
ctx.JSON(http.StatusForbidden, map[string]string{
"message": "You have no permission to request for this.",
})
return
}
ctx.Data["PageIsAdmin"] = true
}
}
}
+3 -4
View File
@@ -47,7 +47,7 @@ const CookieNameFlash = "gitea_flash"
// Render represents a template render
type Render interface {
TemplateLookup(tmpl string) (*template.Template, error)
TemplateLookup(tmpl string) (templates.TemplateExecutor, error)
HTML(w io.Writer, status int, name string, data interface{}) error
}
@@ -301,7 +301,7 @@ func (ctx *Context) serverErrorInternal(logMsg string, logErr error) {
// it's safe to show internal error to admin users, and it helps
if !setting.IsProd || (ctx.Doer != nil && ctx.Doer.IsAdmin) {
ctx.Data["ErrorMsg"] = logErr
ctx.Data["ErrorMsg"] = fmt.Sprintf("%s, %s", logMsg, logErr)
}
}
@@ -741,8 +741,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler {
ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
ctx.Data["ShowMilestonesDashboardPage"] = setting.Service.ShowMilestonesDashboardPage
ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion
ctx.Data["ShowFooterVersion"] = setting.Other.ShowFooterVersion
ctx.Data["EnableSwagger"] = setting.API.EnableSwagger
ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn
+25 -16
View File
@@ -184,6 +184,9 @@ func (r *Repository) CanCreateIssueDependencies(user *user_model.User, isPull bo
// GetCommitsCount returns cached commit count for current view
func (r *Repository) GetCommitsCount() (int64, error) {
if r.Commit == nil {
return 0, nil
}
var contextName string
if r.IsViewBranch {
contextName = r.BranchName
@@ -449,7 +452,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
userName := ctx.Params(":username")
repoName := ctx.Params(":reponame")
repoName = strings.TrimSuffix(repoName, ".git")
if setting.EnableFeed {
if setting.Other.EnableFeed {
repoName = strings.TrimSuffix(repoName, ".rss")
repoName = strings.TrimSuffix(repoName, ".atom")
}
@@ -537,7 +540,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Data["RepoLink"] = ctx.Repo.RepoLink
ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
if setting.EnableFeed {
if setting.Other.EnableFeed {
ctx.Data["EnableFeed"] = true
ctx.Data["FeedURL"] = ctx.Repo.RepoLink
}
@@ -642,8 +645,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if err != nil {
if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
ctx.Repo.Repository.Status = repo_model.RepositoryBroken
ctx.Repo.Repository.IsEmpty = true
ctx.Repo.Repository.MarkAsBrokenEmpty()
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
// Only allow access to base of repo or settings
if !isHomeOrSettings {
@@ -689,7 +691,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Data["BranchesCount"] = len(brs)
// If not branch selected, try default one.
// If default branch doesn't exists, fall back to some other branch.
// If default branch doesn't exist, fall back to some other branch.
if len(ctx.Repo.BranchName) == 0 {
if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
@@ -878,6 +880,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
return func(ctx *Context) (cancel context.CancelFunc) {
// Empty repository does not have reference information.
if ctx.Repo.Repository.IsEmpty {
// assume the user is viewing the (non-existent) default branch
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
ctx.Data["TreePath"] = ""
return
}
@@ -907,27 +913,30 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
refName = ctx.Repo.Repository.DefaultBranch
if !ctx.Repo.GitRepo.IsBranchExist(refName) {
brs, _, err := ctx.Repo.GitRepo.GetBranchNames(0, 0)
if err != nil {
ctx.ServerError("GetBranches", err)
return
if err == nil && len(brs) != 0 {
refName = brs[0]
} else if len(brs) == 0 {
err = fmt.Errorf("No branches in non-empty repository %s",
ctx.Repo.GitRepo.Path)
ctx.ServerError("GetBranches", err)
return
log.Error("No branches in non-empty repository %s", ctx.Repo.GitRepo.Path)
ctx.Repo.Repository.MarkAsBrokenEmpty()
} else {
log.Error("GetBranches error: %v", err)
ctx.Repo.Repository.MarkAsBrokenEmpty()
}
refName = brs[0]
}
ctx.Repo.RefName = refName
ctx.Repo.BranchName = refName
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
if err != nil {
if err == nil {
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if strings.Contains(err.Error(), "fatal: not a git repository") || strings.Contains(err.Error(), "object does not exist") {
// if the repository is broken, we can continue to the handler code, to show "Settings -> Delete Repository" for end users
log.Error("GetBranchCommit: %v", err)
ctx.Repo.Repository.MarkAsBrokenEmpty()
} else {
ctx.ServerError("GetBranchCommit", err)
return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
ctx.Repo.IsViewBranch = true
} else {
refName = getRefName(ctx, refType)
ctx.Repo.RefName = refName
+1 -1
View File
@@ -106,7 +106,7 @@ func isWritableDir(path string) error {
return err
}
if err := os.Remove(tmpFile.Name()); err != nil {
fmt.Printf("Warning: can't remove temporary file: '%s'\n", tmpFile.Name())
fmt.Printf("Warning: can't remove temporary file: '%s'\n", tmpFile.Name()) //nolint:forbidigo
}
tmpFile.Close()
return nil
+12 -4
View File
@@ -211,10 +211,18 @@ type RunOpts struct {
Env []string
Timeout time.Duration
UseContextTimeout bool
Dir string
Stdout, Stderr io.Writer
Stdin io.Reader
PipelineFunc func(context.Context, context.CancelFunc) error
// Dir is the working dir for the git command, however:
// FIXME: this could be incorrect in many cases, for example:
// * /some/path/.git
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
// The correct approach is to use `--git-dir" global argument
Dir string
Stdout, Stderr io.Writer
Stdin io.Reader
PipelineFunc func(context.Context, context.CancelFunc) error
}
func commonBaseEnvs() []string {
+1 -1
View File
@@ -80,7 +80,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool) error {
// IsEmpty Check if repository is empty.
func (repo *Repository) IsEmpty() (bool, error) {
var errbuf, output strings.Builder
if err := NewCommand(repo.Ctx, "show-ref", "--head", "^HEAD$").
if err := NewCommand(repo.Ctx).AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("show-ref", "--head", "^HEAD$").
Run(&RunOpts{
Dir: repo.Path,
Stdout: &output,
+2 -2
View File
@@ -19,7 +19,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
n, err := wr.Write([]byte(testStr))
assert.Equal(t, n, len(testStr))
assert.Len(t, testStr, n)
assert.NoError(t, err)
select {
case attr := <-wr.ReadAttribute():
@@ -32,7 +32,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
// Write a second attribute again
n, err = wr.Write([]byte(testStr))
assert.Equal(t, n, len(testStr))
assert.Len(t, testStr, n)
assert.NoError(t, err)
select {
+1 -1
View File
@@ -61,7 +61,7 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
}
repo.batchWriter, repo.batchReader, repo.batchCancel = CatFileBatch(ctx, repoPath)
repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repo.Path)
repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repoPath)
return repo, nil
}
+3
View File
@@ -84,6 +84,9 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
if err != nil {
return nil, err
}
if len(commits) == 0 {
return nil, ErrNotExist{ID: relpath}
}
return commits[0], nil
}
+1 -1
View File
@@ -97,6 +97,6 @@ func TestRepository_CommitsBetweenIDs(t *testing.T) {
for i, c := range cases {
commits, err := bareRepo1.CommitsBetweenIDs(c.NewID, c.OldID)
assert.NoError(t, err)
assert.Equal(t, c.ExpectedCommits, len(commits), "case %d", i)
assert.Len(t, commits, c.ExpectedCommits, "case %d", i)
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ func TestRepository_GetTags(t *testing.T) {
return
}
assert.Len(t, tags, 2)
assert.Equal(t, len(tags), total)
assert.Len(t, tags, total)
assert.EqualValues(t, "signed-tag", tags[0].Name)
assert.EqualValues(t, "36f97d9a96457e2bab511db30fe2db03893ebc64", tags[0].ID.String())
assert.EqualValues(t, "tag", tags[0].Type)
+1 -1
View File
@@ -96,7 +96,7 @@ func (g *Manager) start() {
run := svc.Run
//lint:ignore SA1019 We use IsAnInteractiveSession because IsWindowsService has a different permissions profile
isAnInteractiveSession, err := svc.IsAnInteractiveSession()
isAnInteractiveSession, err := svc.IsAnInteractiveSession() //nolint:staticcheck
if err != nil {
log.Error("Unable to ascertain if running as an Windows Service: %v", err)
return
+3 -1
View File
@@ -154,7 +154,9 @@ func Init() {
log.Trace("IndexerData Process Repo: %d", indexerData.RepoID)
if err := index(ctx, indexer, indexerData.RepoID); err != nil {
log.Error("index: %v", err)
if !setting.IsInTesting {
log.Error("indexer index error for repo %v: %v", indexerData.RepoID, err)
}
if indexer.Ping() {
continue
}
+1 -1
View File
@@ -69,7 +69,7 @@ func testIndexer(name string, t *testing.T, indexer Indexer) {
t.Run(kw.Keyword, func(t *testing.T) {
total, res, langs, err := indexer.Search(context.TODO(), kw.RepoIDs, "", kw.Keyword, 1, 10, false)
assert.NoError(t, err)
assert.EqualValues(t, len(kw.IDs), total)
assert.Len(t, kw.IDs, int(total))
assert.Len(t, langs, kw.Langs)
ids := make([]int64, 0, len(res))
+1 -2
View File
@@ -16,7 +16,6 @@ import (
_ "code.gitea.io/gitea/models"
"github.com/stretchr/testify/assert"
"gopkg.in/ini.v1"
)
func TestMain(m *testing.M) {
@@ -27,7 +26,7 @@ func TestMain(m *testing.M) {
func TestBleveSearchIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
setting.CfgProvider = ini.Empty()
setting.CfgProvider = setting.NewEmptyConfigProvider()
tmpIndexerDir := t.TempDir()
+5 -2
View File
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
)
// DBIndexer implements Indexer interface to use database's like search
@@ -46,7 +47,7 @@ func (db *DBIndexer) Index(id int64) error {
// Get latest commit for default branch
commitID, err := gitRepo.GetBranchCommitID(repo.DefaultBranch)
if err != nil {
if git.IsErrBranchNotExist(err) || git.IsErrNotExist(err) {
if git.IsErrBranchNotExist(err) || git.IsErrNotExist(err) || setting.IsInTesting {
log.Debug("Unable to get commit ID for default branch %s in %s ... skipping this repository", repo.DefaultBranch, repo.RepoPath())
return nil
}
@@ -62,7 +63,9 @@ func (db *DBIndexer) Index(id int64) error {
// Calculate and save language statistics to database
stats, err := gitRepo.GetLanguageStats(commitID)
if err != nil {
log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err)
if !setting.IsInTesting {
log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err)
}
return err
}
err = repo_model.UpdateLanguageStats(repo, commitID, stats)
+1 -2
View File
@@ -18,7 +18,6 @@ import (
_ "code.gitea.io/gitea/models"
"github.com/stretchr/testify/assert"
"gopkg.in/ini.v1"
)
func TestMain(m *testing.M) {
@@ -29,7 +28,7 @@ func TestMain(m *testing.M) {
func TestRepoStatsIndex(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
setting.CfgProvider = ini.Empty()
setting.CfgProvider = setting.NewEmptyConfigProvider()
setting.LoadQueueSettings()
+4 -1
View File
@@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
)
// statsQueue represents a queue to handle repository stats updates
@@ -20,7 +21,9 @@ func handle(data ...queue.Data) []queue.Data {
for _, datum := range data {
opts := datum.(int64)
if err := indexer.Index(opts); err != nil {
log.Error("stats queue indexer.Index(%d) failed: %v", opts, err)
if !setting.IsInTesting {
log.Error("stats queue indexer.Index(%d) failed: %v", opts, err)
}
}
}
return nil
+2 -2
View File
@@ -162,7 +162,7 @@ func TestHTTPClientDownload(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "download", batchRequest.Operation)
assert.Equal(t, 1, len(batchRequest.Objects))
assert.Len(t, batchRequest.Objects, 1)
assert.Equal(t, p.Oid, batchRequest.Objects[0].Oid)
assert.Equal(t, p.Size, batchRequest.Objects[0].Size)
@@ -269,7 +269,7 @@ func TestHTTPClientUpload(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "upload", batchRequest.Operation)
assert.Equal(t, 1, len(batchRequest.Objects))
assert.Len(t, batchRequest.Objects, 1)
assert.Equal(t, p.Oid, batchRequest.Objects[0].Oid)
assert.Equal(t, p.Size, batchRequest.Objects[0].Size)
-71
View File
@@ -1,71 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package log
import (
"bytes"
"sync"
)
type bufferWriteCloser struct {
mu sync.Mutex
buffer bytes.Buffer
}
func (b *bufferWriteCloser) Write(p []byte) (int, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.buffer.Write(p)
}
func (b *bufferWriteCloser) Close() error {
return nil
}
func (b *bufferWriteCloser) String() string {
b.mu.Lock()
defer b.mu.Unlock()
return b.buffer.String()
}
// BufferLogger implements LoggerProvider and writes messages in a buffer.
type BufferLogger struct {
WriterLogger
}
// NewBufferLogger create BufferLogger returning as LoggerProvider.
func NewBufferLogger() LoggerProvider {
log := &BufferLogger{}
log.NewWriterLogger(&bufferWriteCloser{})
return log
}
// Init inits connection writer
func (log *BufferLogger) Init(string) error {
log.NewWriterLogger(log.out)
return nil
}
// Content returns the content accumulated in the content provider
func (log *BufferLogger) Content() (string, error) {
return log.out.(*bufferWriteCloser).String(), nil
}
// Flush when log should be flushed
func (log *BufferLogger) Flush() {
}
// ReleaseReopen does nothing
func (log *BufferLogger) ReleaseReopen() error {
return nil
}
// GetName returns the default name for this implementation
func (log *BufferLogger) GetName() string {
return "buffer"
}
func init() {
Register("buffer", NewBufferLogger)
}
-63
View File
@@ -1,63 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package log
import (
"fmt"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestBufferLogger(t *testing.T) {
logger := NewBufferLogger()
bufferLogger := logger.(*BufferLogger)
assert.NotNil(t, bufferLogger)
err := logger.Init("")
assert.NoError(t, err)
location, _ := time.LoadLocation("EST")
date := time.Date(2019, time.January, 13, 22, 3, 30, 15, location)
msg := "TEST MSG"
event := Event{
level: INFO,
msg: msg,
caller: "CALLER",
filename: "FULL/FILENAME",
line: 1,
time: date,
}
logger.LogEvent(&event)
content, err := bufferLogger.Content()
assert.NoError(t, err)
assert.Contains(t, content, msg)
logger.Close()
}
func TestBufferLoggerContent(t *testing.T) {
level := INFO
logger := NewLogger(0, "console", "console", fmt.Sprintf(`{"level":"%s"}`, level.String()))
logger.SetLogger("buffer", "buffer", "{}")
defer logger.DelLogger("buffer")
msg := "A UNIQUE MESSAGE"
Error(msg)
found := false
for i := 0; i < 30000; i++ {
content, err := logger.GetLoggerProviderContent("buffer")
assert.NoError(t, err)
if strings.Contains(content, msg) {
found = true
break
}
time.Sleep(1 * time.Millisecond)
}
assert.True(t, found)
}
-5
View File
@@ -118,11 +118,6 @@ func (log *ConnLogger) Init(jsonconfig string) error {
return nil
}
// Content returns the content accumulated in the content provider
func (log *ConnLogger) Content() (string, error) {
return "", fmt.Errorf("not supported")
}
// Flush does nothing for this implementation
func (log *ConnLogger) Flush() {
}
-5
View File
@@ -65,11 +65,6 @@ func (log *ConsoleLogger) Init(config string) error {
return nil
}
// Content returns the content accumulated in the content provider
func (log *ConsoleLogger) Content() (string, error) {
return "", fmt.Errorf("not supported")
}
// Flush when log should be flushed
func (log *ConsoleLogger) Flush() {
}
+8 -10
View File
@@ -82,7 +82,7 @@ func (l *ChannelledLog) Start() {
l.closeLogger()
return
}
l.loggerProvider.LogEvent(event)
l.loggerProvider.LogEvent(event) //nolint:errcheck
case _, ok := <-l.flush:
if !ok {
l.closeLogger()
@@ -119,7 +119,7 @@ func (l *ChannelledLog) emptyQueue() bool {
if !ok {
return false
}
l.loggerProvider.LogEvent(event)
l.loggerProvider.LogEvent(event) //nolint:errcheck
default:
return true
}
@@ -247,12 +247,6 @@ func (m *MultiChannelledLog) GetEventLogger(name string) EventLogger {
return m.loggers[name]
}
// GetEventProvider returns a sub logger provider content from this MultiChannelledLog
func (m *MultiChannelledLog) GetLoggerProviderContent(name string) (string, error) {
channelledLogger := m.GetEventLogger(name).(*ChannelledLog)
return channelledLogger.loggerProvider.Content()
}
// GetEventLoggerNames returns a list of names
func (m *MultiChannelledLog) GetEventLoggerNames() []string {
m.rwmutex.RLock()
@@ -351,7 +345,7 @@ func (m *MultiChannelledLog) Start() {
for _, logger := range m.loggers {
err := logger.LogEvent(event)
if err != nil {
fmt.Println(err)
fmt.Println(err) //nolint:forbidigo
}
}
m.rwmutex.RUnlock()
@@ -385,7 +379,7 @@ func (m *MultiChannelledLog) emptyQueue() bool {
for _, logger := range m.loggers {
err := logger.LogEvent(event)
if err != nil {
fmt.Println(err)
fmt.Println(err) //nolint:forbidigo
}
}
m.rwmutex.RUnlock()
@@ -460,3 +454,7 @@ func (m *MultiChannelledLog) ResetLevel() Level {
func (m *MultiChannelledLog) GetName() string {
return m.name
}
func (e *Event) GetMsg() string {
return e.msg
}
+2 -11
View File
@@ -181,7 +181,7 @@ func (log *FileLogger) DoRotate() error {
}
if log.Compress {
go compressOldLogFile(fname, log.CompressionLevel)
go compressOldLogFile(fname, log.CompressionLevel) //nolint:errcheck
}
// re-start logger
@@ -216,7 +216,7 @@ func compressOldLogFile(fname string, compressionLevel int) error {
if err != nil {
zw.Close()
fw.Close()
util.Remove(fname + ".gz")
util.Remove(fname + ".gz") //nolint:errcheck
return err
}
reader.Close()
@@ -253,15 +253,6 @@ func (log *FileLogger) deleteOldLog() {
})
}
// Content returns the content accumulated in the content provider
func (log *FileLogger) Content() (string, error) {
b, err := os.ReadFile(log.Filename)
if err != nil {
return "", err
}
return string(b), nil
}
// Flush flush file logger.
// there are no buffering messages in file logger in memory.
// flush file means sync file from disk.
+1 -1
View File
@@ -51,7 +51,7 @@ func TestFileLogger(t *testing.T) {
fileLogger := NewFileLogger()
realFileLogger, ok := fileLogger.(*FileLogger)
assert.Equal(t, true, ok)
assert.True(t, ok)
location, _ := time.LoadLocation("EST")
+2 -2
View File
@@ -245,7 +245,7 @@ func Close() {
func Log(skip int, level Level, format string, v ...interface{}) {
l, ok := NamedLoggers.Load(DEFAULT)
if ok {
l.Log(skip+1, level, format, v...)
l.Log(skip+1, level, format, v...) //nolint:errcheck
}
}
@@ -273,7 +273,7 @@ func (l *LoggerAsWriter) Write(p []byte) (int, error) {
for _, logger := range l.ourLoggers {
// Skip = 3 because this presumes that we have been called by log.Println()
// If the caller has used log.Output or the like this will be wrong
logger.Log(3, l.level, string(p))
logger.Log(3, l.level, string(p)) //nolint:errcheck
}
return len(p), nil
}
+10 -10
View File
@@ -53,7 +53,7 @@ type LevelLoggerLogger struct {
// Trace records trace log
func (l *LevelLoggerLogger) Trace(format string, v ...interface{}) {
l.Log(1, TRACE, format, v...)
l.Log(1, TRACE, format, v...) //nolint:errcheck
}
// IsTrace returns true if the logger is TRACE
@@ -63,7 +63,7 @@ func (l *LevelLoggerLogger) IsTrace() bool {
// Debug records debug log
func (l *LevelLoggerLogger) Debug(format string, v ...interface{}) {
l.Log(1, DEBUG, format, v...)
l.Log(1, DEBUG, format, v...) //nolint:errcheck
}
// IsDebug returns true if the logger is DEBUG
@@ -73,7 +73,7 @@ func (l *LevelLoggerLogger) IsDebug() bool {
// Info records information log
func (l *LevelLoggerLogger) Info(format string, v ...interface{}) {
l.Log(1, INFO, format, v...)
l.Log(1, INFO, format, v...) //nolint:errcheck
}
// IsInfo returns true if the logger is INFO
@@ -83,7 +83,7 @@ func (l *LevelLoggerLogger) IsInfo() bool {
// Warn records warning log
func (l *LevelLoggerLogger) Warn(format string, v ...interface{}) {
l.Log(1, WARN, format, v...)
l.Log(1, WARN, format, v...) //nolint:errcheck
}
// IsWarn returns true if the logger is WARN
@@ -93,12 +93,12 @@ func (l *LevelLoggerLogger) IsWarn() bool {
// Error records error log
func (l *LevelLoggerLogger) Error(format string, v ...interface{}) {
l.Log(1, ERROR, format, v...)
l.Log(1, ERROR, format, v...) //nolint:errcheck
}
// ErrorWithSkip records error log from "skip" calls back from this function
func (l *LevelLoggerLogger) ErrorWithSkip(skip int, format string, v ...interface{}) {
l.Log(skip+1, ERROR, format, v...)
l.Log(skip+1, ERROR, format, v...) //nolint:errcheck
}
// IsError returns true if the logger is ERROR
@@ -108,12 +108,12 @@ func (l *LevelLoggerLogger) IsError() bool {
// Critical records critical log
func (l *LevelLoggerLogger) Critical(format string, v ...interface{}) {
l.Log(1, CRITICAL, format, v...)
l.Log(1, CRITICAL, format, v...) //nolint:errcheck
}
// CriticalWithSkip records critical log from "skip" calls back from this function
func (l *LevelLoggerLogger) CriticalWithSkip(skip int, format string, v ...interface{}) {
l.Log(skip+1, CRITICAL, format, v...)
l.Log(skip+1, CRITICAL, format, v...) //nolint:errcheck
}
// IsCritical returns true if the logger is CRITICAL
@@ -123,14 +123,14 @@ func (l *LevelLoggerLogger) IsCritical() bool {
// Fatal records fatal log and exit the process
func (l *LevelLoggerLogger) Fatal(format string, v ...interface{}) {
l.Log(1, FATAL, format, v...)
l.Log(1, FATAL, format, v...) //nolint:errcheck
l.Close()
os.Exit(1)
}
// FatalWithSkip records fatal log from "skip" calls back from this function and exits the process
func (l *LevelLoggerLogger) FatalWithSkip(skip int, format string, v ...interface{}) {
l.Log(skip+1, FATAL, format, v...)
l.Log(skip+1, FATAL, format, v...) //nolint:errcheck
l.Close()
os.Exit(1)
}
+1 -1
View File
@@ -99,6 +99,6 @@ func (l *MultiChannelledLogger) SendLog(level Level, caller, filename string, li
time: time.Now(),
stacktrace: stack,
}
l.LogEvent(event)
l.LogEvent(event) //nolint:errcheck
return nil
}
-1
View File
@@ -6,7 +6,6 @@ package log
// LoggerProvider represents behaviors of a logger provider.
type LoggerProvider interface {
Init(config string) error
Content() (string, error)
EventLogger
}
-5
View File
@@ -95,11 +95,6 @@ func (log *SMTPLogger) sendMail(p []byte) (int, error) {
)
}
// Content returns the content accumulated in the content provider
func (log *SMTPLogger) Content() (string, error) {
return "", fmt.Errorf("not supported")
}
// Flush when log should be flushed
func (log *SMTPLogger) Flush() {
}
+2 -2
View File
@@ -202,7 +202,7 @@ func (logger *WriterLogger) createMsg(buf *[]byte, event *Event) {
(&protectedANSIWriter{
w: &baw,
mode: pawMode,
}).Write(msg)
}).Write(msg) //nolint:errcheck
*buf = baw
if event.stacktrace != "" && logger.StacktraceLevel <= event.level {
@@ -249,7 +249,7 @@ func (logger *WriterLogger) Match(event *Event) bool {
(&protectedANSIWriter{
w: &baw,
mode: removeColor,
}).Write([]byte(event.msg))
}).Write([]byte(event.msg)) //nolint:errcheck
msg = baw
return logger.regexp.Match(msg)
}
+1 -1
View File
@@ -593,5 +593,5 @@ func TestIssue18471(t *testing.T) {
}, strings.NewReader(data), &res)
assert.NoError(t, err)
assert.Equal(t, res.String(), "<a href=\"http://domain/org/repo/compare/783b039...da951ce\" class=\"compare\"><code class=\"nohighlight\">783b039...da951ce</code></a>")
assert.Equal(t, "<a href=\"http://domain/org/repo/compare/783b039...da951ce\" class=\"compare\"><code class=\"nohighlight\">783b039...da951ce</code></a>", res.String())
}
+1 -1
View File
@@ -33,7 +33,7 @@ func TestParseImageConfig(t *testing.T) {
assert.Equal(t, projectURL, metadata.ProjectURL)
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
assert.Equal(t, documentationURL, metadata.DocumentationURL)
assert.Equal(t, []string{"do it 1", "do it 2"}, metadata.ImageLayers)
assert.ElementsMatch(t, []string{"do it 1", "do it 2"}, metadata.ImageLayers)
assert.Equal(
t,
map[string]string{
+20 -20
View File
@@ -70,19 +70,19 @@ func TestPaginator(t *testing.T) {
t.Run("Generate pages", func(t *testing.T) {
p := New(0, 10, 1, 0)
pages := p.Pages()
assert.Equal(t, 0, len(pages))
assert.Empty(t, pages)
})
t.Run("Only current page", func(t *testing.T) {
p := New(0, 10, 1, 1)
pages := p.Pages()
assert.Equal(t, 1, len(pages))
assert.Len(t, pages, 1)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
p = New(1, 10, 1, 1)
pages = p.Pages()
assert.Equal(t, 1, len(pages))
assert.Len(t, pages, 1)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
})
@@ -90,13 +90,13 @@ func TestPaginator(t *testing.T) {
t.Run("Total page number is less or equal", func(t *testing.T) {
p := New(1, 10, 1, 2)
pages := p.Pages()
assert.Equal(t, 1, len(pages))
assert.Len(t, pages, 1)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
p = New(11, 10, 1, 2)
pages = p.Pages()
assert.Equal(t, 2, len(pages))
assert.Len(t, pages, 2)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -104,7 +104,7 @@ func TestPaginator(t *testing.T) {
p = New(11, 10, 2, 2)
pages = p.Pages()
assert.Equal(t, 2, len(pages))
assert.Len(t, pages, 2)
assert.Equal(t, 1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -112,7 +112,7 @@ func TestPaginator(t *testing.T) {
p = New(25, 10, 2, 3)
pages = p.Pages()
assert.Equal(t, 3, len(pages))
assert.Len(t, pages, 3)
assert.Equal(t, 1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -125,7 +125,7 @@ func TestPaginator(t *testing.T) {
// ... 2
p := New(11, 10, 2, 1)
pages := p.Pages()
assert.Equal(t, 2, len(pages))
assert.Len(t, pages, 2)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -134,7 +134,7 @@ func TestPaginator(t *testing.T) {
// ... 2 3
p = New(21, 10, 2, 2)
pages = p.Pages()
assert.Equal(t, 3, len(pages))
assert.Len(t, pages, 3)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -145,7 +145,7 @@ func TestPaginator(t *testing.T) {
// ... 2 3 4
p = New(31, 10, 3, 3)
pages = p.Pages()
assert.Equal(t, 4, len(pages))
assert.Len(t, pages, 4)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -158,7 +158,7 @@ func TestPaginator(t *testing.T) {
// ... 3 4 5
p = New(41, 10, 4, 3)
pages = p.Pages()
assert.Equal(t, 4, len(pages))
assert.Len(t, pages, 4)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 3, pages[1].Num())
@@ -171,7 +171,7 @@ func TestPaginator(t *testing.T) {
// ... 4 5 6 7 8 9 10
p = New(100, 10, 9, 7)
pages = p.Pages()
assert.Equal(t, 8, len(pages))
assert.Len(t, pages, 8)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 4, pages[1].Num())
@@ -194,7 +194,7 @@ func TestPaginator(t *testing.T) {
// 1 ...
p := New(21, 10, 1, 1)
pages := p.Pages()
assert.Equal(t, 2, len(pages))
assert.Len(t, pages, 2)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
assert.Equal(t, -1, pages[1].Num())
@@ -203,7 +203,7 @@ func TestPaginator(t *testing.T) {
// 1 2 ...
p = New(21, 10, 1, 2)
pages = p.Pages()
assert.Equal(t, 3, len(pages))
assert.Len(t, pages, 3)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -214,7 +214,7 @@ func TestPaginator(t *testing.T) {
// 1 2 3 ...
p = New(31, 10, 2, 3)
pages = p.Pages()
assert.Equal(t, 4, len(pages))
assert.Len(t, pages, 4)
assert.Equal(t, 1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -227,7 +227,7 @@ func TestPaginator(t *testing.T) {
// 1 2 3 ...
p = New(41, 10, 2, 3)
pages = p.Pages()
assert.Equal(t, 4, len(pages))
assert.Len(t, pages, 4)
assert.Equal(t, 1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -240,7 +240,7 @@ func TestPaginator(t *testing.T) {
// 1 2 3 4 5 6 7 ...
p = New(100, 10, 1, 7)
pages = p.Pages()
assert.Equal(t, 8, len(pages))
assert.Len(t, pages, 8)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -261,7 +261,7 @@ func TestPaginator(t *testing.T) {
// 1 2 3 4 5 6 7 ...
p = New(100, 10, 2, 7)
pages = p.Pages()
assert.Equal(t, 8, len(pages))
assert.Len(t, pages, 8)
assert.Equal(t, 1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -284,7 +284,7 @@ func TestPaginator(t *testing.T) {
// ... 2 3 ...
p := New(35, 10, 2, 2)
pages := p.Pages()
assert.Equal(t, 4, len(pages))
assert.Len(t, pages, 4)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -297,7 +297,7 @@ func TestPaginator(t *testing.T) {
// ... 2 3 4 ...
p = New(49, 10, 3, 3)
pages = p.Pages()
assert.Equal(t, 5, len(pages))
assert.Len(t, pages, 5)
assert.Equal(t, -1, pages[0].Num())
assert.False(t, pages[0].IsCurrent())
assert.Equal(t, 2, pages[1].Num())
@@ -4,7 +4,6 @@
package queue
import (
"fmt"
"strconv"
"sync"
"testing"
@@ -17,7 +16,6 @@ import (
func TestPersistableChannelUniqueQueue(t *testing.T) {
tmpDir := t.TempDir()
fmt.Printf("TempDir %s\n", tmpDir)
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
// Common function to create the Queue
@@ -208,7 +206,7 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
mapLock.Lock()
assert.Equal(t, 101, len(executedInitial[name])+len(executedEmpty[name]))
assert.Equal(t, 0, len(hasEmpty[name]))
assert.Empty(t, hasEmpty[name])
mapLock.Unlock()
})
close(done)
+2 -2
View File
@@ -15,9 +15,9 @@ func TestEncryptDecrypt(t *testing.T) {
hex, _ = EncryptSecret("foo", "baz")
str, _ = DecryptSecret("foo", hex)
assert.Equal(t, str, "baz")
assert.Equal(t, "baz", str)
hex, _ = EncryptSecret("bar", "baz")
str, _ = DecryptSecret("foo", hex)
assert.NotEqual(t, str, "baz")
assert.NotEqual(t, "baz", str)
}
+141 -4
View File
@@ -4,20 +4,157 @@
package setting
import (
"fmt"
"os"
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
ini "gopkg.in/ini.v1"
)
type ConfigSection interface {
Name() string
MapTo(interface{}) error
HasKey(key string) bool
NewKey(name, value string) (*ini.Key, error)
Key(key string) *ini.Key
Keys() []*ini.Key
ChildSections() []*ini.Section
}
// ConfigProvider represents a config provider
type ConfigProvider interface {
Section(section string) *ini.Section
NewSection(name string) (*ini.Section, error)
GetSection(name string) (*ini.Section, error)
Section(section string) ConfigSection
NewSection(name string) (ConfigSection, error)
GetSection(name string) (ConfigSection, error)
DeleteSection(name string) error
Save() error
}
type iniFileConfigProvider struct {
*ini.File
filepath string // the ini file path
newFile bool // whether the file has not existed previously
allowEmpty bool // whether not finding configuration files is allowed (only true for the tests)
}
// NewEmptyConfigProvider create a new empty config provider
func NewEmptyConfigProvider() ConfigProvider {
cp, _ := newConfigProviderFromData("")
return cp
}
// newConfigProviderFromData this function is only for testing
func newConfigProviderFromData(configContent string) (ConfigProvider, error) {
var cfg *ini.File
var err error
if configContent == "" {
cfg = ini.Empty()
} else {
cfg, err = ini.Load(strings.NewReader(configContent))
if err != nil {
return nil, err
}
}
cfg.NameMapper = ini.SnackCase
return &iniFileConfigProvider{
File: cfg,
newFile: true,
}, nil
}
// newConfigProviderFromFile load configuration from file.
// NOTE: do not print any log except error.
func newConfigProviderFromFile(customConf string, allowEmpty bool, extraConfig string) (*iniFileConfigProvider, error) {
cfg := ini.Empty()
newFile := true
if customConf != "" {
isFile, err := util.IsFile(customConf)
if err != nil {
return nil, fmt.Errorf("unable to check if %s is a file. Error: %v", customConf, err)
}
if isFile {
if err := cfg.Append(customConf); err != nil {
return nil, fmt.Errorf("failed to load custom conf '%s': %v", customConf, err)
}
newFile = false
}
}
if newFile && !allowEmpty {
return nil, fmt.Errorf("unable to find configuration file: %q, please ensure you are running in the correct environment or set the correct configuration file with -c", CustomConf)
}
if extraConfig != "" {
if err := cfg.Append([]byte(extraConfig)); err != nil {
return nil, fmt.Errorf("unable to append more config: %v", err)
}
}
cfg.NameMapper = ini.SnackCase
return &iniFileConfigProvider{
File: cfg,
filepath: customConf,
newFile: newFile,
allowEmpty: allowEmpty,
}, nil
}
func (p *iniFileConfigProvider) Section(section string) ConfigSection {
return p.File.Section(section)
}
func (p *iniFileConfigProvider) NewSection(name string) (ConfigSection, error) {
return p.File.NewSection(name)
}
func (p *iniFileConfigProvider) GetSection(name string) (ConfigSection, error) {
return p.File.GetSection(name)
}
func (p *iniFileConfigProvider) DeleteSection(name string) error {
p.File.DeleteSection(name)
return nil
}
// Save save the content into file
func (p *iniFileConfigProvider) Save() error {
if p.filepath == "" {
if !p.allowEmpty {
return fmt.Errorf("custom config path must not be empty")
}
return nil
}
if p.newFile {
if err := os.MkdirAll(filepath.Dir(CustomConf), os.ModePerm); err != nil {
return fmt.Errorf("failed to create '%s': %v", CustomConf, err)
}
}
if err := p.SaveTo(p.filepath); err != nil {
return fmt.Errorf("failed to save '%s': %v", p.filepath, err)
}
// Change permissions to be more restrictive
fi, err := os.Stat(CustomConf)
if err != nil {
return fmt.Errorf("failed to determine current conf file permissions: %v", err)
}
if fi.Mode().Perm() > 0o600 {
if err = os.Chmod(CustomConf, 0o600); err != nil {
log.Warn("Failed changing conf file permissions to -rw-------. Consider changing them manually.")
}
}
return nil
}
// a file is an implementation ConfigProvider and other implementations are possible, i.e. from docker, k8s, …
var _ ConfigProvider = &ini.File{}
var _ ConfigProvider = &iniFileConfigProvider{}
func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting interface{}) {
if err := rootCfg.Section(sectionName).MapTo(setting); err != nil {
+3 -2
View File
@@ -21,9 +21,10 @@ var CORSConfig = struct {
Headers []string
XFrameOptions string
}{
Enabled: false,
MaxAge: 10 * time.Minute,
AllowDomain: []string{"*"},
Methods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
Headers: []string{"Content-Type", "User-Agent"},
MaxAge: 10 * time.Minute,
XFrameOptions: "SAMEORIGIN",
}
+4 -5
View File
@@ -7,7 +7,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
ini "gopkg.in/ini.v1"
)
func Test_getCronSettings(t *testing.T) {
@@ -23,11 +22,11 @@ func Test_getCronSettings(t *testing.T) {
iniStr := `
[cron.test]
Base = true
Second = white rabbit
Extend = true
BASE = true
SECOND = white rabbit
EXTEND = true
`
cfg, err := ini.Load([]byte(iniStr))
cfg, err := newConfigProviderFromData(iniStr)
assert.NoError(t, err)
extended := &Extended{
+6 -7
View File
@@ -9,8 +9,6 @@ import (
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
ini "gopkg.in/ini.v1"
)
// LFS represents the configuration for Git LFS
@@ -38,8 +36,7 @@ func loadLFSFrom(rootCfg ConfigProvider) {
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
// if these are removed, the warning will not be shown
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0")
lfsSec.Key("PATH").MustString(
sec.Key("LFS_CONTENT_PATH").String())
lfsSec.Key("PATH").MustString(sec.Key("LFS_CONTENT_PATH").String())
LFS.Storage = getStorage(rootCfg, "lfs", storageType, lfsSec)
@@ -62,9 +59,11 @@ func loadLFSFrom(rootCfg ConfigProvider) {
}
// Save secret
CreateOrAppendToCustomConf("server.LFS_JWT_SECRET", func(cfg *ini.File) {
cfg.Section("server").Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
})
sec.Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
if err := rootCfg.Save(); err != nil {
log.Fatal("Error saving JWT Secret for custom config: %v", err)
return
}
}
}
}

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