diff --git a/.air.toml b/.air.toml index d13f8c4f99..3740c4d4aa 100644 --- a/.air.toml +++ b/.air.toml @@ -2,12 +2,22 @@ root = "." tmp_dir = ".air" [build] +pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs cmd = "make --no-print-directory backend" bin = "gitea" -delay = 1000 +delay = 2000 include_ext = ["go", "tmpl"] 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_dir = [ + "models/fixtures", + "models/migrations/fixtures", + "modules/avatar/identicon/testdata", + "modules/avatar/testdata", + "modules/git/tests", + "modules/migration/file_format_testdata", + "routers/private/tests", + "services/gitdiff/testdata", +] exclude_regex = ["_test.go$", "_gen.go$"] stop_on_error = true diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a4a6ce8fcf..d391cf78cf 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "features": { // installs nodejs into container "ghcr.io/devcontainers/features/node:1": { - "version":"20" + "version": "20" }, "ghcr.io/devcontainers/features/git-lfs:1.1.0": {}, "ghcr.io/devcontainers-contrib/features/poetry:2": {}, @@ -24,7 +24,7 @@ "DavidAnson.vscode-markdownlint", "Vue.volar", "ms-azuretools.vscode-docker", - "zixuanchen.vitest-explorer", + "vitest.explorer", "qwtel.sqlite-viewer", "GitHub.vscode-pull-request-github" ] diff --git a/.dockerignore b/.dockerignore index 80cbeb040c..b696e1603c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -14,7 +14,7 @@ _test # MS VSCode .vscode -__debug_bin +__debug_bin* # Architecture specific extensions/prefixes *.[568vq] @@ -62,7 +62,6 @@ cpu.out /data /indexers /log -/public/img/avatar /tests/integration/gitea-integration-* /tests/integration/indexers-* /tests/e2e/gitea-e2e-* @@ -78,7 +77,7 @@ cpu.out /public/assets/js /public/assets/css /public/assets/fonts -/public/assets/img/webpack +/public/assets/img/avatar /vendor /web_src/fomantic/node_modules /web_src/fomantic/build/* @@ -96,6 +95,9 @@ cpu.out /.air /.go-licenses +# Files and folders that were previously generated +/public/assets/img/webpack + # Snapcraft snap/.snapcraft/ parts/ diff --git a/.eslintrc.yaml b/.eslintrc.yaml index e9991c02ba..cd5a0735b4 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -3,6 +3,7 @@ reportUnusedDisableDirectives: true ignorePatterns: - /web_src/js/vendor + - /web_src/fomantic parserOptions: sourceType: module @@ -42,10 +43,6 @@ overrides: worker: true rules: no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top] - - files: ["build/generate-images.js"] - rules: - i/no-unresolved: [0] - i/no-extraneous-dependencies: [0] - files: ["*.config.*"] rules: i/no-unused-modules: [0] @@ -123,7 +120,7 @@ rules: "@stylistic/js/arrow-spacing": [2, {before: true, after: true}] "@stylistic/js/block-spacing": [0] "@stylistic/js/brace-style": [2, 1tbs, {allowSingleLine: true}] - "@stylistic/js/comma-dangle": [2, only-multiline] + "@stylistic/js/comma-dangle": [2, always-multiline] "@stylistic/js/comma-spacing": [2, {before: false, after: true}] "@stylistic/js/comma-style": [2, last] "@stylistic/js/computed-property-spacing": [2, never] @@ -171,7 +168,7 @@ rules: "@stylistic/js/semi-spacing": [2, {before: false, after: true}] "@stylistic/js/semi-style": [2, last] "@stylistic/js/space-before-blocks": [2, always] - "@stylistic/js/space-before-function-paren": [0] + "@stylistic/js/space-before-function-paren": [2, {anonymous: ignore, named: never, asyncArrow: always}] "@stylistic/js/space-in-parens": [2, never] "@stylistic/js/space-infix-ops": [2] "@stylistic/js/space-unary-ops": [2] @@ -283,14 +280,14 @@ rules: i/unambiguous: [0] init-declarations: [0] jquery/no-ajax-events: [2] - jquery/no-ajax: [0] + jquery/no-ajax: [2] jquery/no-animate: [2] - jquery/no-attr: [0] + jquery/no-attr: [2] jquery/no-bind: [2] jquery/no-class: [0] jquery/no-clone: [2] jquery/no-closest: [0] - jquery/no-css: [0] + jquery/no-css: [2] jquery/no-data: [0] jquery/no-deferred: [2] jquery/no-delegate: [2] @@ -307,23 +304,23 @@ rules: jquery/no-in-array: [2] jquery/no-is-array: [2] jquery/no-is-function: [2] - jquery/no-is: [0] + jquery/no-is: [2] jquery/no-load: [2] jquery/no-map: [2] jquery/no-merge: [2] jquery/no-param: [2] jquery/no-parent: [0] - jquery/no-parents: [0] + jquery/no-parents: [2] jquery/no-parse-html: [2] - jquery/no-prop: [0] + jquery/no-prop: [2] jquery/no-proxy: [2] jquery/no-ready: [2] jquery/no-serialize: [2] jquery/no-show: [2] jquery/no-size: [2] - jquery/no-sizzle: [0] - jquery/no-slide: [0] - jquery/no-submit: [0] + jquery/no-sizzle: [2] + jquery/no-slide: [2] + jquery/no-submit: [2] jquery/no-text: [0] jquery/no-toggle: [2] jquery/no-trigger: [0] @@ -396,12 +393,12 @@ rules: no-irregular-whitespace: [2] no-iterator: [2] no-jquery/no-ajax-events: [2] - no-jquery/no-ajax: [0] + no-jquery/no-ajax: [2] 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-append-html: [2] + no-jquery/no-attr: [2] no-jquery/no-bind: [2] no-jquery/no-box-model: [2] no-jquery/no-browser: [2] @@ -413,7 +410,7 @@ rules: 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-css: [2] no-jquery/no-data: [0] no-jquery/no-deferred: [2] no-jquery/no-delegate: [2] @@ -444,7 +441,7 @@ rules: 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-is: [2] no-jquery/no-jquery-constructor: [0] no-jquery/no-live: [2] no-jquery/no-load-shorthand: [2] @@ -461,19 +458,19 @@ rules: no-jquery/no-other-utils: [2] no-jquery/no-param: [2] no-jquery/no-parent: [0] - no-jquery/no-parents: [0] + no-jquery/no-parents: [2] no-jquery/no-parse-html-literal: [0] no-jquery/no-parse-html: [2] no-jquery/no-parse-json: [2] no-jquery/no-parse-xml: [2] - no-jquery/no-prop: [0] + no-jquery/no-prop: [2] 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-sizzle: [2] no-jquery/no-slide: [2] no-jquery/no-sub: [2] no-jquery/no-support: [2] @@ -487,7 +484,7 @@ rules: no-jquery/no-visibility: [2] no-jquery/no-when: [2] no-jquery/no-wrap: [2] - no-jquery/variable-pattern: [0] + no-jquery/variable-pattern: [2] no-label-var: [2] no-labels: [0] # handled by no-restricted-syntax no-lone-blocks: [2] @@ -540,7 +537,7 @@ rules: no-underscore-dangle: [0] no-unexpected-multiline: [2] no-unmodified-loop-condition: [2] - no-unneeded-ternary: [0] + no-unneeded-ternary: [2] no-unreachable-loop: [2] no-unreachable: [2] no-unsafe-finally: [2] @@ -719,12 +716,14 @@ rules: unicorn/import-style: [0] unicorn/new-for-builtins: [2] unicorn/no-abusive-eslint-disable: [0] + unicorn/no-anonymous-default-export: [0] unicorn/no-array-callback-reference: [0] unicorn/no-array-for-each: [2] unicorn/no-array-method-this-argument: [2] unicorn/no-array-push-push: [2] unicorn/no-array-reduce: [2] unicorn/no-await-expression-member: [0] + unicorn/no-await-in-promise-methods: [2] unicorn/no-console-spaces: [0] unicorn/no-document-cookie: [2] unicorn/no-empty-file: [2] @@ -741,6 +740,7 @@ rules: unicorn/no-null: [0] unicorn/no-object-as-default-parameter: [0] unicorn/no-process-exit: [0] + unicorn/no-single-promise-in-promise-methods: [2] unicorn/no-static-only-class: [2] unicorn/no-thenable: [2] unicorn/no-this-assignment: [2] diff --git a/.gitattributes b/.gitattributes index 467b8a47b5..9fb4a4e83d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ * text=auto eol=lf *.tmpl linguist-language=Handlebars +*.pb.go linguist-generated /assets/*.json linguist-generated /public/assets/img/svg/*.svg linguist-generated /templates/swagger/v1_json.tmpl linguist-generated diff --git a/.github/labeler.yml b/.github/labeler.yml index 8a5ab26975..d1b4d00d80 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,36 +1,77 @@ modifies/docs: - - "**/*.md" - - "docs/**" - -modifies/frontend: - - "web_src/**/*" + - changed-files: + - any-glob-to-any-file: + - "**/*.md" + - "docs/**" modifies/templates: - - all: ["templates/**", "!templates/swagger/v1_json.tmpl"] + - changed-files: + - all-globs-to-any-file: + - "templates/**" + - "!templates/swagger/v1_json.tmpl" modifies/api: - - "routers/api/**" - - "templates/swagger/v1_json.tmpl" + - changed-files: + - any-glob-to-any-file: + - "routers/api/**" + - "templates/swagger/v1_json.tmpl" modifies/cli: - - "cmd/**" + - changed-files: + - any-glob-to-any-file: + - "cmd/**" modifies/translation: - - "options/locale/*.ini" + - changed-files: + - any-glob-to-any-file: + - "options/locale/*.ini" modifies/migrations: - - "models/migrations/**/*" + - changed-files: + - any-glob-to-any-file: + - "models/migrations/**" modifies/internal: - - "Makefile" - - "Dockerfile" - - "Dockerfile.rootless" - - "docker/**" - - "webpack.config.js" - - ".eslintrc.yaml" - - ".golangci.yml" - - ".markdownlint.yaml" - - ".spectral.yaml" - - ".stylelintrc.yaml" - - ".yamllint.yaml" - - ".github/**" + - changed-files: + - any-glob-to-any-file: + - ".air.toml" + - "Makefile" + - "Dockerfile" + - "Dockerfile.rootless" + - ".dockerignore" + - "docker/**" + - ".editorconfig" + - ".eslintrc.yaml" + - ".golangci.yml" + - ".gitpod.yml" + - ".markdownlint.yaml" + - ".spectral.yaml" + - "stylelint.config.js" + - ".yamllint.yaml" + - ".github/**" + - ".gitea/" + - ".devcontainer/**" + - "build.go" + - "build/**" + - "contrib/**" + +modifies/dependencies: + - changed-files: + - any-glob-to-any-file: + - "package.json" + - "package-lock.json" + - "pyproject.toml" + - "poetry.lock" + - "go.mod" + - "go.sum" + +modifies/go: + - changed-files: + - any-glob-to-any-file: + - "**/*.go" + +modifies/js: + - changed-files: + - any-glob-to-any-file: + - "**/*.js" + - "**/*.vue" diff --git a/.github/workflows/cron-lock.yml b/.github/workflows/cron-lock.yml deleted file mode 100644 index 665313135b..0000000000 --- a/.github/workflows/cron-lock.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: cron-lock - -on: - schedule: - - cron: "0 0 * * *" # every day at 00:00 UTC - workflow_dispatch: - -permissions: - issues: write - pull-requests: write - -concurrency: - group: lock - -jobs: - action: - runs-on: ubuntu-latest - if: github.repository == 'go-gitea/gitea' - steps: - - uses: dessant/lock-threads@v5 - with: - issue-inactive-days: 10 - pr-inactive-days: 7 diff --git a/.github/workflows/cron-translations.yml b/.github/workflows/cron-translations.yml index 390aae7c07..f1b51debf1 100644 --- a/.github/workflows/cron-translations.yml +++ b/.github/workflows/cron-translations.yml @@ -11,14 +11,19 @@ jobs: if: github.repository == 'go-gitea/gitea' steps: - uses: actions/checkout@v4 - - name: download from crowdin - uses: docker://jonasfranz/crowdin + - uses: crowdin/github-action@v1 + with: + upload_sources: true + upload_translations: false + download_sources: false + download_translations: true + push_translations: false + push_sources: false + create_pull_request: false + config: crowdin.yml env: + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} 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 @@ -31,19 +36,3 @@ jobs: 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 - if: github.repository == 'go-gitea/gitea' - steps: - - uses: actions/checkout@v4 - - name: push translations to crowdin - uses: docker://jonasfranz/crowdin - env: - CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }} - PLUGIN_UPLOAD: true - PLUGIN_EXPORT_DIR: options/locale/ - PLUGIN_IGNORE_BRANCH: true - PLUGIN_PROJECT_IDENTIFIER: gitea - PLUGIN_FILES: | - locale_en-US.ini: options/locale/locale_en-US.ini - PLUGIN_BRANCH: main diff --git a/.github/workflows/files-changed.yml b/.github/workflows/files-changed.yml index f9b6b1ec49..9a609e0551 100644 --- a/.github/workflows/files-changed.yml +++ b/.github/workflows/files-changed.yml @@ -58,7 +58,7 @@ jobs: - "package-lock.json" - "Makefile" - ".eslintrc.yaml" - - ".stylelintrc.yaml" + - "stylelint.config.js" - ".npmrc" docs: @@ -73,6 +73,7 @@ jobs: - "Makefile" templates: + - "tools/lint-templates-*.js" - "templates/**/*.tmpl" - "pyproject.toml" - "poetry.lock" diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml index 02a265b1ff..f89276fe82 100644 --- a/.github/workflows/pull-compliance.yml +++ b/.github/workflows/pull-compliance.yml @@ -35,8 +35,14 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: pip install poetry - run: make deps-py + - run: make deps-frontend - run: make lint-templates lint-yaml: @@ -61,6 +67,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend - run: make lint-swagger @@ -130,6 +138,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend - run: make lint-frontend - run: make checks-frontend @@ -177,6 +187,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend - run: make lint-md - run: make docs diff --git a/.github/workflows/pull-e2e-tests.yml b/.github/workflows/pull-e2e-tests.yml index 5a249db9f8..35ac7598f6 100644 --- a/.github/workflows/pull-e2e-tests.yml +++ b/.github/workflows/pull-e2e-tests.yml @@ -24,6 +24,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend frontend deps-backend - run: npx playwright install --with-deps - run: make test-e2e-sqlite diff --git a/.github/workflows/pull-labeler.yml b/.github/workflows/pull-labeler.yml index edd2f6d16e..812819b599 100644 --- a/.github/workflows/pull-labeler.yml +++ b/.github/workflows/pull-labeler.yml @@ -9,12 +9,12 @@ concurrency: cancel-in-progress: true jobs: - label: + labeler: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@v5 with: - dot: true + sync-labels: true diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 80e6683919..990f3c8e07 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -25,6 +25,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend deps-backend # xgo build - run: make release diff --git a/.github/workflows/release-tag-rc.yml b/.github/workflows/release-tag-rc.yml index 12d1e1e4be..55908d3657 100644 --- a/.github/workflows/release-tag-rc.yml +++ b/.github/workflows/release-tag-rc.yml @@ -24,6 +24,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend deps-backend # xgo build - run: make release diff --git a/.github/workflows/release-tag-version.yml b/.github/workflows/release-tag-version.yml index e0e93633e8..edf7ea1270 100644 --- a/.github/workflows/release-tag-version.yml +++ b/.github/workflows/release-tag-version.yml @@ -26,6 +26,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 + cache: npm + cache-dependency-path: package-lock.json - run: make deps-frontend deps-backend # xgo build - run: make release diff --git a/.gitignore b/.gitignore index 8f2544866a..46c8b9b49c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,7 @@ cpu.out /data /indexers /log -/public/img/avatar +/public/assets/img/avatar /tests/integration/gitea-integration-* /tests/integration/indexers-* /tests/e2e/gitea-e2e-* @@ -77,7 +77,6 @@ cpu.out /public/assets/css /public/assets/fonts /public/assets/licenses.txt -/public/assets/img/webpack /vendor /web_src/fomantic/node_modules /web_src/fomantic/build/* @@ -95,6 +94,9 @@ cpu.out /.air /.go-licenses +# Files and folders that were previously generated +/public/assets/img/webpack + # Snapcraft /gitea_a*.txt snap/.snapcraft/ diff --git a/.gitpod.yml b/.gitpod.yml index ed2f57f4bf..f573d55a76 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -42,7 +42,7 @@ vscode: - DavidAnson.vscode-markdownlint - Vue.volar - ms-azuretools.vscode-docker - - zixuanchen.vitest-explorer + - vitest.explorer - qwtel.sqlite-viewer - GitHub.vscode-pull-request-github diff --git a/.golangci.yml b/.golangci.yml index d6ce37f49a..238f6cb837 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,13 +1,14 @@ linters: + enable-all: false + disable-all: true + fast: false enable: - bidichk - # - deadcode # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - depguard - dupl - errcheck - forbidigo - gocritic - # - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time. - gofmt - gofumpt - gosimple @@ -17,23 +18,17 @@ linters: - nolintlint - revive - staticcheck - # - structcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - stylecheck - typecheck - unconvert - unused - # - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841 - wastedassign - enable-all: false - disable-all: true - fast: false run: timeout: 10m - skip-dirs: - - node_modules - - public - - web_src + +output: + sort-results: true linters-settings: stylecheck: @@ -51,27 +46,37 @@ linters-settings: errorCode: 1 warningCode: 1 rules: + - name: atomic + - name: bare-return - name: blank-imports + - name: constant-logical-expr - name: context-as-argument - name: context-keys-type - name: dot-imports + - name: duplicated-imports + - name: empty-lines + - name: error-naming - name: error-return - name: error-strings - - name: error-naming + - name: errorf - name: exported + - name: identical-branches - name: if-return - name: increment-decrement - - name: var-naming - - name: var-declaration + - name: indent-error-flow + - name: modifies-value-receiver - name: package-comments - name: range - name: receiver-naming + - name: redefines-builtin-id + - name: string-of-int + - name: superfluous-else - name: time-naming + - name: unconditional-recursion - name: unexported-return - - name: indent-error-flow - - name: errorf - - name: duplicated-imports - - name: modifies-value-receiver + - name: unreachable-code + - name: var-declaration + - name: var-naming gofumpt: extra-rules: true depguard: @@ -90,12 +95,15 @@ linters-settings: desc: do not use the internal package, use AddXxx function instead - pkg: gopkg.in/ini.v1 desc: do not use the ini package, use gitea's config system instead + - pkg: gitea.com/go-chi/cache + desc: do not use the go-chi cache package, use gitea's cache system issues: max-issues-per-linter: 0 max-same-issues: 0 + exclude-dirs: [node_modules, public, web_src] + exclude-case-sensitive: true exclude-rules: - # Exclude some linters from running on tests files. - path: _test\.go linters: - gocyclo @@ -113,19 +121,19 @@ issues: - path: cmd linters: - forbidigo - - linters: + - text: "webhook" + linters: - dupl - text: "webhook" - - linters: + - text: "`ID' should not be capitalized" + linters: - gocritic - text: "`ID' should not be capitalized" - - linters: + - text: "swagger" + linters: - unused - deadcode - text: "swagger" - - linters: + - text: "argument x is overwritten before first use" + linters: - staticcheck - text: "argument x is overwritten before first use" - text: "commentFormatting: put a space between `//` and comment text" linters: - gocritic diff --git a/.ignore b/.ignore index 5c945ab981..5b96dabd38 100644 --- a/.ignore +++ b/.ignore @@ -4,6 +4,8 @@ /modules/options/bindata.go /modules/public/bindata.go /modules/templates/bindata.go -/vendor +/options/gitignore +/options/license /public/assets +/vendor node_modules diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml deleted file mode 100644 index c7725159f1..0000000000 --- a/.stylelintrc.yaml +++ /dev/null @@ -1,222 +0,0 @@ -plugins: - - stylelint-declaration-strict-value - - stylelint-declaration-block-no-ignored-properties - - "@stylistic/stylelint-plugin" - -ignoreFiles: - - "**/*.go" - -overrides: - - files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"] - rules: - scale-unlimited/declaration-strict-value: null - - files: ["**/chroma/*", "**/codemirror/*"] - rules: - block-no-empty: null - - files: ["**/*.vue"] - customSyntax: postcss-html - -rules: - "@stylistic/at-rule-name-case": null - "@stylistic/at-rule-name-newline-after": null - "@stylistic/at-rule-name-space-after": null - "@stylistic/at-rule-semicolon-newline-after": null - "@stylistic/at-rule-semicolon-space-before": null - "@stylistic/block-closing-brace-empty-line-before": null - "@stylistic/block-closing-brace-newline-after": null - "@stylistic/block-closing-brace-newline-before": null - "@stylistic/block-closing-brace-space-after": null - "@stylistic/block-closing-brace-space-before": null - "@stylistic/block-opening-brace-newline-after": null - "@stylistic/block-opening-brace-newline-before": null - "@stylistic/block-opening-brace-space-after": null - "@stylistic/block-opening-brace-space-before": null - "@stylistic/color-hex-case": lower - "@stylistic/declaration-bang-space-after": never - "@stylistic/declaration-bang-space-before": null - "@stylistic/declaration-block-semicolon-newline-after": null - "@stylistic/declaration-block-semicolon-newline-before": null - "@stylistic/declaration-block-semicolon-space-after": null - "@stylistic/declaration-block-semicolon-space-before": never - "@stylistic/declaration-block-trailing-semicolon": null - "@stylistic/declaration-colon-newline-after": null - "@stylistic/declaration-colon-space-after": null - "@stylistic/declaration-colon-space-before": never - "@stylistic/function-comma-newline-after": null - "@stylistic/function-comma-newline-before": null - "@stylistic/function-comma-space-after": null - "@stylistic/function-comma-space-before": null - "@stylistic/function-max-empty-lines": 0 - "@stylistic/function-parentheses-newline-inside": never-multi-line - "@stylistic/function-parentheses-space-inside": null - "@stylistic/function-whitespace-after": null - "@stylistic/indentation": 2 - "@stylistic/linebreaks": null - "@stylistic/max-empty-lines": 1 - "@stylistic/max-line-length": null - "@stylistic/media-feature-colon-space-after": null - "@stylistic/media-feature-colon-space-before": never - "@stylistic/media-feature-name-case": null - "@stylistic/media-feature-parentheses-space-inside": null - "@stylistic/media-feature-range-operator-space-after": always - "@stylistic/media-feature-range-operator-space-before": always - "@stylistic/media-query-list-comma-newline-after": null - "@stylistic/media-query-list-comma-newline-before": null - "@stylistic/media-query-list-comma-space-after": null - "@stylistic/media-query-list-comma-space-before": null - "@stylistic/named-grid-areas-alignment": null - "@stylistic/no-empty-first-line": null - "@stylistic/no-eol-whitespace": true - "@stylistic/no-extra-semicolons": true - "@stylistic/no-missing-end-of-source-newline": null - "@stylistic/number-leading-zero": null - "@stylistic/number-no-trailing-zeros": null - "@stylistic/property-case": lower - "@stylistic/selector-attribute-brackets-space-inside": null - "@stylistic/selector-attribute-operator-space-after": null - "@stylistic/selector-attribute-operator-space-before": null - "@stylistic/selector-combinator-space-after": null - "@stylistic/selector-combinator-space-before": null - "@stylistic/selector-descendant-combinator-no-non-space": null - "@stylistic/selector-list-comma-newline-after": null - "@stylistic/selector-list-comma-newline-before": null - "@stylistic/selector-list-comma-space-after": always-single-line - "@stylistic/selector-list-comma-space-before": never-single-line - "@stylistic/selector-max-empty-lines": 0 - "@stylistic/selector-pseudo-class-case": lower - "@stylistic/selector-pseudo-class-parentheses-space-inside": never - "@stylistic/selector-pseudo-element-case": lower - "@stylistic/string-quotes": double - "@stylistic/unicode-bom": null - "@stylistic/unit-case": lower - "@stylistic/value-list-comma-newline-after": null - "@stylistic/value-list-comma-newline-before": null - "@stylistic/value-list-comma-space-after": null - "@stylistic/value-list-comma-space-before": null - "@stylistic/value-list-max-empty-lines": 0 - alpha-value-notation: null - annotation-no-unknown: true - at-rule-allowed-list: null - at-rule-disallowed-list: null - at-rule-empty-line-before: null - at-rule-no-unknown: [true, {ignoreAtRules: [tailwind]}] - at-rule-no-vendor-prefix: true - at-rule-property-required-list: null - block-no-empty: true - color-function-notation: null - color-hex-alpha: null - color-hex-length: null - color-named: null - color-no-hex: null - color-no-invalid-hex: true - comment-empty-line-before: null - comment-no-empty: true - comment-pattern: null - comment-whitespace-inside: null - comment-word-disallowed-list: null - custom-media-pattern: null - custom-property-empty-line-before: null - custom-property-no-missing-var-function: true - custom-property-pattern: null - declaration-block-no-duplicate-custom-properties: true - declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}] - declaration-block-no-redundant-longhand-properties: null - declaration-block-no-shorthand-property-overrides: null - declaration-block-single-line-max-declarations: null - declaration-empty-line-before: null - declaration-no-important: null - declaration-property-max-values: null - declaration-property-unit-allowed-list: null - declaration-property-unit-disallowed-list: {line-height: [em]} - declaration-property-value-allowed-list: null - declaration-property-value-disallowed-list: null - declaration-property-value-no-unknown: true - font-family-name-quotes: always-where-recommended - font-family-no-duplicate-names: true - font-family-no-missing-generic-family-keyword: true - font-weight-notation: null - function-allowed-list: null - function-calc-no-unspaced-operator: true - function-disallowed-list: null - function-linear-gradient-no-nonstandard-direction: true - function-name-case: lower - function-no-unknown: null - function-url-no-scheme-relative: null - function-url-quotes: always - function-url-scheme-allowed-list: null - function-url-scheme-disallowed-list: null - hue-degree-notation: null - import-notation: string - keyframe-block-no-duplicate-selectors: true - keyframe-declaration-no-important: true - keyframe-selector-notation: null - keyframes-name-pattern: null - length-zero-no-unit: [true, ignore: [custom-properties], ignoreFunctions: [var]] - max-nesting-depth: null - media-feature-name-allowed-list: null - media-feature-name-disallowed-list: null - media-feature-name-no-unknown: true - media-feature-name-no-vendor-prefix: true - media-feature-name-unit-allowed-list: null - media-feature-name-value-allowed-list: null - media-feature-name-value-no-unknown: true - media-feature-range-notation: null - media-query-no-invalid: true - named-grid-areas-no-invalid: true - no-descending-specificity: null - no-duplicate-at-import-rules: true - no-duplicate-selectors: true - no-empty-source: true - no-invalid-double-slash-comments: true - no-invalid-position-at-import-rule: null - no-irregular-whitespace: true - no-unknown-animations: null - no-unknown-custom-properties: null - number-max-precision: null - plugin/declaration-block-no-ignored-properties: true - property-allowed-list: null - property-disallowed-list: null - property-no-unknown: true - property-no-vendor-prefix: null - rule-empty-line-before: null - rule-selector-property-disallowed-list: null - scale-unlimited/declaration-strict-value: [[/color$/, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true, expandShorthand: true}] - selector-attribute-name-disallowed-list: null - selector-attribute-operator-allowed-list: null - selector-attribute-operator-disallowed-list: null - selector-attribute-quotes: always - selector-class-pattern: null - selector-combinator-allowed-list: null - selector-combinator-disallowed-list: null - selector-disallowed-list: null - selector-id-pattern: null - selector-max-attribute: null - selector-max-class: null - selector-max-combinators: null - selector-max-compound-selectors: null - selector-max-id: null - selector-max-pseudo-class: null - selector-max-specificity: null - selector-max-type: null - selector-max-universal: null - selector-nested-pattern: null - selector-no-qualifying-type: null - selector-no-vendor-prefix: true - selector-not-notation: null - selector-pseudo-class-allowed-list: null - selector-pseudo-class-disallowed-list: null - selector-pseudo-class-no-unknown: true - selector-pseudo-element-allowed-list: null - selector-pseudo-element-colon-notation: double - selector-pseudo-element-disallowed-list: null - selector-pseudo-element-no-unknown: true - selector-type-case: lower - selector-type-no-unknown: [true, {ignore: [custom-elements]}] - shorthand-property-no-redundant-values: true - string-no-newline: true - time-min-milliseconds: null - unit-allowed-list: null - unit-disallowed-list: null - unit-no-unknown: true - value-keyword-case: null - value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}] diff --git a/CHANGELOG-archived.md b/CHANGELOG-archived.md new file mode 100644 index 0000000000..e0551d39a6 --- /dev/null +++ b/CHANGELOG-archived.md @@ -0,0 +1,5223 @@ +# Changelog (archived) + +This changelog (archived) contains changes for old releases. + +* Recent changelogs: [CHANGELOG.md](CHANGELOG.md) +* Release blogs with highlights: [blog.gitea.com](https://blog.gitea.com). + +## [1.15.11](https://github.com/go-gitea/gitea/releases/tag/v1.15.11) - 2022-01-29 + +* SECURITY + * Only view milestones from current repo (#18414) (#18418) +* BUGFIXES + * Fix broken when no commits and default branch is not master (#18422) (#18424) + * Fix commit's time (#18375) (#18409) + * Fix restore without topic failure (#18387) (#18401) + * Fix mermaid import in 1.15 (it uses ESModule now) (#18382) + * Update to go/text 0.3.7 (#18336) +* MISC + * Upgrade EasyMDE to 2.16.1 (#18278) (#18279) + +## [1.15.10](https://github.com/go-gitea/gitea/releases/tag/v1.15.10) - 2022-01-14 + +* BUGFIXES + * Fix inconsistent PR comment counts (#18260) (#18261) + * Fix release link broken (#18252) (#18253) + * Fix update user from site administration page bug (#18250) (#18251) + * Set HeadCommit when creating tags (#18116) (#18173) + * Use correct translation key for error messages due to max repo limits (#18135 & #18153) (#18152) + * Fix purple color in suggested label colors (#18241) (#18242) +* SECURITY + * Bump mermaid from 8.10.1 to 8.13.8 (#18198) (#18206) + +## [1.15.9](https://github.com/go-gitea/gitea/releases/tag/v1.15.9) - 2021-12-30 + +* BUGFIXES + * Fix wrong redirect on org labels (#18128) (#18134) + * Fix: unstable sort skips/duplicates issues across pages (#18094) (#18095) + * Revert "Fix delete u2f keys bug (#18042)" (#18107) + * Migrating wiki don't require token, so we should move it out of the require form (#17645) (#18104) + * Prevent NPE if gitea uploader fails to open url (#18080) (#18101) + * Reset locale on login (#17734) (#18100) + * Correctly handle failed migrations (#17575) (#18099) + * Instead of using routerCtx just escape the url before routing (#18086) (#18098) + * Quote references to the user table in consistency checks (#18072) (#18073) + * Add NotFound handler (#18062) (#18067) + * Ensure that git repository is closed before transfer (#18049) (#18057) + * Use common sessioner for API and web routes (#18114) +* TRANSLATION + * Fix code search result hint on zh-CN (#18053) + +## [1.15.8](https://github.com/go-gitea/gitea/releases/tag/v1.15.8) - 2021-12-20 + +* BUGFIXES + * Move POST /{username}/action/{action} to simply POST /{username} (#18045) (#18046) + * Fix delete u2f keys bug (#18040) (#18042) + * Reset Session ID on login (#18018) (#18041) + * Prevent off-by-one error on comments on newly appended lines (#18029) (#18035) + * Stop printing 03d after escaped characters in logs (#18030) (#18034) + * Reset locale on login (#18023) (#18025) + * Fix reset password email template (#17025) (#18022) + * Fix outType on gitea dump (#18000) (#18016) + * Ensure complexity, minlength and isPwned are checked on password setting (#18005) (#18015) + * Fix rename notification bug (#18011) + * Prevent double decoding of % in url params (#17997) (#18001) + * Prevent hang in git cat-file if the repository is not a valid repository (Partial #17991) (#17992) + * Prevent deadlock in create issue (#17970) (#17982) +* TESTING + * Use non-expiring key. (#17984) (#17985) + +## [1.15.7](https://github.com/go-gitea/gitea/releases/tag/v1.15.7) - 2021-12-01 + +* ENHANCEMENTS + * Only allow webhook to send requests to allowed hosts (#17482) (#17510) + * Fix login redirection links (#17451) (#17473) +* BUGFIXES + * Fix database inconsistent when admin change user email (#17549) (#17840) + * Use correct user on releases (#17806) (#17818) + * Fix commit count in tag view (#17698) (#17790) + * Fix close issue but time watcher still running (#17643) (#17761) + * Fix Migrate Description (#17692) (#17727) + * Fix bug when project board get open issue number (#17703) (#17726) + * Return 400 but not 500 when request archive with wrong format (#17691) (#17700) + * Fix bug when read mysql database max lifetime (#17682) (#17690) + * Fix database deadlock when update issue labels (#17649) (#17665) + * Fix bug on detect issue/comment writer (#17592) + * Remove appSubUrl from pasted images (#17572) (#17588) + * Make `ParsePatch` more robust (#17573) (#17580) + * Fix stats upon searching issues (#17566) (#17578) + * Escape issue titles in comments list (#17555) (#17556) + * Fix zero created time bug on commit api (#17546) (#17547) + * Fix database keyword quote problem on migration v161 (#17522) (#17523) + * Fix email with + when active (#17518) (#17520) + * Stop double encoding blame commit messages (#17498) (#17500) + * Quote the table name in CountOrphanedObjects (#17487) (#17488) + * Run Migrate in Install rather than just SyncTables (#17475) (#17486) +* BUILD + * Fix golangci-lint warnings (#17598 et al) (#17668) +* MISC + * Preserve color when inverting emojis (#17797) (#17799) + +## [1.15.6](https://github.com/go-gitea/gitea/releases/tag/v1.15.6) - 2021-10-28 + +* BUGFIXES + * Prevent panic in serv.go with Deploy Keys (#17434) (#17435) + * Fix CSV render error (#17406) (#17431) + * Read expected buffer size (#17409) (#17430) + * Ensure that restricted users can access repos for which they are members (#17460) (#17464) + * Make commit-statuses popup show correctly (#17447) (#17466) +* TESTING + * Add integration tests for private.NoServCommand and private.ServCommand (#17456) (#17463) + +## [1.15.5](https://github.com/go-gitea/gitea/releases/tag/v1.15.5) - 2021-10-21 + +* SECURITY + * Upgrade Bluemonday to v1.0.16 (#17372) (#17374) + * Ensure correct SSH permissions check for private and restricted users (#17370) (#17373) +* BUGFIXES + * Prevent NPE in CSV diff rendering when column removed (#17018) (#17377) + * Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH (#17281) (#17376) + * Don't panic if we fail to parse U2FRegistration data (#17304) (#17371) + * Ensure popup text is aligned left (backport for 1.15) (#17343) + * Ensure that git daemon export ok is created for mirrors (#17243) (#17306) + * Disable core.protectNTFS (#17300) (#17302) + * Use pointer for wrappedConn methods (#17295) (#17296) + * AutoRegistration is supposed to be working with disabled registration (backport) (#17292) + * Handle duplicate keys on GPG key ring (#17242) (#17284) + * Fix SVG side by side comparison link (#17375) (#17391) + +## [1.15.4](https://github.com/go-gitea/gitea/releases/tag/v1.15.4) - 2021-10-08 + +* BUGFIXES + * Raw file API: don't try to interpret 40char filenames as commit SHA (#17185) (#17272) + * Don't allow merged PRs to be reopened (#17192) (#17271) + * Fix incorrect repository count on organization tab of dashboard (#17256) (#17266) + * Fix unwanted team review request deletion (#17257) (#17264) + * Fix broken Activities link in team dashboard (#17255) (#17258) + * API pull's head/base have correct permission(#17214) (#17245) + * Fix strange behavior of DownloadPullDiffOrPatch in incorrect index (#17223) (#17227) + * Upgrade xorm to v1.2.5 (#17177) (#17188) + * Fix missing repo link in issue/pull assigned emails (#17183) (#17184) + * Fix bug of get context user (#17169) (#17172) + * Nicely handle missing user in collaborations (#17049) (#17166) + * Add Horizontal scrollbar to inner menu on Chrome (#17086) (#17164) + * Fix wrong i18n keys (#17150) (#17153) + * Fix Archive Creation: correct transaction ending (#17151) + * Prevent panic in Org mode HighlightCodeBlock (#17140) (#17141) + * Create doctor command to fix repo_units broken by dumps from 1.14.3-1.14.6 (#17136) (#17137) +* ENHANCEMENT + * Check user instead of organization when creating a repo from a template via API (#16346) (#17195) +* TRANSLATION + * v1.15 fix Sprintf format 'verbs' in locale files (#17187) + +## [1.15.3](https://github.com/go-gitea/gitea/releases/tag/v1.15.3) - 2021-09-19 + +* ENHANCEMENTS + * Add fluid to ui container class to remove margin (#16396) (#16976) + * Add caller to cat-file batch calls (#17082) (#17089) +* BUGFIXES + * Render full plain readme. (#17083) (#17090) + * Upgrade xorm to v1.2.4 (#17059) + * Fix bug of migrate comments which only fetch one page (#17055) (#17058) + * Do not show issue context popup on external issues (#17050) (#17054) + * Decrement Fork Num when converting from Fork (#17035) (#17046) + * Correctly rollback in ForkRepository (#17034) (#17045) + * Fix missing close in WalkGitLog (#17008) (#17009) + * Add prefix to SVG id/class attributes (#16997) (#17000) + * Fix bug of migrated repository not index (#16991) (#16996) + * Skip AllowedUserVisibilityModes validation on update user if it is an organisation (#16988) (#16990) + * Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971) (#16977) + * Fix issue with issue default mail template (#16956) (#16975) + * Ensure that rebase conflicts are handled in updates (#16952) (#16960) + * Prevent panic on diff generation (#16950) (#16951) + +## [1.15.2](https://github.com/go-gitea/gitea/releases/tag/v1.15.2) - 2021-09-03 + +* BUGFIXES + * Add unique constraint back into issue_index (#16938) + * Close storage objects before cleaning (#16934) (#16942) + +## [1.15.1](https://github.com/go-gitea/gitea/releases/tag/v1.15.1) - 2021-09-02 + +* BUGFIXES + * Allow BASIC authentication access to /:owner/:repo/releases/download/* (#16916) (#16923) + * Prevent leave changes dialogs due to autofill fields (#16912) (#16920) + * Ignore review comment when ref commit is missed (#16905) (#16919) + * Fix wrong attachment removal (#16915) (#16917) + * Gitlab Migrator: dont ignore reactions of last request (#16903) (#16913) + * Correctly return the number of Repositories for Organizations (#16807) (#16911) + * Test if LFS object is accessible (#16865) (#16904) + * Fix git.Blob.DataAsync(): close pipe since we return a NopCloser (#16899) (#16900) + * Fix dump and restore repository (#16698) (#16898) + * Repare and Improve GetDiffRangeWithWhitespaceBehavior (#16894) (#16895) + * Fix wiki raw commit diff/patch view (#16891) (#16892) + * Ensure wiki repos are all closed (#16886) (#16888) + * List limited and private orgs if authenticated on API (#16866) (#16879) + * Simplify split diff view generation and remove JS dependency (#16775) (#16863) + * Ensure that the default visibility is set on the user create page (#16845) (#16862) + * In Render tolerate not being passed a context (#16842) (#16858) + * Upgrade xorm to v1.2.2 (#16663) & Add test to ensure that dumping of login sources remains correct (#16847) (#16848) + * Report the correct number of pushes on the feeds (#16811) (#16822) + * Add primary_key to issue_index (#16813) (#16820) + * Prevent NPE on empty commit (#16812) (#16819) + * Fix branch pagination error (#16805) (#16816) + * Add missing return to handleSettingRemoteAddrError (#16794) (#16795) + * Remove spurious / from issues.opened_by (#16793) + * Ensure that template compilation panics are sent to the logs (#16788) (#16792) + * Update caddyserver/certmagic (#16789) (#16790) + +## [1.15.0](https://github.com/go-gitea/gitea/releases/tag/v1.15.0) - 2021-08-21 + +* BREAKING + * Make app.ini permissions more restrictive (#16266) + * Refactor Webhook + Add X-Hub-Signature (#16176) + * Add asymmetric JWT signing (#16010) + * Clean-up the settings hierarchy for issue_indexer queue (#16001) + * Change default queue settings to be low go-routines (#15964) + * Improve assets handler middleware (#15961) + * Rename StaticUrlPrefix to AssetUrlPrefix (#15779) + * Use a generic markup class to display externally rendered files and diffs (#15735) + * Add frontend testing, require node 12 (#15315) + * Move (custom) assets into subpath `/assets` (#15219) + * Use level config in log section when sub log section not set level (#15176) + * Links in markdown should be absolute to the repository not the server (#15088) + * Upgrade to the latest version of golang-jwt (#16590) (#16606) + * Set minimum supported version of go to 1.16 (#16710) +* SECURITY + * Encrypt LDAP bind password in db with SECRET_KEY (#15547) + * Remove random password in Dockerfiles (#15362) + * Upgrade to the latest version of golang-jwt and increase minimum go to 1.15 (#16590) (#16606) + * Correctly create of git-daemon-export-ok files (#16508) (#16514) + * Don't show private user's repo in explore view (#16550) (#16554) + * Update node tar dependency to 6.1.6 (#16622) (#16623) +* FEATURES + * Update Go-Git to take advantage of LargeObjectThreshold (#16316) + * Support custom mime type mapping for text files (#16304) + * Link to previous blames in file blame page (#16259) + * Add LRU mem cache implementation (#16226) + * Localize Email Templates (#16200) + * Make command in authorized keys a template (#16003) + * Add possibility to make branch in branch page (#15960) + * Add email headers (#15939) + * Make tasklist checkboxes clickable (#15791) + * Add selecting tags on the compare page (#15723) + * Add cron job to delete old actions from database (#15688) + * On open repository open common cat file batch and batch-check (#15667) + * Add tag protection (#15629) + * Add push to remote mirror repository (#15157) + * Add Image Diff for SVG files (#14867) + * Add dashboard milestone search and repo milestone search by name. (#14866) + * Add LFS Migration and Mirror (#14726) + * Improve notifications for WIP draft PR's (#14663) + * Disable Stars config option (#14653) + * GPG Key Ownership verification with Signed Token (#14054) + * OAuth2 auto-register (#5123) +* API + * Return updated repository when changing repository using API (#16420) + * Let branch/tag name be a valid ref to get CI status (#16400) + * Add endpoint to get commits of PR (#16300) + * Allow COMMENT reviews to not specify a body (#16229) + * Add subject-type filter to list notification API endpoints (#16177) + * ListReleases add filter for draft and pre-releases (#16175) + * ListIssues add more filters (#16174) + * Issue Search Add filter for MilestoneNames (#16173) + * GET / SET User Settings (#16169) + * Expose repo.GetReviewers() & repo.GetAssignees() (#16168) + * User expose counters (#16167) + * Add repoGetTag (#16166) + * Add repoCreateTag (#16165) + * Creating a repo from a template repo via API (#15958) + * Add Active and ProhibitLogin to API (#15689) + * Add Location, Website and Description to API (#15675) + * Expose resolver via API (#15167) + * Swagger AccessToken fixes (#16574) (#16597) + * Set AllowedHeaders on API CORS handler (#16524) (#16618) +* ENHANCEMENTS + * Support HTTP/2 in Let's Encrypt (#16371) + * Introduce NotifySubjectType (#16320) + * Add forge emojies (#16296) + * Implemented head_commit for webhooks (#16282) + * Upgrade Gliderlabs SSH to 0.3.3 and add FailedConnectionCallback (#16278) + * Add previous/next buttons to review comments (#16273) + * Review comments: break-word for long file names (#16272) + * Add configuration to restrict allowed user visibility modes (#16271) + * Add scroll-margin-top to account for sticky header (#16269) + * Add --quiet and --verbose to gitea web to control initial logging (#16260) + * Use gitea logging module for git module (#16243) + * Add tests for all webhooks (#16214) + * Add button to delete undeleted repositories from failed migrations (#16197) + * Speed up git diff highlight generation (#16180) + * Add OpenID claims "profile" and "email". (#16141) + * Reintroduce squash merge default comment as a config setting (#16134) + * Add sanitizer rules per renderer (#16110) + * Improve performance of dashboard list orgs (#16099) + * Refactor assert statements in tests (#16089) + * Add sso.Group, context.Auth, context.APIAuth to allow auth special routes (#16086) + * Remove unnecessary goroutine (#16080) + * Add attachments for PR reviews (#16075) + * Make the github migration less rate limit waiting to get comment per page from repository but not per issue (#16070) + * Add Visible modes function from Organisation to Users too (#16069) + * Add checkbox to delete pull branch after successful merge (#16049) + * Make commit info cancelable (#16032) + * Make modules/context.Context a context.Context (#16031) + * Unified custom config creation (#16012) + * Make sshd_config more flexible regarding connections (#16009) + * Append to existing trailers in generated squash commit message (#15980) + * Always store primary email address into email_address table and also the state (#15956) + * Load issue/PR context popup data only when needed (#15955) + * Remove remaining fontawesome usage in templates (#15952) + * Remove fomantic accordion module (#15951) + * Small refactoring of modules/private (#15947) + * Double the avatar size factor (#15941) + * Add curl to rootless docker image (#15908) + * Replace clipboard.js with async clipboard api (#15899) + * Allow custom highlight mapping beyond file extensions (#15808) + * Add trace logging to SSO methods (#15803) + * Refactor routers directory (#15800) + * Allow only internal registration (#15795) + * Add a new internal hook to save ssh log (#15787) + * Respect default merge message syntax when parsing item references (#15772) + * OAuth2 login: Set account link to "login" as default behavior (#15768) + * Use single shared random string generation function (#15741) + * Hold the event source when there are no listeners (#15725) + * Code comments improvements (#15722) + * Provide OIDC compliant user info endpoint (#15721) + * Fix webkit calendar icon color on arc-green (#15713) + * Improve Light Chroma style (#15699) + * Only use boost workers for leveldb shadow queues (#15696) + * Add compare tag dropdown to releases page (#15695) + * Add caret styling CSS (#15651) + * Remove x-ua-compatible meta tag (#15640) + * Refactor of link creation (#15619) + * Add a new table issue_index to store the max issue index so that issue could be deleted with no duplicated index (#15599) + * Rewrite of the LFS server (#15523) + * Display more repository type on admin repository management (#15440) + * Remove usage of some JS globals (#15378) + * SHA in merged commit comment should be rendered ui sha (#15376) + * Add well-known config for OIDC (#15355) + * Use route rather than use thus reducing the number of stack frames (#15301) + * Code Formats, Nits & Unused Func/Var deletions (#15286) + * Let package git depend on setting but not opposite (#15241) + * Fixed sanitize errors (#15240) + * response simple text message for not html request when 404 (#15229) + * Remove file-loader dependency (#15196) + * Refactor renders (#15175) + * Add mimetype mapping settings (#15133) + * Add Status Updates whilst Gitea migrations are occurring (#15076) + * Reload locales in initialisation if needed by utilizing i18n.Reset (#15073) + * Counterwork seemingly unclickable repo button labels (#15064) + * Add DefaultMergeStyle option to repository (#14789) + * Added support for gopher URLs. (#14749) + * Rework repository archive (#14723) + * Add links to toggle WIP status (#14677) + * Add Tabular Diff for CSV files (#14661) + * Use milestone deadline when sorting issues (#14551) +* BUGFIXES + * Fix invalid params and typo of email templates (#16394) + * Fix activation of primary email addresses (#16385) + * Fix calculation for finalPage in repo-search component (#16382) + * Specify user in rootless container numerically (#16361) + * Detect encoding changes while parsing diff (#16330) + * Fix U2F error reasons always hidden (#16327) + * Prevent zombie processes (#16314) + * Escape reference to `user` table in models.SearchEmails (#16313) + * Fix default push instructions on empty repos (#16302) + * Fix modified files list in webhooks when there is a space (#16288) + * Fix webhook commits wrong hash on HEAD reset (#16283) + * Fuzzer finds an NPE due to incorrect URLPrefix (#16249) + * Don't WARN log UserNotExist errors on ExternalUserLogin failure (#16238) + * Do not show No match found for tribute (#16231) + * Fix "Copy Link" for pull requests (#16230) + * Fix diff expansion is missing final line in a file (#16222) + * Fix private repo permission problem (#16142) + * Fix not able to update local created non-urlencoded wiki pages (#16139) + * More efficiently parse shas for shaPostProcessor (#16101) + * Fix `doctor --run check-db-consistency --fix` with label fix (#16094) + * Prevent webhook action buttons from shifting (#16087) + * Change default TMPDIR path in rootless containers (#16077) + * Fix typo and add TODO notice (#16064) + * Use git log name-status in get last commit (#16059) + * Fix 500 Error with branch and tag sharing the same name (#16040) + * Fix get tag when migration (#16014) + * Add custom emoji support (#16004) + * Use filepath.ToSlash and Join in indexer defaults and queues (#15971) + * Add permission check for ``GenerateRepository`` (#15946) + * Ensure settings for Service and Mailer are read on the install page (#15943) + * Fix layout of milestone view (#15927) + * Unregister non-matching serviceworkers (#15834) + * Multiple Queue improvements: LevelDB Wait on empty, shutdown empty shadow level queue, reduce goroutines etc (#15693) + * Attachment support repository route (#15580) + * Fix missing icons and colorpicker when mounted on suburl (#15501) + * Create a session on ReverseProxy and ensure that ReverseProxy users cannot change username (#15304) + * Prevent double-login for Git HTTP and LFS and simplify login (#15303) + * Resolve Object { type: "error", data: undefined } in stopwatch.js (#15278) + * Fix heatmap activity (#15252) + * Remove vendored copy of fomantic-dropdown (#15193) + * Update repository size on cron gc task (#15177) + * Add NeedPostProcess for Parser interface to improve performance of csv parser and some external parser (#15153) + * Add code block highlight to orgmode back (#14222) + * Remove User.GetOrganizations() (#14032) + * Restore Accessibility for Dropdown (#16576) (#16617) + * Pass down SignedUserName down to AccessLogger context (#16605) (#16616) + * Fix table alignment in markdown (#16596) (#16602) + * Fix 500 on first wiki page (#16586) (#16598) + * Lock goth/gothic and Re-attempt OAuth2 registration on login if registration failed at startup (#16564) (#16570) + * Upgrade levelqueue to v0.4.0 (#16560) (#16561) + * Handle too long PR titles correctly (#16517) (#16549) + * Fix data race in bleve indexer (#16474) (#16509) + * Restore CORS on git smart http protocol (#16496) (#16506) + * Fix race in log (#16490) (#16505) + * Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498) + * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480) + * Update notification table with only latest data (#16445) (#16469) + * Fix crash following ldap authentication update (#16447) (#16448) + * Fix direct creation of external users on admin page (partial #16612) (#16613) + * Prevent 500 on draft releases without tag (#16634) (#16636) + * Restore creation of git-daemon-export-ok files (#16508) (#16514) + * Fix data race in bleve indexer (#16474) (#16509) + * Restore CORS on git smart http protocol (#16496) (#16506) + * Fix race in log (#16490) (#16505) + * Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498) + * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480) + * Update notification table with only latest data (#16445) (#16469) + * Fix crash following ldap authentication update (#16447) (#16448) + * Restore compatibility with SQLServer 2008 R2 in migrations (#16638) + * Fix direct creation of external users on admin page (#16613) + * Fix go-git implementation of GetNote when passed a non-existent commit (#16658) (#16659) + * Fix NPE in fuzzer (#16680) (#16682) + * Set issue_index when finishing migration (#16685) (#16687) + * Skip patch download when no patch file exists (#16356) (#16681) + * Ensure empty lines are copiable and final new line too (#16678) (#16692) + * Fix wrong user in OpenID response (#16736) (#16741) + * Do not use thin scrollbars on Firefox (#16738) (#16745) + * Recreate Tables should Recreate indexes on MySQL (#16718) (#16739) + * Keep attachments on tasklist update (#16750) (#16757) +* TESTING + * Bump `postgres` and `mysql` versions (#15710) + * Add tests for clone from wiki (#15513) + * Fix Benchmark tests, remove a broken one & add two new (#15250) + * Create Proper Migration tests (#15116) +* TRANSLATION + * Use a special name for update default branch on repository setting (#15893) + * Fix mirror_lfs source string in en-US locale (#15369) +* BUILD + * Upgrade xorm to v1.1.1 (#16339) + * Disable legal comments in esbuild (#15929) + * Switch to Node 16 to build fronted (#15804) + * Use esbuild to minify CSS (#15756) + * Use binary version of revive linter (#15739) + * Fix: npx webpack make: *** [Makefile:699: public/js/index.js] Error -… (#15465) + * Stop packaging node_modules in release tarballs (#15273) + * Introduce esbuild on webpack (#14578) +* DOCS + * Update queue workers documentation (#15999) + * Comment out app.example.ini (#15807) + * Improve logo customization docs (#15754) + * Add some response status on api docs (#15399) + * Rework Token API comments (#15162) + * Add better errors for disabled account recovery (#15117) +* MISC + * Remove utf8 option from installation page (#16126) + * Use Wants= over Requires= in systemd file (#15897) + +## [1.14.7](https://github.com/go-gitea/gitea/releases/tag/v1.14.7) - 2021-09-02 + +* BUGFIXES + * Add missing gitRepo close at GetDiffRangeWithWhitespaceBehavior (Partial #16894) (#16896) + * Fix wiki raw commit diff/patch view (#16891) (#16893) + * Ensure wiki repos are all closed (#16886) (#16889) + * Upgrade xorm to v1.2.2 (#16663) & Add test to ensure that dumping of login sources remains correct (#16847) (#16849) + * Recreate Tables should Recreate indexes on MySQL (#16718) (#16740) + +## [1.14.6](https://github.com/go-gitea/gitea/releases/tag/v1.14.6) - 2021-08-04 + +* SECURITY + * Bump github.com/markbates/goth from v1.67.1 to v1.68.0 (#16538) (#16540) + * Switch to maintained JWT lib (#16532) (#16535) + * Upgrade to latest version of golang-jwt (as forked for 1.14) (#16590) (#16607) +* BUGFIXES + * Add basic edit ldap auth test & actually fix #16252 (#16465) (#16495) + * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16481) + +## [1.14.5](https://github.com/go-gitea/gitea/releases/tag/v1.14.5) - 2021-07-16 + +* SECURITY + * Hide mirror passwords on repo settings page (#16022) (#16355) + * Update bluemonday to v1.0.15 (#16379) (#16380) +* BUGFIXES + * Retry rename on lock induced failures (#16435) (#16439) + * Validate issue index before querying DB (#16406) (#16410) + * Fix crash following ldap authentication update (#16447) (#16449) +* ENHANCEMENTS + * Redirect on bad CSRF instead of presenting bad page (#14937) (#16378) + +## [1.14.4](https://github.com/go-gitea/gitea/releases/tag/v1.14.4) - 2021-07-06 + +* BUGFIXES + * Fix relative links in postprocessed images (#16334) (#16340) + * Fix list_options GetStartEnd (#16303) (#16305) + * Fix API to use author for commits instead of committer (#16276) (#16277) + * Handle misencoding of login_source cfg in mssql (#16268) (#16275) + * Fixed issues not updated by commits (#16254) (#16261) + * Improve efficiency in FindRenderizableReferenceNumeric and getReference (#16251) (#16255) + * Use html.Parse rather than html.ParseFragment (#16223) (#16225) + * Fix milestone counters on new issue (#16183) (#16224) + * reqOrgMembership calls need to be preceded by reqToken (#16198) (#16219) + +## [1.14.3](https://github.com/go-gitea/gitea/releases/tag/v1.14.3) - 2021-06-18 + +* SECURITY + * Encrypt migration credentials at rest (#15895) (#16187) + * Only check access tokens if they are likely to be tokens (#16164) (#16171) + * Add missing SameSite settings for the i_like_gitea cookie (#16037) (#16039) + * Fix setting of SameSite on cookies (#15989) (#15991) +* API + * Repository object only count releases as releases (#16184) (#16190) + * EditOrg respect RepoAdminChangeTeamAccess option (#16184) (#16190) + * Fix overly strict edit pr permissions (#15900) (#16081) +* BUGFIXES + * Run processors on whole of text (#16155) (#16185) + * Class `issue-keyword` is being incorrectly stripped off spans (#16163) (#16172) + * Fix language switch for install page (#16043) (#16128) + * Fix bug on getIssueIDsByRepoID (#16119) (#16124) + * Set self-adjusting deadline for connection writing (#16068) (#16123) + * Fix http path bug (#16117) (#16120) + * Fix data URI scramble (#16098) (#16118) + * Merge all deleteBranch as one function and also fix bug when delete branch don't close related PRs (#16067) (#16097) + * git migration: don't prompt interactively for clone credentials (#15902) (#16082) + * Fix case change in ownernames (#16045) (#16050) + * Don't manipulate input params in email notification (#16011) (#16033) + * Remove branch URL before IssueRefURL (#15968) (#15970) + * Fix layout of milestone view (#15927) (#15940) + * GitHub Migration, migrate draft releases too (#15884) (#15888) + * Close the gitrepo when deleting the repository (#15876) (#15887) + * Upgrade xorm to v1.1.0 (#15869) (#15885) + * Fix blame row height alignment (#15863) (#15883) + * Fix error message when saving generated LOCAL_ROOT_URL config (#15880) (#15882) + * Backport Fix LFS commit finder not working (#15856) (#15874) + * Stop calling WriteHeader in Write (#15862) (#15873) + * Add timeout to writing to responses (#15831) (#15872) + * Return go-get info on subdirs (#15642) (#15871) + * Restore PAM user autocreation functionality (#15825) (#15867) + * Fix truncate utf8 string (#15828) (#15854) + * Fix bound address/port for caddy's certmagic library (#15758) (#15848) + * Upgrade unrolled/render to v1.1.1 (#15845) (#15846) + * Queue manager FlushAll can loop rapidly - add delay (#15733) (#15840) + * Tagger can be empty, as can Commit and Author - tolerate this (#15835) (#15839) + * Set autocomplete off on branches selector (#15809) (#15833) + * Add missing error to Doctor log (#15813) (#15824) + * Move restore repo to internal router and invoke from command to avoid open the same db file or queues files (#15790) (#15816) +* ENHANCEMENTS + * Removable media support to snap package (#16136) (#16138) + * Move sans-serif fallback font higher than emoji fonts (#15855) (#15892) +* DOCKER + * Only write config in environment-to-ini if there are changes (#15861) (#15868) + * Only offer hostcertificates if they exist (#15849) (#15853) + +## [1.14.2](https://github.com/go-gitea/gitea/releases/tag/v1.14.2) - 2021-05-09 + +* API + * Make change repo settings work on empty repos (#15778) (#15789) + * Add pull "merged" notification subject status to API (#15344) (#15654) +* BUGFIXES + * Ensure that ctx.Written is checked after issues(...) calls (#15797) (#15798) + * Use pulls in commit graph unless pulls are disabled (#15734 & #15740 & #15774) (#15775) + * Set GIT_DIR correctly if it is not set (#15751) (#15769) + * Fix bug where repositories appear unadopted (#15757) (#15767) + * Not show `ref-in-new-issue` pop when issue was disabled (#15761) (#15765) + * Drop back to use IsAnInteractiveSession for SVC (#15749) (#15762) + * Fix setting version table in dump (#15753) (#15759) + * Fix close button change on delete in simplemde area (#15737) (#15747) + * Defer closing the gitrepo until the end of the wrapped context functions (#15653) (#15746) + * Fix some ui bug about draft release (#15137) (#15745) + * Only log Error on getLastCommitStatus error to let pull list still be visible (#15716) (#15715) + * Move tooltip down to allow selection of Remove File on error (#15672) (#15714) + * Fix setting redis db path (#15698) (#15708) + * Fix DB session cleanup (#15697) (#15700) + * Fixed several activation bugs (#15473) (#15685) + * Delete references if repository gets deleted (#15681) (#15684) + * Fix orphaned objects deletion bug (#15657) (#15683) + * Delete protected branch if repository gets removed (#15658) (#15676) + * Remove spurious set name from eventsource.sharedworker.js (#15643) (#15652) + * Not update updated uinx for `git gc` (#15637) (#15641) + * Fix commit graph author link (#15627) (#15630) + * Fix webhook timeout bug (#15613) (#15621) + * Resolve panic on failed interface conversion in migration v156 (#15604) (#15610) + * Fix missing storage init (#15589) (#15598) + * If the default branch is not present do not report error on stats indexing (#15546 & #15583) (#15594) + * Fix lfs management find (#15537) (#15578) + * Fix NPE on view commit with notes (#15561) (#15573) + * Fix bug on commit graph (#15517) (#15530) + * Send size to /avatars if requested (#15459) (#15528) + * Prevent migration 156 failure if tag commit missing (#15519) (#15527) +* ENHANCEMENTS + * Display conflict-free merge messages for pull requests (#15773) (#15796) + * Exponential Backoff for ByteFIFO (#15724) (#15793) + * Issue list alignment tweaks (#15483) (#15766) + * Implement delete release attachments and update release attachments' name (#14130) (#15666) + * Add placeholder text to deploy key textarea (#15575) (#15576) + * Project board improvements (#15429) (#15560) + * Repo branch page: label size, PR ref, new PR button alignment (#15363) (#15365) +* MISC + * Fix webkit calendar icon color on arc-green (#15713) (#15728) + * Performance improvement for last commit cache and show-ref (#15455) (#15701) + * Bump unrolled/render to v1.1.0 (#15581) (#15608) + * Add ETag header (#15370) (#15552) + +## [1.14.1](https://github.com/go-gitea/gitea/releases/tag/v1.14.1) - 2021-04-15 + +* BUGFIXES + * Fix bug clone wiki (#15499) (#15502) + * Github Migration ignore rate limit, if not enabled (#15490) (#15495) + * Use subdir for URL (#15446) (#15493) + * Query the DB for the hash before inserting in to email_hash (#15457) (#15491) + * Ensure review dismissal only dismisses the correct review (#15477) (#15489) + * Use index of the supported tags to choose user lang (#15452) (#15488) + * Fix wrong file link in code search page (#15466) (#15486) + * Quick template fix for built-in SSH server in admin config (#15464) (#15481) + * Prevent superfluous response.WriteHeader (#15456) (#15476) + * Fix ambiguous argument error on tags (#15432) (#15474) + * Add created_unix instead of expiry to migration (#15458) (#15463) + * Fix repository search (#15428) (#15442) + * Prevent NPE on avatar direct rendering if federated avatars disabled (#15434) (#15439) + * Fix wiki clone urls (#15430) (#15431) + * Fix dingtalk icon url at webhook (#15417) (#15426) + * Standardise icon on projects PR page (#15387) (#15408) +* ENHANCEMENTS + * Add option to skip LFS/attachment files for `dump` (#15407) (#15492) + * Clone panel fixes (#15436) + * Use semantic dropdown for code search query type (#15276) (#15364) +* BUILD + * Build go-git variants for windows (#15482) (#15487) + * Lock down build-images dependencies (Partial #15479) (#15480) +* MISC + * Performance improvement for list pull requests (#15447) (#15500) + * Fix potential copy lfs records failure when fork a repository (#15441) (#15485) + +## [1.14.0](https://github.com/go-gitea/gitea/releases/tag/v1.14.0) - 2021-04-11 + +* SECURITY + * Respect approved email domain list for externally validated user registration (#15014) + * Add reverse proxy configuration support for remote IP address detection (#14959) + * Ensure validation occurs on clone addresses too (#14994) + * Fix several render issues highlighted during fuzzing (#14986) +* BREAKING + * Fix double 'push tag' action feed (#15078) (#15083) + * Remove possible resource leak (#15067) (#15082) + * Handle unauthorized user events gracefully (#15071) (#15074) + * Restore Access.log following migration to Chi framework (Stops access logging of /api/internal routes) (#14475) + * Migrate from Macaron to Chi framework (#14293) + * Deprecate building for mips (#14174) + * Consolidate Logos and update README header (#14136) + * Inline manifest.json (#14038) + * Store repository data in data path if not previously set (#13991) + * Rename "gitea" png to "logo" (#13974) + * Standardise logging of failed authentication attempts in internal SSH (#13962) + * Add markdown support in organization description (#13549) + * Improve users management through the CLI (#6001) (#10492) +* FEATURES + * Create a new issue with reference to lines of code from file view (#14863) + * Repository transfer has to be confirmed, if user can not create repo for new owner (#14792) + * Allow blocking some email domains from registering an account (#14667) + * Create a new issue based on reference to an issue comment (#14366) + * Add support to migrate from gogs (#14342) + * Add pager to the branches page (#14202) + * Minimal OpenID Connect implementation (#14139) + * Display current stopwatch in navbar (#14122) + * Display SVG files as images instead of text (#14101) + * Disable SSH key deletion of externally managed Keys (#13985) + * Add support for ed25519_sk and ecdsa_sk SSH keys (#13462) + * Add support for Mastodon OAuth2 provider (#13293) + * Add gitea sendmail command (#13079) + * Create DB session provider(based on xorm) (#13031) + * Add dismiss review feature (#12674) + * Make manual merge autodetection optional and add manual merge as merge method (#12543) + * Dump github/gitlab/gitea repository data to a local directory and restore to gitea (#12244) + * Create Rootless Docker image (#10154) +* API + * Speedup issue search (#15179) (#15192) + * Get pull, return head branch sha, even if deleted (#14931) + * Export LFS & TimeTracking function status (#14753) + * Show Gitea version in swagger (#14654) + * Fix PATCH /repos/{owner}/{repo} panic (#14637) + * Add Restricted Field to User (#14630) + * Add support for ref parameter to get raw file API (#14602) + * Add affected files of commits to commit struct (#14579) + * Fix CJK fonts again and misc. font issues (#14575) + * Add delete release by tag & delete tag (#14563) & (#13358) + * Add pagination to ListBranches (#14524) + * Add signoff option in commit form (#14516) + * GetRelease by tag only return release (#14397) + * Add MirrorInterval to the API (#14163) + * Make BasicAuth Prefix case insensitive (#14106) + * Add user filter to issueTrackedTimes, enable usage for issue managers (#14081) + * Add ref to create/edit issue options & deprecated assignee (#13992) + * Add Ref to Issue (#13946) + * Expose default theme in meta and API (#13809) + * Send error message when CSRF token is missing (#13676) + * List, Check, Add & delete endpoints for repository teams (#13630) + * Admin EditUser: Make FullName, Email, Website & Location optional (#13562) + * Add more filters to issues search (#13514) + * Add review request api (#11355) +* BUGFIXES + * Fix delete nonexist oauth application 500 and prevent deadlock (#15384) (#15396) + * Always set the merge base used to merge the commit (#15352) (#15385) + * Upgrade to bluemonday 1.0.7 (#15379) (#15380) + * Turn RepoRef and RepoAssignment back into func(*Context) (#15372) (#15377) + * Move FCGI req.URL.Path fix-up to the FCGI listener (#15292) (#15361) + * Show diff on rename with diff changes (#15338) (#15339) + * Fix handling of logout event (#15323) (#15337) + * Fix CanCreateRepo check (#15311) (#15321) + * Fix xorm log stack level (#15285) (#15316) + * Fix bug in Wrap (#15302) (#15309) + * Drop the event source if we are unauthorized (#15275) (#15280) + * Backport Fix graph pagination (#15225) (#15249) + * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15200) + * should run RetrieveRepoMetas() for empty pr (#15187) (#15190) + * Move setting to enable closing issue via commit in non default branch to repo settings (#14965) + * Show correct issues for team dashboard (#14952) + * Ensure that new pull request button works on forked forks owned by owner of the root and reduce ambiguity (#14932) + * Only allow issue labels from owner repository or organization (#14928) + * Fix alignment of People and Teams right arrow on org homepage (#14924) + * Fix overdue marking of closed issues and milestones (#14923) + * Prevent panic when empty MilestoneID in repo/issue/list (#14911) + * Fix migration context data (#14910) + * Handle URLs with trailing slash (#14852) + * Add CORS config on to /login/oauth/access_token endpoint (#14850) + * Make searching issues by keyword case insensitive on DB (#14848) + * Prevent use of double sub-path and incorrect asset path in manifest (#14827) + * Fix link account ui (#14763) + * Fix preview status switch button on wiki editor (#14742) + * Fix github download on migration (#14703) + * Fix svg spacing (#14638) + * Prevent adding nil label to .AddedLabels or .RemovedLabels (#14623) + * Truncated organizations name (#14615) + * Exclude the current dump file from the dump (#14606) + * Use OldRef instead of CommitSHA for DeleteBranch comments (#14604) + * Ensure memcache caching works when TTL greater than 30 days (#14592) + * Remove NULs byte arrays passed to PostProcess (#14587) + * Restore detection of branches are equal on compare page (#14586) + * Fix incorrect key name so registerManualConfirm works (#14455) + * Fix close/reopen with comment (#14436) + * Allow passcode invalid error to appear (#14371) + * Escape branch names in compare url (#14364) + * Label and milestone webhooks on issue/pull creation (#14363) + * Handle NotifyCreateRef as create branch in feeds (#14245) + * Prevent clipping input text in Chrome + Segoe UI Font (#14179) + * Fix UI on edit auth source page (#14137) + * Fix git.parseTagData (#14105) + * Refactor get tag to remove unnecessary steps (#14058) + * Fix integrations test error with space in CURDIR path (#14056) + * Dropdown triangle fixes (#14028) + * Fix label of --id in admin delete user (#14005) + * Cause NotifyMigrateRepository to emit a repo create webhook (#14004) + * Update HEAD to match defaultBranch in template generation (#13948) + * Fix action avatar loading (#13909) + * Fix issue participants (#13893) + * Fix avatar template error (#13833) + * Fix review request notification email links when external issue tracker is enabled (#13723) + * Fix blame line alignment (#13542) + * Include OriginalAuthor in Reaction constraint (#13505) + * Comments on review should have the same sha (#13448) + * Fix whitespace rendering in diff (#13415) + * Fixed git args duplication (#13411) + * Fix bug on release publisherid migrations (#13410) + * Fix --port setting (#13288) + * Keep database transactions not too big (#13254) + * Git version check, ignore pre-releases constraints (#13234) + * Handle and propagate errors when checking if paths are Dirs, Files or Exist (#13186) + * Update Mirror IsEmpty status on synchronize (#13185) + * Use GO variable in go-check target (#13146) (#13147) +* ENHANCEMENTS + * UI style improvements + * Dropzone styling improvements (#15291) (#15374) + * Add size to Save function (#15264) (#15270) + * Monaco improvements (#15333) (#15345) + * Support .mailmap in code activity stats (#15009) + * Sort release attachments by name (#15008) + * Add ui.explore settings to control view of explore pages (#14094) + * Make internal SSH server host key path configurable (#14918) + * Hide resync all ssh principals when using internal ssh server (#14904) + * Add SameSite setting for cookies (#14900) + * Move Bleve and Elastic code indexers to use a common cat-file --batch (#14781) + * Add environment-to-ini to docker image (#14762) + * Add preview support for wiki editor when disable simpleMDE (#14757) + * Add easyMDE(simpleMDE) support for release content editor (#14744) + * Organization removal confirmation using name not password (#14738) + * Make branch names in PR description clickable (#14716) + * Add Password Algorithm option to install page (#14701) + * Add fullTextSearch to dropdowns by default (#14694) + * Fix truncated organization names (#14655) + * Whitespace in commits (#14650) + * Sort / move project boards (#14634) + * Make fileheader sticky in diffs (#14616) + * Add helper descriptions on new repo page (#14591) + * Move the stopwatches to the eventsource stream (#14588) + * Add Content-Length header to HEAD requests (#14542) + * Add Image Diff options in Diff view (#14450) + * Improve Description in new/ edit Project template (#14429) + * Allow ssh-keygen on Windows to detect ssh key type (#14413) + * Display error if twofaSecret cannot be retrieved (#14372) + * Sort issue search results by relevance (#14353) + * Implement ghost comment mitigation (#14349) + * Upgrade blevesearch dependency to v2.0.1 (#14346) + * Add edit, delete and reaction support to code review comments on issue page (#14339) + * Merge default and system webhooks under one menu (#14244) + * Add option for administrator to reset user 2FA (#14243) + * Add option to change username to the admin panel (#14229) + * Check for 'main' as potential default branch name (#14193) + * Project: show referenced PRs in issue cards (#14183) + * Use caddy's certmagic library for extensible/robust ACME handling (#14177) + * CLI support for OAuth sources custom icons (#14166) + * Custom icons for OAuth sources (#14161) + * Team dashboards (#14159) + * KanBan: be able to set default board (#14147) + * Disable Fomantic's custom scrollbars (#14109) + * Add UI to delete tracked times (#14100) + * Rework heatmap permissions (#14080) + * Issue and pull request filters on organization dashboard (#14072) + * Fix webhook list styling (#14001) + * Show dropdown with all statuses for commit (#13977) + * Show status check for merged PRs (#13975) + * Diff stat improvements (#13954) + * Report permissions denied in internal SSH (#13953) + * Markdown task list improvements (#13952) + * Heatmap days clickable (#13935) + * chore: use octicon-mirror for feeds display (#13928) + * Move diff split code into own template file (#13919) + * Markdown: Enable wrapping in code blocks and a color tweak (#13894) + * Do not reload page after adding comments in Pull Request reviews (#13877) + * Add pull request manually merge instruction (#13840) + * add thumbnail preview section to issue attachments (#13826) + * Move Repo APIFormat to convert package (#13787) + * Move notification APIFormat (#13783) + * Swap swagger-ui with swagger-ui-dist (#13777) + * User Settings: Ignore empty language codes & validate (#13755) + * Improve migrate page and add card CSS (#13751) + * Add block on official review requests branch protection (#13705) + * Add review requested filter on pull request overview (#13701) + * Use chronological commit order in default squash message (#13696) + * Clickable links in pull request (and issue) titles (#13695) + * Support shortened commit SHAs in URLs (#13686) + * Use native git variants by default with go-git variants as build tag (#13673) + * Don't render dropdown when only 1 merge style is available (#13670) + * Move webhook type from int to string (#13664) + * Direct avatar rendering (#13649) + * Verify password for local-account activation (#13631) + * Prevent clone protocol button flash on page load (#13626) + * Remove fetch request from heatmap (#13623) + * Refactor combine label comments with tests (#13619) + * Move metrics from macaron to chi (#13601) + * Issue and Pulls lists rework (#13594) + * HTTP cache rework and enable caching for storage assets (#13569) + * Use mount but not register for chi routes (#13555) + * Use monaco for the git hook editor (#13552) + * Make heatmap colors more distinct (#13533) + * Lazy-load issue reviewers and assignees avatars (#13526) + * Change search and filter icons to SVG (#13473) + * Create tag on ui (#13467) + * updateSize when create a repo with init commit (#13441) + * Added title and action buttons to Project view page (#13437) + * Override fomantic monospace fonts and set size (#13435) + * Rework focused comment styling (#13434) + * Tags cleanup (#13428) + * Various style tweaks (#13418) + * Refactor push update (#13381) + * Comment box tweaks and SVG dropdown triangles (#13376) + * Various style fixes (#13372) + * Change repo home page icons to SVG (#13364) + * Use CSS Vars for primary color (#13361) + * Refactor image paste code (#13354) + * Switch from SimpleMDE to EasyMDE (#13333) + * Group Label Changed Comments in timeline (#13304) + * Make the logger an interface (#13294) + * Fix PR/Issue titles on mobile (#13292) + * Rearrange the order of the merged by etc. in locale (#13284) + * Replace footer and modal icons with SVG (#13245) + * Issues overview should not show issues from archived repos (#13220) + * Show stale label for stale code comment which is marked as resolved (#13213) + * Use CSS Variables for fonts, remove postcss-loader (#13204) + * Add mentionable teams to tributeValues and change team mention rules to gh's style (#13198) + * Move install pages out of main macaron routes (#13195) + * Update outdated label to use Fomantic UI style (#13181) + * Added option to disable webhooks (#13176) + * Change order of possible-owner organizations to alphabetical (#13160) + * Log IP on SSH authentication failure for Built-in SSH server (#13150) + * Added option to disable migrations (#13114) + * New "Add Mirror" Button in the Organization view (#13105) + * Manually approve new registration (#13083) + * Cron job to cleanup hook_task table (#13080) + * Use the headline comment of pull-request as the squash commit's message (#13071) + * Clarify the suffices and prefixes of setting.AppSubURL and setting.AppURL (#12999) + * Slightly simplify the queue settings code to help reduce the risk of problems (#12976) + * Add precise search type for Elastic Search (#12869) + * Move APIFormat functions into convert package (#12856) + * Multiple GitGraph improvements: Exclude PR heads, Add branch/PR links, Show only certain branches, (#12766) + * Add TrN for repository limit (#12492) + * Refactor doctor (#12264) + * Add the tag list page to the release page (#12096) + * Redirect on changed user and org name (#11649) + * load U2F js only on pages which need it (#11585) + * Make archival asynchronous (#11296) + * Introduce go chi web framework as frontend of macaron, so that we can move routes from macaron to chi step by step (#7420) + * Improve vfsgen to not unzip bindata files but send to browser directly (#7109) + * Enhance release list (#6025) +* DOCS + * Swagger show models by default (#14880) + * Add missing repo.projects unit into swagger (#14876) + * Update docs and comments to remove macaron (#14491) + * Issue template addition: Are you using Gitea behind CloudFlare? (#14098) + * Generate man pages (#13901) + * Reformat/fine-tune docs (#13897) + * Added Table of Contents to long documentation pages (#13890) + * Add docs command (#13429) + * Update external-renderers.en-us.md (#13165) +* MISC + * Add builds for apple M1 (darwin arm64) (#14951) + * Migrate to use jsoniter instead of encoding/json (#14841) + * Reduce make verbosity (#13803) + * Add git command error directory on log (#13194) + +## [1.13.7](https://github.com/go-gitea/gitea/releases/tag/v1.13.7) - 2021-04-07 + +* SECURITY + * Update to bluemonday-1.0.6 (#15294) (#15298) + * Clusterfuzz found another way (#15160) (#15169) +* API + * Fix wrong user returned in API (#15139) (#15150) +* BUGFIXES + * Add 'fonts' into 'KnownPublicEntries' (#15188) (#15317) + * Speed up `enry.IsVendor` (#15213) (#15246) + * Response 404 for diff/patch of a commit that not exist (#15221) (#15238) + * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15201) +* MISC + * Add size to Save function (#15264) (#15271) + +## [1.13.6](https://github.com/go-gitea/gitea/releases/tag/v1.13.6) - 2021-03-23 + +* SECURITY + * Fix bug on avatar middleware (#15124) (#15125) + * Fix another clusterfuzz identified issue (#15096) (#15114) +* API + * Fix nil exeption for get pull reviews API #15104 (#15106) +* BUGFIXES + * Fix markdown rendering in milestone content (#15056) (#15092) + +## [1.13.5](https://github.com/go-gitea/gitea/releases/tag/v1.13.5) - 2021-03-21 + +* SECURITY + * Update to goldmark 1.3.3 (#15059) (#15061) + * Another clusterfuzz spotted issue (#15032) (#15034) +* API + * Fix set milestone on PR creation (#14981) (#15001) + * Prevent panic when editing forked repos by API (#14960) (#14963) +* BUGFIXES + * Fix bug when upload on web (#15042) (#15055) + * Delete Labels & IssueLabels on Repo Delete too (#15039) (#15051) + * Fix postgres ID sequences broken by recreate-table (#15015) (#15029) + * Fix several render issues (#14986) (#15013) + * Make sure sibling images get a link too (#14979) (#14995) + * Fix Anchor jumping with escaped query components (#14969) (#14977) + * Fix release mail html template (#14976) + * Fix excluding more than two labels on issues list (#14962) (#14973) + * Don't mark each comment poster as OP (#14971) (#14972) + * Add "captcha" to list of reserved usernames (#14930) + * Re-enable import local paths after reversion from #13610 (#14925) (#14927) + +## [1.13.4](https://github.com/go-gitea/gitea/releases/tag/v1.13.4) - 2021-03-07 + +* SECURITY + * Fix issue popups (#14898) (#14899) +* BUGFIXES + * Fix race in LFS ContentStore.Put(...) (#14895) (#14913) + * Fix a couple of issues with a feeds (#14897) (#14903) + * When transferring repository and database transaction failed, rollback the renames (#14864) (#14902) + * Fix race in local storage (#14888) (#14901) + * Fix 500 on pull view page if user is not loged in (#14885) (#14886) +* DOCS + * Fix how lfs data path is set (#14855) (#14884) + +## [1.13.3](https://github.com/go-gitea/gitea/releases/tag/v1.13.3) - 2021-03-04 + +* BREAKING + * Turn default hash password algorithm back to pbkdf2 from argon2 until we find a better one (#14673) (#14675) +* BUGFIXES + * Fix paging of file commit logs (#14831) (#14879) + * Print useful error if SQLite is used in settings but not supported (#14476) (#14874) + * Fix display since time round (#14226) (#14873) + * When Deleting Repository only explicitly close PRs whose base is not this repository (#14823) (#14842) + * Set HCaptchaSiteKey on Link Account pages (#14834) (#14839) + * Fix a couple of CommentAsPatch issues. (#14804) (#14820) + * Disable broken OAuth2 providers at startup (#14802) (#14811) + * Repo Transfer permission checks (#14792) (#14794) + * Fix double alert in oauth2 application edit view (#14764) (#14768) + * Fix broken spans in diffs (#14678) (#14683) + * Prevent race in PersistableChannelUniqueQueue.Has (#14651) (#14676) + * HasPreviousCommit causes recursive load of commits unnecessarily (#14598) (#14649) + * Do not assume all 40 char strings are SHA1s (#14624) (#14648) + * Allow org labels to be set with issue templates (#14593) (#14647) + * Accept multiple SSH keys in single LDAP SSHPublicKey attribute (#13989) (#14607) + * Fix bug about ListOptions and stars/watchers pagnation (#14556) (#14573) + * Fix GPG key deletion during account deletion (#14561) (#14569) + +## [1.13.2](https://github.com/go-gitea/gitea/releases/tag/v1.13.2) - 2021-01-31 + +* SECURITY + * Prevent panic on fuzzer provided string (#14405) (#14409) + * Add secure/httpOnly attributes to the lang cookie (#14279) (#14280) +* API + * If release publisher is deleted use ghost user (#14375) +* BUGFIXES + * Internal ssh server respect Ciphers, MACs and KeyExchanges settings (#14523) (#14530) + * Set the name Mapper in migrations (#14526) (#14529) + * Fix wiki preview (#14515) + * Update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 (#14497) + * ChangeUserName: rename user files back on DB issue (#14447) + * Fix lfs preview bug (#14428) (#14433) + * Ensure timeout error is shown on u2f timeout (#14417) (#14431) + * Fix Deadlock & Delete affected reactions on comment deletion (#14392) (#14425) + * Use path not filepath in routers/editor (#14390) (#14396) + * Check if label template exist first (#14384) (#14389) + * Fix migration v141 (#14387) (#14388) + * Use Request.URL.RequestURI() for fcgi (#14347) + * Use ServerError provided by Context (#14333) (#14345) + * Fix edit-label form init (#14337) + * Fix mailIssueCommentBatch for pull request (#14252) (#14296) + * Render links for commit hashes followed by comma (#14224) (#14227) + * Send notifications for mentions in pulls, issues, (code-)comments (#14218) (#14221) + * Fix avatar bugs (#14217) (#14220) + * Ensure that schema search path is set with every connection on postgres (#14131) (#14216) + * Fix dashboard issues labels filter bug (#14210) (#14214) + * When visit /favicon.ico but the static file is not exist return 404 but not continue to handle the route (#14211) (#14213) + * Fix branch selector on new issue page (#14194) (#14207) + * Check for notExist on profile repository page (#14197) (#14203) + +## [1.13.1](https://github.com/go-gitea/gitea/releases/tag/v1.13.1) - 2020-12-29 + +* SECURITY + * Hide private participation in Orgs (#13994) (#14031) + * Fix escaping issue in diff (#14153) (#14154) +* BUGFIXES + * Fix bug of link query order on markdown render (#14156) (#14171) + * Drop long repo topics during migration (#14152) (#14155) + * Ensure that search term and page are not lost on adoption page-turn (#14133) (#14143) + * Fix storage config implementation (#14091) (#14095) + * Fix panic in BasicAuthDecode (#14046) (#14048) + * Always wait for the cmd to finish (#14006) (#14039) + * Don't use simpleMDE editor on mobile devices for 1.13 (#14029) + * Fix incorrect review comment diffs (#14002) (#14011) + * Trim the branch prefix from action.GetBranch (#13981) (#13986) + * Ensure template renderer is available before storage handler (#13164) (#13982) + * Whenever the password is updated ensure that the hash algorithm is too (#13966) (#13967) + * Enforce setting HEAD in wiki to master (#13950) (#13961) + * Fix feishu webhook caused by API changed (#13938) + * Fix Quote Reply button on review diff (#13830) (#13898) + * Fix Pull Merge when tag with same name as base branch exist (#13882) (#13896) + * Fix mermaid chart size (#13865) + * Fix branch/tag notifications in mirror sync (#13855) (#13862) + * Fix crash in short link processor (#13839) (#13841) + * Update font stack to bootstrap's latest (#13834) (#13837) + * Make sure email recipients can see issue (#13820) (#13827) + * Reply button is not removed when deleting a code review comment (#13824) + * When reinitialising DBConfig reset the database use flags (#13796) (#13811) +* ENHANCEMENTS + * Add emoji in label to project boards (#13978) (#14021) + * Send webhook when tag is removed via Web UI (#14015) (#14019) + * Use Process Manager to create own Context (#13792) (#13793) +* API + * GetCombinedCommitStatusByRef always return json & swagger doc fixes (#14047) + * Return original URL of Repositories (#13885) (#13886) + +## [1.13.0](https://github.com/go-gitea/gitea/releases/tag/v1.13.0) - 2020-12-01 + +* SECURITY + * Add Allow-/Block-List for Migrate & Mirrors (#13610) (#13776) + * Prevent git operations for inactive users (#13527) (#13536) + * Disallow urlencoded new lines in git protocol paths if there is a port (#13521) (#13524) + * Mitigate Security vulnerability in the git hook feature (#13058) + * Disable DSA ssh keys by default (#13056) + * Set TLS minimum version to 1.2 (#12689) + * Use argon as default password hash algorithm (#12688) +* BREAKING + * Set RUN_MODE prod by default (#13765) (#13767) + * Don't replace underscores in auto-generated IDs in goldmark (#12805) + * Add Primary Key to Topic and RepoTopic tables (#12639) + * Disable password complexity check default (#12557) + * Change PIDFile default from /var/run/gitea.pid to /run/gitea.pid (#12500) + * Add extension Support to Attachments (allow all types for releases) (#12465) + * Remove IE11 Support (#11470) +* FEATURES + * Adopt repositories (#12920) + * Check passwords against HaveIBeenPwned (#12716) + * Gitea 2 Gitea migration (#12657) + * Support storing Avatars in minio (#12516) + * Allow addition of gpg keyring with multiple keys (#12487) + * Add email notify for new release (#12463) + * Add Access-Control-Expose-Headers (#12446) + * UserProfile Page: Render Description (#12415) + * Add command to recreate tables (#12407) + * Add mermaid JS renderer (#12334) + * Add ssh certificate support (#12281) + * Add spent time to referenced issue in commit message (#12220) + * Initial support for push options (#12169) + * Provide option to unlink a fork (#11858) + * Show exact tag for commit on diff view (#11846) + * Pause, Resume, Release&Reopen, Add and Remove Logging from command line (#11777) + * Issue templates directory (#11450) + * Add a storage layer for attachments (#11387) + * Add hide activity option (#11353) + * Add push commits history comment on PR time-line (#11167) + * Support elastic search for code search (#10273) + * Kanban board (#8346) +* API + * If User is Admin, show 500 error message on PROD mode too (#13115) + * Add Timestamp to Tag list API (#13026) + * Return sample message for login error in api context (#12994) + * Add IsTemplate option in create repo ui and api (#12942) + * GetReleaseByID return 404 if not found (#12933) + * Get release by tags endpoint (#12932) + * NotificationSubject show Issue/Pull State (#12901) + * Expose its limitation settings (#12714) + * Add Created & Updated to Milestone (#12662) + * Milestone endpoints accept names too (#12649) + * Expose Attachment Settings in the API (#12514) + * Add Issue and Repo info to StopWatch (#12458) + * Add cron running API (#12421) + * Add Update Pull HeadBranch Function (#12419) + * Add TOTP header to Swagger Documentation (#12402) + * Delete Token accept names too (#12366) + * Add name filter for GetMilestoneList (#12336) + * Fixed count of filtered issues when api request. (#12275) + * Do not override API issue pagination with UI settings (#12068) + * Expose useful General Repo settings settings (#11758) + * Return error when trying to create Mirrors but Mirrors are globally disabled (#11757) + * Provide diff and patch API endpoints (#11751) + * Allow to create closed milestones (#11745) + * Add language Statistics endpoint (#11737) + * Add Endpoint to get GetGeneralUI Settings (#11735) & (#11854) + * Issue/Pull expose IsLocked Property on API (#11708) + * Add endpoint for Branch Creation (#11607) + * Add pagination headers on endpoints that support total count from database (#11145) +* BUGFIXES + * Fix bogus http requests on diffs (#13760) (#13761) + * Show 'owner' tag for real owner (#13689) (#13743) + * Validate email before inserting/updating (#13475) (#13666) + * Fix issue/pull request list assignee filter (#13647) (#13651) + * Gitlab migration support for subdirectories (#13563) (#13591) + * Fix logic for preferred license setting (#13550) (#13557) + * Add missed sync branch/tag webhook (#13538) (#13556) + * Migration won't fail on non-migrated reactions (#13507) + * Fix Italian language file parsing error (#13156) + * Show outdated comments in pull request (#13148) (#13162) + * Fix parsing of pre-release git version (#13169) (#13172) + * Fix diff skipping lines (#13154) (#13155) + * When handling errors in storageHandler check underlying error (#13178) (#13193) + * Fix size and clickable area on file table back link (#13205) (#13207) + * Add better error checking for inline html diff code (#13251) + * Fix initial commit page & binary munching problem (#13249) (#13258) + * Fix migrations from remote Gitea instances when configuration not set (#13229) (#13273) + * Store task errors following migrations and display them (#13246) (#13287) + * Fix bug isEnd detection on getIssues/getPullRequests (#13299) (#13301) + * When the git ref is unable to be found return broken pr (#13218) (#13303) + * Ensure topics added using the API are added to the repository (#13285) (#13302) + * Fix avatar autogeneration (#13233) (#13282) + * Add migrated pulls to pull request task queue (#13331) (#13334) + * Issue comment reactions should also check pull type on API (#13349) (#13350) + * Fix links to repositories in /user/setting/repos (#13360) (#13362) + * Remove obsolete change of email on profile page (#13341) (#13347) + * Fix scrolling to resolved comment anchors (#13343) (#13371) + * Storage configuration support `[storage]` (#13314) (#13379) + * When creating line diffs do not split within an html entity (#13357) (#13375) (#13425) (#13427) + * Fix reactions on code comments (#13390) (#13401) + * Add missing full names when DEFAULT_SHOW_FULL_NAME is enabled (#13424) + * Replies to outdated code comments should also be outdated (#13217) (#13433) + * Fix panic bug in handling multiple references in commit (#13486) (#13487) + * Prevent panic on git blame by limiting lines to 4096 bytes at most (#13470) (#13491) + * Show original author's reviews on pull summary box (#13127) + * Update golangci-lint to version 1.31.0 (#13102) + * Fix line break for MS teams webhook (#13081) + * Fix Issue & Pull Request comment headers on mobile (#13039) + * Avoid setting the CONN_STR in queues unless it is meant to be set (#13025) + * Remove code-view class from diff view (#13011) + * Fix the color of PR comment hyperlinks. (#13009) + * (Re)Load issue labels when changing them (#13007) + * Fix Media links in org files not liked to media files (#12997) + * Always return a list from GetCommitsFromIDs (#12981) + * Only set the user password if the password field would have been shown (#12980) + * Fix admin/config page (#12979) + * Changed width of commit signature avatar (#12961) + * Completely quote AppPath and CustomConf paths (#12955) + * Fix handling of migration errors (#12928) + * Fix anonymous GL migration (#12862) + * Fix git open close bug (#12834) + * Fix markdown meta parsing (#12817) + * Add default storage configurations (#12813) + * Show PR settings on empty repos (#12808) + * Disable watch and star if not signed in (#12807) + * Whilst changing the character set to utf8mb4 we should set ROW_FORMAT=dynamic too (#12804) + * Set opengraph attributes on org pages (#12803) + * Return error when creating gitlabdownloader failed (#12790) + * Add migration for password algorithm change (#12784) + * Compare SSH_DOMAIN when parsing submodule URLs (#12753) + * Fix editor.commit_empty_file_text locale string (#12744) + * Fix wrong poster message for code comment on Pull view (#11721) + * Escape failed highlighted files (#12685) + * Ensure that all migration requests are cancellable (#12669) + * Ensure RepoPath is lowercased in gitea serv (#12668) + * Do not disable commit changes button on repost (#12644) + * Dark theme for line numbers in blame view (#12632) + * Fix message when deleting last owner from an organization (#12628) + * Use shellquote to unpack arguments to gitea serv (#12624) + * Fix signing.wont_sign.%!s() if Require Signing commits but not signed in. (#12581) + * Set utf8mb4 as the default charset on MySQL if CHARSET is unset (#12563) + * Set context for running CreateArchive to that of the request (#12555) + * Prevent redirect back to /user/events (#12462) + * Re-attempt to delete temporary upload if the file is locked by another process (#12447) + * Mirror System Notice reports are too frequent (#12438) + * Do not show arrows on comment diffs on pull comment pages (#12434) + * Fix milestone links (#12405) + * Increase size of the language column in language_stat (#12396) + * Use transaction in V102 migration (#12395) + * Only use --exclude on name-rev with git >= 2.13 (#12347) + * Add action feed for new release (#12324) + * Set NoAutoTime when updating is_archived (#12266) + * Support Force-update in Mirror and improve Tracing in mirror (#12242) + * Avoid sending "0 new commits" webhooks (#12212) + * Fix U2F button icon (#12167) + * models/repo_sign.go: break out of loops (#12159) + * Ensure that git commit tree continues properly over the page (#12142) + * Rewrite GitGraph.js (#12137) + * Fix repo API listing stability (#12057) + * Add team support for review request (#12039) + * Fix 500 error on repos with no tags (#11870) + * Fix nil pointer in default issue mail template (#11862) + * Fix commit search in all branches (#11849) + * Don't consider tag refs as valid for branch name (#11847) + * Don't add same line code comment box twice (#11837) + * Fix visibility of forked public repos from private orgs (#11717) + * Fix chardet test and add ordering option (#11621) + * Fix number of files, total additions, and deletions on Diff pages (#11614) + * Properly handle and return empty string for dangling commits in GetBranchName (#11587) + * Include query in sign in redirect (#11579) + * Fix Enter not working in SimpleMDE (#11564) + * Fix bug about can't skip commits base on base branch (#11555) +* ENHANCEMENTS + * Only Return JSON for responses (#13511) (#13565) + * Use existing analyzer module for language detection for highlighting (#13522) (#13551) + * Return the full rejection message and errors in flash errors (#13221) (#13237) + * Remove PAM from auth dropdown when unavailable (#13276) (#13281) + * Add HostCertificate to sshd_config in Docker image (#13143) + * Save TimeStamps for Star, Label, Follow, Watch and Collaboration to Database (#13124) + * Improve error feedback for duplicate deploy keys (#13112) + * Set appropriate `autocomplete` attributes on password fields (#13078) + * Adding visual cue for "Limited" & "Private" organizations. (#13040) + * Fix Pull Request merge buttons on mobile (#13035) + * Gitea serv, hooks, manager and the like should always display Fatals (#13032) + * CSS tweaks to warning/error segments and misc fixes (#13024) + * Fix formatting of branches ahead-behind on narrow windows (#12989) + * Add config option to make create-on-push repositories public by default (#12936) + * Disable migration items when mirror is selected (#12918) + * Add the checkbox quick button to the comment tool bar also (#12885) + * Support GH enterprise (#12863) + * Simplify CheckUnitUser logic (#12854) + * Fix background of signed-commits on arc-green of timeline commits (#12837) + * Move git update-server-info to hooks (#12826) + * Add ui style for "Open a blank issue" button (#12824) + * Use a simple format for the big number on ui (#12822) + * Make SVG size argument optional (#12814) + * Add placeholder text for bio profile text form (#12792) + * Set language via AJAX (#12785) + * Show git-pull-request icon for closed pull request (#12742) + * Migrate version parsing library to hashicorp/go-version (#12719) + * Only use async pre-empt hack if go < 1.15 (#12718) + * Inform user about meaning of an hourglass on reviews (#12713) + * Add a migrate service type switch page (#12697) + * Migrations: Gitlab Add Reactions Support for Issues & MergeRequests (#12695) + * Remove duplicate logic in initListSubmits (#12660) + * Set avatar image dimensions (#12654) + * Rename models.ProtectedBranchRepoID/PRID to models.EnvRepoID/PRID and ensure EnvPusherEmail is set (#12646) + * Set setting.AppURL as GITEA_ROOT_URL environment variable during pushes (#12752) + * Add postgres schema to the search_path on database connection (#12634) + * Git migration UX improvements (#12619) + * Add link to home page on swagger ui (#12601) + * hCaptcha Support (#12594) + * OpenGraph: use repo avatar if exist (#12586) + * Reaction picker display improvements (#12576) + * Fix emoji replacements, make emoji images consistent (#12567) + * Increase clickable area on files table links (#12553) + * Set z-index for sticky diff box lower (#12537) + * Report error if API merge is not allowed (#12528) + * LFS support to be stored on minio (#12518) + * Show 2FA info on Admin Pannel: Users List (#12515) + * Milestone Issue/Pull List: Add octicons type (#12499) + * Make dashboard newsfeed list length a configurable item (#12469) + * Add placeholder text for send testing email button in admin/config (#12452) + * Add SVG favicon (#12437) + * In issue comments, put issue participants also in completion list when hitting @ (#12433) + * Collapse Swagger UI tags by default (#12428) + * Detect full references to issues and pulls in commit messages (#12399) + * Allow common redis and leveldb connections (#12385) + * Don't use legacy method to send Matrix Webhook (#12348) + * Remove padding/border-radius on image diffs (#12346) + * Render the git graph on the server (#12333) + * Fix clone panel in wiki position not always align right (#12326) + * Rework 'make generate-images' (#12316) + * Refactor webhook payload conversion (#12310) + * Move jquery-minicolors to npm/webpack (#12305) + * Support use nvarchar for all varchar columns when using mssql (#12269) + * Update Octicons to v10 (#12240) + * Disable search box autofocus (#12229) + * Replace code fold icons with octicons (#12222) + * Ensure syntax highlighting is the same inside diffs (#12205) + * Auto-init repo on license, .gitignore select (#12202) + * Default to showing closed Issues/PR list when there are only closed issues/PRs (#12200) + * Enable cloning via Git Wire Protocol v2 over HTTP (#12170) + * Direct SVG rendering (#12157) + * Improve arc-green code colors (#12111) + * Allow admin to merge pr with protected file changes (#12078) + * Show description on individual milestone view (#12055) + * Update the wiki repository remote origin while update the mirror repository's Clone From URL (#12053) + * Server-side syntax highlighting for all code (#12047) + * Use Fomantic's fluid padded for blame full width (#12023) + * Use custom SVGs for commit signing lock icon (#12017) + * Make tabs smaller (#12003) + * Fix sticky diff stats container (#12002) + * Move fomantic and jQuery to main webpack bundle (#11997) + * Use enry language type to detect special languages (#11974) + * Use only first line of commit when creating referenced comment (#11960) + * Rename custom/conf/app.ini.sample to custom/conf/app.example.ini for better syntax light on editor (#11926) + * Fix double divider on issue sidebar (#11919) + * Shorten markdown heading anchors links (#11903) + * Add org avatar on top of internal repo icon (#11895) + * Use label to describe repository type (#11891) + * Make repository size unclickable on repo summary bar (#11887) + * Rework blame template and styling (#11885) + * Fix icon alignment for show/hide outdated link on resolved conversation (#11881) + * Vertically align review icons on repository sidebar (#11880) + * Better align items using flex within review request box (#11879) + * Only write to global gitconfig if necessary (#11876) + * Disable all typographic replacements in markdown renderer (#11871) + * Improve label edit buttons labels (#11841) + * Use crispEdges rendering for octicon-internal-repo (#11801) + * Show update branch item in merge box when it's necessary (#11761) + * Add compare link to releases (#11752) + * Allow site admin to disable mirrors (#11740) + * Export monaco editor on window.codeEditors (#11739) + * Add configurable Trust Models (#11712) + * Show full GPG commit status on PR commit history (#11702) + * Fix align issues and decrease avatar size on PR timeline (#11689) + * Replace jquery-datetimepicker with native date input (#11684) + * Change Style of Tags on Comments (#11668) + * Fix missing styling for shabox on PR commit history (#11625) + * Apply padding to approval icons on PR list (#11622) + * Fix message wrapping on PR commit list (#11616) + * Right-align status icon on pull request commit history (#11594) + * Add missing padding for multi-commit list on PR view (#11593) + * Do not show avatar for "{{user}} added X commits" (#11591) + * Fix styling and padding for commit list on PR view (#11588) + * Style code review comment for arc-green (#11572) + * Use default commit message for wiki edits (#11550) + * Add internal-repo octicon for public repos of private org (#11529) + * Fix dropzone color on arc-green (#11514) + * Insert ui divider directly in templates instead of from inside heatmap vue component (#11508) + * Move tributejs to npm/webpack (#11497) + * Fix text-transform on wiki revisions page (#11486) + * Do not show lock icon on repo list for public repos in private org (#11445) + * Include LFS when calculating repo size (#11060) + * Add check for LDAP group membership (#10869) + * When starting new stopwatch stop previous if it is still running (#10533) + * Add queue for code indexer (#10332) + * Move all push update operations to a queue (#10133) + * Cache last commit when pushing for big repository (#10109) + * Change/remove a branch of an open issue (#9080) + * Sortable Tables Header By Click (#7980) +* TESTING + * Use community codecov drone plugin (#12468) + * Add more tests for diff highlighting (#12467) + * Don't put integration test data outside of test folder (#11746) + * Add debug option to hooks (#11624) + * Log slow tests (#11487) +* TRANSLATION + * Translate two small lables on commit statutes list (#12821) + * Make issues.force_push_codes message shorter (#11575) +* BUILD + * Bump min required golang to 1.13 (#12717) + * Add 'make watch' (#12636) + * Extract Swagger CSS to its own file (#12616) + * Update eslint config (#12609) + * Avoid unnecessary system-ui expansion (#12522) + * Make the default PID file compile-time settable (#12485) + * Add 'watch-backend' (#12330) + * Detect version of sed in Makefile (#12319) + * Update gitea-vet to v0.2.1 (#12282) + * Add logic to build stable and edge builds for gitea snap (#12052) + * Fix missing CGO_EXTRA_FLAGS build arg for docker (#11782) + * Alpine 3.12 (#11720) + * Enable stylelint's shorthand-property-no-redundant-values (#11436) +* DOCS + * Change default log configuration (#13088) + * Add automatic JS license generation (#11810) + * Remove page size limit comment from swagger (#11806) + * Narrow down Edge version in browser support docs (#11640) + +## [1.12.5](https://github.com/go-gitea/gitea/releases/tag/v1.12.5) - 2020-10-01 + +* BUGFIXES + * Allow U2F with default settings for gitea in subpath (#12990) (#13001) + * Prevent empty div when editing comment (#12404) (#12991) + * On mirror update also update address in DB (#12964) (#12967) + * Allow extended config on cron settings (#12939) (#12943) + * Open transaction when adding Avatar email-hash pairs to the DB (#12577) (#12940) + * Fix internal server error from ListUserOrgs API (#12910) (#12915) + * Update only the repository columns that need updating (#12900) (#12912) + * Fix panic when adding long comment (#12892) (#12894) + * Add size limit for content of comment on action ui (#12881) (#12890) + * Convert User expose ID each time (#12855) (#12883) + * Support slashes in release tags (#12864) (#12882) + * Add missing information to CreateRepo API endpoint (#12848) (#12867) + * On Migration respect old DefaultBranch (#12843) (#12858) + * Fix notifications page links (#12838) (#12853) + * Stop cloning unnecessarily on PR update (#12839) (#12852) + * Escape more things that are passed through str2html (#12622) (#12850) + * Remove double escape on labels addition in comments (#12809) (#12810) + * Fix "only mail on mention" bug (#12775) (#12789) + * Fix yet another bug with diff file names (#12771) (#12776) + * RepoInit Respect AlternateDefaultBranch (#12746) (#12751) + * Fix Avatar Resize (resize algo NearestNeighbor -> Bilinear) (#12745) (#12750) +* ENHANCEMENTS + * gitea dump: include version & Check InstallLock (#12760) (#12762) + +## [1.12.4](https://github.com/go-gitea/gitea/releases/tag/v1.12.4) - 2020-09-02 + +* SECURITY + * Escape provider name in oauth2 provider redirect (#12648) (#12650) + * Escape Email on password reset page (#12610) (#12612) + * When reading expired sessions - expire them (#12686) (#12690) +* ENHANCEMENTS + * StaticRootPath configurable at compile time (#12371) (#12652) +* BUGFIXES + * Fix to show an issue that is related to a deleted issue (#12651) (#12692) + * Expire time acknowledged for cache (#12605) (#12611) + * Fix diff path unquoting (#12554) (#12575) + * Improve HTML escaping helper (#12562) + * models: break out of loop (#12386) (#12561) + * Default empty merger list to those with write permissions (#12535) (#12560) + * Skip SSPI authentication attempts for /api/internal (#12556) (#12559) + * Prevent NPE on commenting on lines with invalidated comments (#12549) (#12550) + * Remove hardcoded ES indexername (#12521) (#12526) + * Fix bug preventing transfer to private organization (#12497) (#12501) + * Keys should not verify revoked email addresses (#12486) (#12495) + * Do not add prefix on http/https submodule links (#12477) (#12479) + * Fix ignored login on compare (#12476) (#12478) + * Fix incorrect error logging in Stats indexer and OAuth2 (#12387) (#12422) + * Upgrade google/go-github to v32.1.0 (#12361) (#12390) + * Render emoji's of Commit message on feed-page (#12373) + * Fix handling of diff on unrelated branches when Git 2.28 used (#12370) + +## [1.12.3](https://github.com/go-gitea/gitea/releases/tag/v1.12.3) - 2020-07-28 + +* BUGFIXES + * Don't change creation date when updating Release (#12343) (#12351) + * Show 404 page when release not found (#12328) (#12332) + * Fix emoji detection in certain cases (#12320) (#12327) + * Reduce emoji size (#12317) (#12327) + * Fix double-indirection bug in logging IDs (#12294) (#12308) + * Link to pull list page on sidebar when view pr (#12256) (#12263) + * Extend Notifications API and return pinned notifications by default (#12164) (#12232) + +## [1.12.2](https://github.com/go-gitea/gitea/releases/tag/v1.12.2) - 2020-07-11 + +* BUGFIXES + * When deleting repository decrese user repository count in cache (#11954) (#12188) + * Return full commit message instead of summary in commits API (#12186) (#12187) + * Properly set HEAD when a repo is created with a default branch that is not named 'master' (#12135) (#12182) + * Ensure GPG Subkeys are verified (#12155) (#12168) + * Fix failing to cache last commit with key being to long (#12151) (#12161) + * Multiple small admin dashboard fixes (#12153) (#12156) + * Remove spurious logging of " Delete all repository archives" at startup (#12139) (#12148) + * Fix repository setup instructions when default branch is not named 'master' (#12122) (#12147) + * Move EventSource to SharedWorker (#12095) (#12130) + * Fix ui bug in wiki commit page (#12089) (#12125) + * Fix gitgraph branch continues after merge (#12044) (#12105) + * Set the base url when migrating from Gitlab using access token or username without password (#11852) (#12104) + * Ensure BlameReaders close at end of request (#12102) (#12103) + * Fix panic when adding review comment (#12058) +* ENHANCEMENTS + * Disable dropzone's timeout for file uploads (#12024) (#12032) + +## [1.12.1](https://github.com/go-gitea/gitea/releases/tag/v1.12.1) - 2020-06-21 + +* BUGFIXES + * Handle multiple merges in gitgraph.js (#11996) (#12000) + * Add serviceworker.js to KnownPublicEntries (#11992) (#11994) + * For language detection do not try to analyze big files by content (#11971) (#11975) +* ENHANCEMENTS + * Fix scrollable header on dropdowns (#11893) (#11965) + +## [1.11.8](https://github.com/go-gitea/gitea/releases/tag/v1.11.8) - 2020-06-21 + +* BUGFIXES + * Really fix __webpack_public_path__ for 1.11 (#11961) + +## [1.12.0](https://github.com/go-gitea/gitea/releases/tag/v1.12.0) - 2020-06-17 + +* BREAKING + * When using API CreateRelease set created_unix to the tag commit time (#11218) + * Enable ENABLE_HARD_LINE_BREAK by default for rendering markdown (#11162) + * Fix sanitizer config - multiple rules (#11133) + * Remove check on username when using AccessToken authentication for the API (#11015) + * Return 404 from Contents API when items don't exist (#10323) + * Notification API should always return a JSON object with the current count of notifications (#10059) + * Remove migration support from versions earlier than 1.6.0 (#10026) +* SECURITY + * Use -1 to disable key algorithm type in ssh.minimum_key_sizes (#11635) (#11662) +* FEATURES + * Improve config logging when WrappedQueue times out (#11174) + * Add branch delete to API (#11112) + * Use markdown frontmatter to provide Table of contents, language and frontmatter rendering (#11047) + * Add a way to mark Conversation (code comment) resolved (#11037) + * Handle yaml frontmatter in markdown (#11016) + * Cache PullRequest Divergence (#10914) + * Make `gitea admin auth list` formatting configurable (#10844) + * Add Matrix webhook (#10831) + * Add Organization Wide Labels (#10814) + * Allow to set protected file patterns for files that can not be changed under no conditions (#10806) + * Option to set default branch at repository creation (#10803) + * Add request review from specific reviewers feature in pull request (#10756) + * Add NextCloud oauth (#10562) + * System-wide webhooks (#10546) + * Relax sanitization as per https://github.com/jch/html-pipeline (#10527) + * Use media links for img in post-process (#10515) + * Add API endpoints to manage OAuth2 Application (list/create/delete) (#10437) + * Render READMEs in docs/ .gitea or .github from root (#10361) + * Add feishu webhook support (#10229) + * Cache last commit to accelerate the repository directory page visit (#10069) + * Implement basic app.ini and path checks to doctor cmd (#10064) + * Make WorkerPools and Queues flushable (#10001) + * Implement "embedded" command to extract static resources (#9982) + * Add API endpoint for repo transfer (#9947) + * Make archive prefixing configurable with a global setting (#9943) + * Add Unique Queue infrastructure and move TestPullRequests to this (#9856) + * Issue/PR Context Popups (#9822) + * Add "Update Branch" button to Pull Requests (#9784) + * Add require signed commit for protected branch (#9708) + * Mark PR reviews as stale at push and allow to dismiss stale approvals (#9532) + * Add API notification endpoints (#9488) + * Issue search support elasticsearch (#9428) + * Add API branch protection endpoint (#9311) + * Add a new command doctor to check if some wrong configurations on gitea instance (#9095) + * Add support for migrating from Gitlab (#9084) + * Add support for database schema in PostgreSQL (#8819) + * Add setting to set default and global disabled repository units. (#8788) + * Language statistics bar for repositories (#8037) + * Restricted users (#6274) +* BUGFIXES + * Fix commenting on non-utf8 encoded files (#11916) (#11950) + * Use google/uuid to instead satori/go.uuid (#11943) (#11946) + * Align show/hide outdated button on code review block (#11932) (#11944) + * Update to go-git v5.1.0 (#11936) (#11941) + * Use ID or Where to instead directly use Get when load object from database (#11925) (#11934) + * Update CommitsAhead CommitsBehind on Pull BaseBranch Change too (#11912) (#11915) + * Invalidate comments when file is shortened (#11882) (#11884) + * Rework api/user/repos for pagination (#11827) (#11877) + * Handle more pathological branch and tag names (#11843) (#11863) + * Add doctor check to set IsArchived false if it is null (partial #11853) (#11859) + * Prevent panic on empty HOST for mysql (#11850) (#11856) + * Use DEFAULT_PAGING_NUM instead of MAX_RESPONSE_ITEMS in ListOptions (#11831) (#11836) + * Fix reply octicon (#11821) (#11822) + * Honor DEFAULT_PAGING_NUM for API (#11805) (#11813) + * Ensure rejected push to refs/pull/index/head fails nicely (#11724) (#11809) + * In File Create/Update API return 404 if Branch does not exist (#11791) (#11795) + * Fix doer of rename repo (#11789) (#11794) + * Initialize SimpleMDE when making a code comment (#11749) (#11785) + * Fix timezone on issue deadline (#11697) (#11784) + * Fix to allow comment poster to edit or delete his own comments (#11671) (#11774) + * Show full 500 error in API when Gitea in dev mode (#11641) (#11753) + * Add missing templates for Matrix system webhooks (#11729) (#11748) + * Fix verification of subkeys of default gpg key (#11713) (#11747) + * Fix styling for commiter on diff view (#11715) (#11744) + * Properly truncate system notices (#11714) (#11742) + * Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718) + * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11682) + * Doctor check & fix db consistency (#11111) (#11676) + * Exclude generated files from language statistics (#11653) (#11670) + * Return json on 500 error from API (#11574) (#11659) + * When must change password only show Signout (#11600) (#11637) + * Backport various styling fixes (#11619) + * Fix wrong milestone in webhook message (#11596) (#11611) + * Fix serviceworker output file and misc improvements (#11562) (#11610) + * When initialising repositories ensure that the user doing the creation is the initializer (#11601) (#11608) + * Prevent empty query parameter being set on dashboard (#11561) (#11604) + * Fix images in wiki edit preview (#11546) (#11602) + * Prevent (caught) panic on login (#11590) (#11597) + * Prevent transferring repos to invisible orgs (#11517) (#11549) + * Move serviceworker to workbox and fix SSE interference (#11538) (#11547) + * API PullReviewComment HTMLPullURL should return the HTMLURL (#11501) (#11533) + * Fix repo-list private and total count bugs (#11500) (#11532) + * Fix form action template substitutions on admin pages (backport #11519) (#11531) + * Fix a bug where the reaction emoji doesn't disappear. (#11489) (#11530) + * TrimSpace when reading InternalToken from a file (#11502) (#11524) + * Fix selected line color in arc-green (#11492) (#11520) + * Make localstorage read ssh or https correctly (#11483) (#11490) + * Check branch protection on IsUserAllowedToUpdate (#11448) + * Fix margin on attached segment headers when they are separated by other element (#11425) + * Fix webhook template when validation errors occur (#11421) + * Fix NPE in template due to missing signing key on commit page (#11392) + * Restore active background to Register button on Register page (#11390) + * Fix hook failure due to relative LFS_CONTENT_PATH (#11362) + * Correctly set the organization num repos (#11339) + * Prevent 500 with badly formed task list (#11328) + * Allow compare page to look up base, head, own-fork, forkbase-of-head (#11327) + * Handle panics that percolate up to the graceful module (#11291) + * Don't allow registration via the web form, when AllowOnlyExternalRegistration is True (#11248) + * Patch fomantic-ui to workaround build issue (#11244) + * Prevent panic during wrappedConn close at hammertime (#11219) + * On logout force redirect to start page (#11202) + * Fix creation of Organization repos by Users with max created personal repos (#11183) + * Add option to increase provided OAuth2 token maximum size (#11180) + * Log the indexer path on failure (#11172) + * Ensure that relative paths in edit preview work (#11143) + * Make API EditIssue and EditPullRequest issue notifications (#11123) + * Send 404 immediately for known public requests (#11117) + * Remove nil inserts in models (#11096) + * Add GetReviews() to RetryDownloader (#11093) + * Remove nonexistent serviceworker entries (#11091) + * Simplify and fix GetApprovalCounts (#11086) + * Fix wiki revision template and simplify some tmpl conditions (#11080) + * Make branch parameter optional for /api/v1/repos/{owner}/{repo}/contents/{filepath} (#11067) + * Align review-item svg octicons (#11065) + * Automatically remove Watches, Assignments, etc if user loses access due to being removed as collaborator or from a team (#10997) + * Users should not be able to prohibit their own login (#10970) + * Fix scrollbar issues in dropdowns (#10897) + * Change the order of issues.closed_by to list opening user first (#10876) + * Allow site admin to check /api/v1/orgs endpoints (#10867) + * Avoid logging []byte in queue failures - convert to string first (#10865) + * Use ErrKeyUnableToVerify if fail to calc fingerprint in ssh-keygen (#10863) + * Fix assignees double load bug (#10856) + * Handle push rejection in branch and upload (#10854) + * In authorized_keys use double-quote for windows compatibility (#10841) + * Fix milestone template (#10824) + * log.Fatal on failure to listen to SSH port (#10795) + * Fix forked repo has no icon and language stat. (#10791) + * Fix tag/release deletion (#10663) + * Fix webhook migration (#10641) + * Migration for deleting orphaned dependencies (#10617) + * Add migration to fix the old broken merge-bases (#10604) + * Update templates for Go 1.14 (#10596) + * Remove unnecessary parentheses in wiki/view template (#10583) + * Change default value of DefaultCommandExecutionTimeout to match docs (#10581) + * Handle panic in indexer initialisation better (#10534) + * Set correct content_type value for Gogs/Gitea webhooks (#9504) (#10456) + * Fixed wrong AppSubUrl in multiple templates (#10447) + * Fix profile page CSS (#10406) + * Inject SVG sprite via ajax (#10320) + * Fix migration information update bug when linked github account (#10310) + * Allow admin to check org membership by API for other users (#10201) + * Fix topics dropdown (#10167) + * Ensure DeleteUser is not allowed to Delete Orgs and visa versa (#10134) + * Fix IsErrPullClosed (#10093) + * Accept punctuation after simple+cross repository issue references (#10091) + * On merge of already closed PR redirect back to the pulls page (#10010) + * Fix crowdin update script (#9969) + * Fix pull view when head repository or head branch missed and close related pull requests when delete head repository or head branch (#9927) + * Add option to prevent LDAP from deactivating everything on empty search (#9879) + * Fix admin handling at merge of PR (#9749) + * err_admin_name_pattern_not_allowed String Clarification (#9731) + * Fix wrong original git service type on a migrated repository (#9693) + * Fix ref links in issue overviews for tags (#8742) +* ENHANCEMENTS + * Fix search form button overlap (#11840) (#11864) + * Make tabular menu styling consistent for arc-green (#11570) (#11798) + * Add option to API to update PullRequest base branch (#11666) (#11796) + * Increase maximum SQLite variables count to 32766 (#11696) (#11783) + * Update emoji dataset with skin tone variants (#11678) (#11763) + * Add logging to long migrations (#11647) (#11691) + * Change language statistics to save size instead of percentage (#11681) (#11690) + * Allow different HardBreaks settings for documents and comments (#11515) (#11599) + * Fix alignment for commits on dashboard (#11595) (#11680) + * Default MSSQL port 0 to allow automatic detection by default (#11642) (#11673) + * Handle expected errors in AddGPGkey API (#11644) (#11661) + * Close EventSource before unloading the page (#11539) (#11557) + * Ensure emoji render with regular font-weight (#11541) (#11545) + * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11542) + * Tweak reaction buttons (#11516) + * Use more toned colors for selected line (#11493) (#11511) + * Increase width for authors on commit view (#11441) + * Hide archived repos by default in repo-list (#11440) + * Better styling for code review comment textarea (#11428) + * Support view individual commit for wiki pages (#11415) + * Fix yellow background on active elements in code review (#11414) + * Better styling for code review comment form (#11413) + * Change install description on homepage (#11395) + * Ensure search action button is coalesced to adjacent input (#11385) + * Switch code editor to Monaco (#11366) + * Add paging and archive/private repository filtering to dashboard list (#11321) + * Changed image of openid-connect logo for better look on arc-green theme (#11312) + * Load Repo Topics on blame view too (#11307) + * Change the style in admin notice content view from `

` to `

` (#11301)
+  * Allow log.xxx.default to set logging settings for the default logger only (#11292)
+  * Automatically attempt auto recovery of broken disk queues (Update lunny/levelqueue to 0.3.0) (#11285)
+  * Make sendmail a Process and have default timeout (#11256)
+  * Check value of skip-repository flag in dump command (#11254)
+  * Fix submit review form (#11252)
+  * Allow unauthenticated users to compare (#11240)
+  * Add EventSource support (#11235)
+  * Refactor Milestone related (#11225)
+  * Add pull review API endpoints (#11224)
+  * Add a 'this' to issue close/reopened messages (#11204)
+  * When migrating from Gitlab map Approvals to approving Reviews (#11147)
+  * Improve representation of attachments in issues (#11141)
+  * Protect default branch against deletion (#11115)
+  * Add X-Total-Count on /repos/{owner]/{repo}/pulls API endpoint (#11113)
+  * Fix status label on branches list vertical alignment (#11109)
+  * Add single release page and latest redirect (#11102)
+  * Add missing commit states to PR checks template (#11085)
+  * Change icon on title for merged PR to git-merge (#11064)
+  * Add MergePull comment type instead of close for merge PR (#11058)
+  * Upgrade jQuery to 3.5.0, remove jQuery-Migrate, fix deprecations (#11055)
+  * Consolidate author name across timeline (#11053)
+  * Refactor UpdateOAuth2Application (#11034)
+  * Support unicode emojis and remove emojify.js (#11032)
+  * Add git hook "warning" to admin panel (#11030)
+  * Add flash notify for email preference setting success (#11027)
+  * Remove package code.gitea.io/gitea/modules/git import out of models (#11025)
+  * Match arc-green code tag color to code blocks (#11023)
+  * Move syntax highlighting to web worker (#11017)
+  * Prevent merge of outdated PRs on protected branches (#11012)
+  * Add Get/Update for api/v1/user/applications/oauth2 (#11008)
+  * Upgrade to most recent bluemonday (#11007)
+  * Tweak code tags in markdown (#11000)
+  * Reject duplicate AccessToken names (#10994)
+  * Fix Ctrl-Enter shortcut for issues (#10986)
+  * Provide `OwnerName` field for README template (#10981)
+  * Prettify Timeline (#10972)
+  * Add issue subscription check to API (#10967)
+  * Use AJAX for notifications table (#10961)
+  * Adjust label padding (#10957)
+  * Avoiding directory execution on hook (#10954) (#10955)
+  * Migrate ActivityHeatmap to Vue SFC (#10953)
+  * Change merge strategy: do not check write access if user in merge white list (#10951)
+  * Enable GO111MODULE=on globally in Makefile (#10939)
+  * API endpoint to get single commit via SHA and Ref (#10915)
+  * Add accordion to release list and hide non-latest (#10910)
+  * Split dashboard elements into separate template files (#10885)
+  * Add more message on sidebar menus (#10872)
+  * Set MySQL rowtype to dynamic for new tables (#10833)
+  * Completely fix task-list checkbox styling (#10798)
+  * Hide gear icon for user who can't use them on sidebar (#10750)
+  * Refactor Cron and merge dashboard tasks (#10745)
+  * Change review status icons on pr view style to github style (#10737)
+  * Make pagination optional for API list notification endpoints (#10714)
+  * Fix tab indentation in code view (#10671)
+  * Fix task-list checkbox styling (#10668)
+  * Multiple LFS improvements (#10667)
+  * Make PR message on pushes configurable (#10664)
+  * Move dropzone.js to npm/webpack (#10645)
+  * Ensure Update button is enabled even when CI has failed (#10640)
+  * Add restricted user filter to LDAP authentication (#10600)
+  * Add Yandex OAuth2 provider (#8335) (#10564)
+  * Make avatar lookup occur at image request (#10540)
+  * Prevent accidental selection of language stats bar (#10537)
+  * Add fluid-icon (#10491)
+  * Inform participants on UI too (#10473)
+  * Build with go 1.14 (and raise minimum go version to 1.12) (#10467)
+  * Add max-file-size to LFS (#10463)
+  * Enable paggination for ListRepoTags API (#10454)
+  * Update JS dependencies (#10450)
+  * Show the username as a fallback on feeds if full name is blank (#10438)
+  * Various dark theme fixes (#10416)
+  * Display pull request head branch even the branch deleted or repository deleted (#10413)
+  * Prevent Firefox from using apple-touch-icon (#10402)
+  * Fix input[type=file] on dark theme (#10382)
+  * Improve mobile review-box sizing (#10297)
+  * Notification: queue ui.go notification-service (#10281)
+  * Add detected file language to code search (#10256)
+  * Index code and stats only for non-empty repositories (#10251)
+  * Add Approval Counts to pulls list (#10238)
+  * Limit label list height on edit issue page (#10216)
+  * Improve 404 error message (#10214)
+  * Tweak locale to respect singular conflicting file message in PR list (#10177)
+  * Fix commit view (#10169)
+  * Reorganize frontend files and tooling (#10168)
+  * Allow emoji on popup label (#10166)
+  * ListIssues add filter for milestones API (#10148)
+  * Show if a PR has conflicting files on the PR lists (#10130)
+  * Fix inconsistent label color format in API (#10129)
+  * Show download count info in release list (#10124)
+  * Add Octicon SVG spritemap (#10107)
+  * Update aria-fixed semantic-dropdown to fomantic master (#10096)
+  * Fix apple-touch-icon, regenerate images (#10065)(#10006)
+  * Style blockquote for default issue mail template (#10024)
+  * More expansions in template repositories (#10021)
+  * Allow list collaborators for users with Read access to repo (#9995)
+  * Add explicit dimensions to navbar avatar (#9986)
+  * Remove loadCSS and preload woff2 icon fonts (#9976)
+  * Fix commit view JS features, reimplement folding (#9968)
+  * Fix review avatar image (#9962)
+  * Improve notification pager (#9821)
+  * Move jquery and jquery-migrate to npm/webpack (#9813)
+  * Change font to Roboto to support more charsets (#9803)
+  * Move mailer to use a queue (#9789)
+  * Issue search on my related repositories (#9758)
+  * Add "before" query to ListIssueComments and ListRepoIssueComments API (#9685)
+  * Move tracked time api convert to convert package (#9665)
+  * Improve PR info in default merge message (#9635)
+  * Granular webhook events (#9626)
+  * Add Reviewed-on in commit message (#9623)
+  * Add top author stats to activity page (#9615)
+  * Allow repo admin to merge PR regardless of review status (#9611)
+  * Migrate reactions when migrating repository from github (#9599)
+  * API orgEditTeam make Fields optional (#9556)
+  * Move create/fork repository from models to modules/repository (#9489)
+  * Migrate reviews when migrating repository from github (#9463)
+  * Times API add filters (#9373)
+  * Move push commits from models to modules/repository (#9370)
+  * Add API endpoint to check notifications [Extend #9488] (#9595)
+  * Add GET /orgs API endpoint (#9560)
+  * API add/generalize pagination (#9452)
+  * Make create org repo API call same as github (#9186)
+* BUILD
+  * Turn off go modules for xgo and gxz (#10963)
+  * Add gitea-vet (#10948)
+  * Rename scripts to build and add revive command as a new build tool command (#10942)
+  * Add 'make lint', restructure 'compliance' pipeline (#10861)
+  * Move JS build dependencies to 'dependencies' (#10763)
+  * Use whitelist to find go files, run find only once (#10594)
+  * Move vue and vue-calendar-heatmap to npm/webpack (#10188)
+  * Move jquery.are-you-sure to npm/webpack (#10063)
+  * Move highlight.js to npm/webpack (#10011)
+  * Generate Bindata if TAGS="bindata" and not up-to-date (#10004)
+  * Move CSS build to webpack (#9983)
+  * Move fomantic target, update 'make help' (#9945)
+  * Add css extraction and minification to webpack (#9944)
+  * Misc webpack tweaks (#9924)
+  * Make node_modules a order-only prerequisite (#9923)
+  * Update documentation for the go module era (#9751)
+  * Move swagger-ui to webpack/npm and update it to 3.24.3 (#9714)
+  * Use npm to manage fomantic and only build needed components (#9561)
+* MISC
+  * Add gnupg to Dockerfile (#11365)
+  * Update snapcraft.yaml for core18 and latest features (#11300)
+  * Update JS dependencies, min Node.js version 10.13 (#11246)
+  * Change default charset for MySQL on install to utf8mb4 (#10989)
+  * Return issue subscription status from API subscribe (#10966)
+  * Fix queue log param (#10733)
+  * Add warning when using relative path to app.ini (#10104)
+
+## [1.11.7](https://github.com/go-gitea/gitea/releases/tag/v1.11.7) - 2020-06-18
+
+* BUGFIXES
+  * Use ID or Where to instead directly use Get when load object from database (#11925) (#11935)
+  * Fix __webpack_public_path__ for 1.11 (#11907)
+  * Fix verification of subkeys of default gpg key (#11713) (#11902)
+  * Remove unnecessary parentheses in wiki/view template (#11781)
+  * Doctor fix xorm.Count nil on sqlite error (#11741)
+
+## [1.11.6](https://github.com/go-gitea/gitea/releases/tag/v1.11.6) - 2020-05-30
+
+* SECURITY
+  * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11683)
+  * Use session for retrieving org teams (#11438) (#11439)
+* BUGFIXES
+  * Return json on 500 error from API (#11574) (#11660)
+  * Fix wrong milestone in webhook message (#11596) (#11612)
+  * Prevent (caught) panic on login (#11590) (#11598)
+  * Fix commit page js error (#11527)
+  * Use media links for img in post-process (#10515) (#11504)
+  * Ensure public repositories in private organizations are visible and fix admin organizations list (#11465) (#11475)
+  * Set correct Content-Type value for Gogs/Gitea webhooks (#9504) (#10456) (#11461)
+  * Allow all members of private orgs to see public repos (#11442) (#11459)
+  * Whenever the ctx.Session is updated, release it to save it before sending the redirect (#11456) (#11457)
+  * Forcibly clean and destroy the session on logout (#11447) (#11451)
+  * Fix /api/v1/orgs/* endpoints by changing parameter to :org from :orgname (#11381)
+  * Add tracked time fix to doctor (part of #11111) (#11138)
+  * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11544)
+  * Remove unnecessary parentheses in wiki/revision.tmpl to allow 1.11 to build on go1.14  (#11481)
+
+## [1.11.5](https://github.com/go-gitea/gitea/releases/tag/v1.11.5) - 2020-05-09
+
+* BUGFIXES
+  * Prevent timer leaks in Workerpool and others (#11333) (#11340)
+  * Fix tracked time issues (#11349) (#11354)
+  * Add NotifySyncPushCommits to indexer notifier (#11309) (#11338)
+  * Allow X in addition to x in tasks (#10979) (#11335)
+  * When delete tracked time through the API return 404 not 500 (#11319) (#11326)
+  * Prevent duplicate records in organizations list when creating a repository (#11303) (#11325)
+  * Manage port in submodule refurl (#11305) (#11323)
+  * api.Context.NotFound(...) should tolerate nil (#11288) (#11306)
+  * Show pull request selection even when unrelated branches (#11239) (#11283)
+  * Repo: milestone: make /milestone/:id endpoint accessible (#11264) (#11282)
+  * Fix GetContents(): Dont't ignore Executables (#11192) (#11209)
+  * Fix submodule paths when AppSubUrl is not root (#11098) (#11176)
+  * Prevent clones and pushes to disabled wiki (#11131) (#11134)
+  * Remove errant third closing curly-bracket from account.tmpl and send account ID in account.tmpl (#11130)
+  * On Repo Deletion: Delete related TrackedTimes too (#11110) (#11125)
+  * Refresh codemirror on show pull comment tab (#11100) (#11122)
+  * Fix merge dialog on protected branch with missing required statuses (#11074) (#11084)
+  * Load pr Issue Poster on API too (#11033) (#11039)
+  * Fix release counter on API repository info (#10968) (#10996)
+  * Generate Diff and Patch direct from Pull head (#10936) (#10938)
+  * Fix rebase conflict detection in git 2.26 (#10929) (#10930)
+* ENHANCEMENT
+  * Fix 404 and 500 image size in small size screen (#11043) (#11049)
+  * Multiple Gitea Doctor improvements (#10943) (#10990) (#10064) (#9095) (#10991)
+
+## [1.11.4](https://github.com/go-gitea/gitea/releases/tag/v1.11.4) - 2020-04-01
+
+* BUGFIXES
+  * Only update merge_base if not already merged (#10909)
+  * Fix milestones too many SQL variables bug (#10880) (#10904)
+  * Protect against NPEs in notifications list (#10879) (#10883)
+  * Convert plumbing.ErrObjectNotFound to git.ErrNotExist in getCommit (#10862) (#10868)
+  * Convert plumbing.ErrReferenceNotFound to git.ErrNotExist in GetRefCommitID (#10676) (#10797)
+  * Account for empty lines in receive-hook message (#10773) (#10784)
+  * Fix bug on branch API (#10767) (#10775)
+  * Migrate to go-git/go-git v5.0.0 (#10735) (#10753)
+  * Fix hiding of fields in authorization source page (#10734) (#10752)
+  * Prevent default for linkAction (#10742) (#10743)
+
+## [1.11.3](https://github.com/go-gitea/gitea/releases/tag/v1.11.3) - 2020-03-10
+
+* BUGFIXES
+  * Prevent panic in stopwatch (#10670) (#10673)
+  * Fix bug on pull view when required status check no ci result (#10648) (#10651)
+  * Build explicitly with Go 1.13 (#10684)
+
+## [1.11.2](https://github.com/go-gitea/gitea/releases/tag/v1.11.2) - 2020-03-06
+
+* BREAKING
+  * Various fixes in login sources (#10428) (#10429)
+* SECURITY
+  * Ensure only own addresses are updated (#10397) (#10399)
+  * Logout POST action (#10582) (#10585)
+  * Org action fixes and form cleanup (#10512) (#10514)
+  * Change action GETs to POST (#10462) (#10464)
+  * Fix admin notices (#10480) (#10483)
+  * Change admin dashboard to POST (#10465) (#10466)
+  * Update markbates/goth (#10444) (#10445)
+  * Update crypto vendors (#10385) (#10398)
+* BUGFIXES
+  * Allow users with write permissions to modify issue descriptions and comments. (#10623) (#10626)
+  * Handle deleted base branch in PR (#10618) (#10619)
+  * Delete dependencies when deleting a repository (#10608) (#10616)
+  * Ensure executable bit is kept on the web editor (#10607) (#10614)
+  * Update mergebase in pr checker (#10586) (#10605)
+  * Fix release attachments being deleted while upgrading (#10572) (#10573)
+  * Fix redirection path if Slack webhook channel is invalid (#10566)
+  * Fix head.tmpl og:image picture location (#10531) (#10556)
+  * Fix 404 after activating secondary email (#10547) (#10553)
+  * Show Signer in commit lists and add basic trust (#10425 & #10511) (#10524)
+  * Fix potential bugs (#10513) (#10518)
+  * Use \[:space:\] instead of \\s (#10508) (#10509)
+  * Avoid mailing users that have explicitly unwatched an issue (#10475) (#10500)
+  * Handle push rejection message in Merge & Web Editor (#10373) (#10497)
+  * Fix SQLite concurrency problems by using BEGIN IMMEDIATE (#10368) (#10493)
+  * Fix double PR notification from API (#10482) (#10486)
+  * Show the username as a fallback on feeds if full name is blank (#10461)
+  * Trigger webhooks on issue label-change via API too (#10421) (#10439)
+  * Fix git reference type in webhooks (#10427) (#10432)
+  * Prevent panic on merge to PR (#10403) (#10408)
+  * Fix wrong num closed issues on repository when close issue via commit… (#10364) (#10380)
+  * Reading pull attachments should depend on read UnitTypePullRequests (#10346) (#10354)
+  * Set max-width on review-box comment box (#10348) (#10353)
+  * Prevent nil pointer in GetPullRequestCommitStatusState (#10342) (#10344)
+  * Fix protected branch status check settings (#10341) (#10343)
+  * Truncate long commit message header (#10301) (#10319)
+  * Set the initial commit status to Success otherwise it will always be Pending (#10317) (#10318)
+  * Don't manually replace whitespace during render (#10291) (#10315)
+* ENHANCEMENT
+  * Admin page for managing user e-mail activation (#10557) (#10579)
+
+## [1.11.1](https://github.com/go-gitea/gitea/releases/tag/v1.11.1) - 2020-02-15
+
+* BUGFIXES
+  * Repo name added to automatically generated commit message when merging (#9997) (#10285)
+  * Fix Workerpool deadlock (#10283) (#10284)
+  * Divide GetIssueStats query in smaller chunks (#10176) (#10282)
+  * Fix reply on code review (#10257)
+  * Stop hanging issue indexer initialisation from preventing shutdown (#10243) (#10249)
+  * Fix filter label emoji width (#10241) (#10244)
+  * Fix issue sidebar menus having an infinite height (#10239) (#10240)
+  * Fix commit between two commits calculation if there is only last commit (#10225) (#10226)
+  * Only check for conflicts/merging if the PR has not been merged in the interim (#10132) (#10206)
+  * Blacklist manifest.json & milestones user (#10292) (#10293)
+
+## [1.11.0](https://github.com/go-gitea/gitea/releases/tag/v1.11.0) - 2020-02-10
+
+* BREAKING
+  * Fix followers and following tabs in profile (#10202) (#10203)
+  * Make CertFile and KeyFile relative to CustomPath (#9868) (#9874)
+  * Remove unused endpoints (#9538)
+  * Prefix all user-generated IDs in markup (#9477)
+  * Enforce Gitea environment for pushes (#8982)
+  * Hide some user information via API if user have not enough permissions (#8655)
+  * Move startpage/homepage translation to crowdin (#8596)
+* SECURITY
+  * Never allow an empty password to validate (#9682) (#9683)
+  * Prevent redirect to Host (#9678) (#9679)
+  * Swagger hide search field (#9554)
+  * Add "search" to reserved usernames (#9063)
+  * Switch to fomantic-ui (#9374)
+  * Only serve attachments when linked to issue/release and if accessible by user (#9340)
+* FEATURES
+  * Webhooks should only show sender if it makes sense (#9601)
+  * Provide Default messages for merges (#9393)
+  * Add description to labels on create issue (#9392)
+  * Graceful Queues: Issue Indexing and Tasks (#9363)
+  * Default NO_REPLY_ADDRESS to DOMAIN (#9325)
+  * Allow FCGI over unix sockets (#9298)
+  * Graceful: Xorm, RepoIndexer, Cron and Others (#9282)
+  * Add API for Reactions (#9220)
+  * Graceful: Cancel Process on monitor pages & HammerTime (#9213)
+  * Graceful: Allow graceful restart for unix sockets (#9113)
+  * Graceful: Allow graceful restart for fcgi (#9112)
+  * Sign protected branches (#8993)
+  * Add Graceful shutdown for Windows and hooks for shutdown of goroutines (#8964)
+  * Add Gitea icon to Emojis (#8950)
+  * Expand/Collapse Files and Blob Excerpt while Reviewing/Comparing code (#8924)
+  * Allow Custom Reactions (#8886)
+  * Close/reopen issues by keywords in titles and comments (#8866)
+  * Allow incompletely specified Time Formats (#8816)
+  * Prevent upload (overwrite) of lfs locked file (#8769)
+  * Template Repositories (#8768)
+  * Add /milestones endpoint (#8733)
+  * Make repository management section handle lfs locks (#8726)
+  * Respect LFS File Lock on UI (#8719)
+  * Add team option to grant rights for all organization repositories (#8688)
+  * Enabling and disabling the commit button to prevent empty commits (web editor) (#8590)
+  * Add setting to disable BASIC authentication (#8586)
+  * Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528)
+  * Allow Protected Branches to Whitelist Deploy Keys (#8483)
+  * Push to create repo (#8419)
+  * Sign merges, CRUD, Wiki and Repository initialisation with gpg key (#7631)
+  * Add basic repository lfs management (#7199)
+* BUGFIXES
+  * Fix code-expansion arc-green theme bug (#10180) (#10185)
+  * Prevent double wait-group decrement (#10170) (#10175)
+  * Allow emoji on review head comments (#10159) (#10174)
+  * Fix issue/pull link (#10158) (#10173)
+  * Fix push-create SSH bugs (#10145) (#10151)
+  * Prevent DeleteUser API abuse (#10125) (#10128)
+  * Fix issues/pulls dashboard paging error (#10114) (#10115)
+  * Add button to revert SimpleMDE to plain textarea (#10099) (#10102)
+  * Fix branch page pull request title and link error (#10092) (#10097)
+  * Fix PR API: Only try to get HeadBranch if HeadRepo exist (#10029) (#10088)
+  * Update topics repo count when deleting repository (#10051) (#10081)
+  * Show pull icon on pull requests (#10061) (#10062)
+  * Fix milestone API state parameter unhandled (#10049) (#10052)
+  * Move to using a temporary repo for pushing new PRs (#10009) (#10042)
+  * Fix wiki raw view on sub path (#10002) (#10040)
+  * Ensure that feeds are appropriately restricted (#10018) (#10019)
+  * Sanitize credentials in mirror form (#9975) (#9991)
+  * Close related pull requests when deleting head repository or head branch (#9927) (#9974)
+  * Switch to use -f instead of -F for sendmail (#9961) (#9970)
+  * Fix file rename/copy not supported by indexer (#9965) (#9967)
+  * Fix repo indexer not updating upon push (#9957) (#9963)
+  * Don't convert ellipsis in markdown (#9905) (#9937)
+  * Fixed repo link in generated comment for cross repository dependency (#9863) (#9935)
+  * Check if diff actually contains sections when rendering (#9926) (#9933)
+  * Fix wrong hint when status checking is running on pull request view (#9886) (#9928)
+  * Fix RocketChat (#9908) (#9921)
+  * Do not try to recreate ldap user if they are already created (#9900) (#9919)
+  * Create terminated channel in queue_redis (#9910) (#9911)
+  * Prevent empty LDAP search result from deactivating all users (#9879) (#9896)
+  * Fix wrong permissions check when issues/prs shared operations (#9885) (#9889)
+  * Check user != nil before checking values (#9881) (#9883)
+  * Allow hyphen in language name (#9873) (#9880)
+  * Ensure that 2fa is checked on reset-password (#9857) (#9876)
+  * Fix issues/pulls dependencies problems (#9842) (#9864)
+  * Fix markdown anchor links (#9673) (#9840)
+  * Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9837)
+  * Fix download file wrong content-type (#9825) (#9834)
+  * Fix wrong poster identity on a migrated pull request when submit review (#9827) (#9830)
+  * Fix database dump when log directory is missing (#9818) (#9819)
+  * Fix compare (#9808) (#9814)
+  * Fix push-to-create (#9772) (#9797)
+  * Fix missing msteam webhook on organization (#9781) (#9794)
+  * Fix missing unlock in uniquequeue (#9790) (#9791)
+  * Fix add team on collaborator page when same name as organization (#9778)
+  * DeleteRepoFile incorrectly handles Delete to new branch (#9769) (#9775)
+  * Fix milestones page (#9771)
+  * Fix SimpleMDE quote reply (#9757) (#9768)
+  * Fix missing updated time on migrated issues and comments (#9744) (#9764)
+  * Move Errored PRs out of StatusChecking (#9675) (#9726)
+  * Make hook status printing configurable with delay (#9641) (#9725)
+  * ​Fix /repos​/issues​/search (#9698) (#9724)
+  * Silence fomantic error regarding tabs (#9713) (#9718)
+  * Remove unused lock (#9709) (#9710)
+  * Remove q.lock.Unlock() in setInternal to prevent panic (#9705) (#9706)
+  * Load milestone in API PR list (#9671) (#9700)
+  * Don't attempt to close issue if already closed (#9696) (#9699)
+  * Remove google font call (#9668) (#9681)
+  * Eliminate horizontal scroll caused by footer (#9674)
+  * Fix nil reference in repo generation (#9660) (#9666)
+  * Add HTML URL to API Issues (#9654) (#9661)
+  * Add PR review webhook to Telegram (#9653) (#9655)
+  * Use filepath.IsAbs instead of path.IsAbs (#9651) (#9652)
+  * Disable remove button on repository teams when have access to all (#9640)
+  * Clean up old references on branch delete (#9614)
+  * Hide public repos owned by private orgs (#9609)
+  * Fix access issues on milestone and issue overview pages. (#9603)
+  * Fix error logged when repos qs is empty (#9591)
+  * Dont trigger notification twice on issue assignee change (#9582)
+  * Fix mirror pushed commit actions (#9572)
+  * Allow only specific columns to be updated on issue via API (#9189) (#9539)
+  * Fix default avatar for ghost user (#9536)
+  * Fix download of release attachments with same name (#9529)
+  * Resolve deprecated INI conversion (#9525)
+  * Ignore empty avatars during database migration (#9520)
+  * Fix deleted branch isn't removed when push the branch again (#9516)
+  * Fix repository issues pagination bug when there are more than one label filter (#9512)
+  * Fix SetExpr failed (#9506)
+  * Remove obsolete file private/push_update.go (#9503)
+  * When recreating hooks, delete them first so they are recreated with the umask (#9502)
+  * Properly enforce gitea environment for pushes (#9501)
+  * Fix datarace on repo indexer queue (#9490)
+  * Add call to load repo prior to redirect in add/remove dependency code (#9484)
+  * Wrap the code indexer (#9476)
+  * Use Req.URL.RequestURI() to cope with FCGI urls (#9473)
+  * Set default ssh.minimum_key_sizes (#9466)
+  * Fixed issue with paging in /repos/{owner}/{repo}/git/trees/{sha} api (#9459)
+  * Fix wrong notification on merge (#9450)
+  * Issue with Migration rule v111 (#9449)
+  * Trigger webhook when deleting a branch after merging a PR (#9424)
+  * Add migration to sanitize repository original_url (#9423)
+  * Use OriginalURL instead of CloneAddr in migration logging (#9418)
+  * Push update after branch is restored (#9416)
+  * Fix wrong migration (#9381)
+  * Fix show repositories filter (#9234) (#9379)
+  * Fix Slack webhook payload title generation to work with Mattermost (#9378)
+  * Fix double webhook for new PR (#9375)
+  * AuthorizedKeysCommand should not query db directly (#9371)
+  * Fix missed change to GetManager() (#9361)
+  * Fix cache problem on dashboard (#9358)
+  * RepoIndexer: DefaultBranch needs to be prefixed by BranchPrefix (#9356)
+  * Fix protected branch using IssueID (#9348)
+  * Fix nondeterministic behavior (#9341)
+  * Fix PR/issue redirects when having external tracker (#9339)
+  * Remove release attachments which repository has been deleted (#9334)
+  * Fix issue indexer not triggered when migrating a repository (#9332)
+  * Add SyncTags to uploader interface (#9326)
+  * Fix bug that release attachment files not deleted when deleting repository (#9322)
+  * Only sync tags after all migration release batches are completed (#9319)
+  * File Edit: Author/Committer interchanged (#9297)
+  * prebuild CSS/JS before xgo release binaries (#9293)
+  * Log: Ensure FLAGS=none shows no flags (#9287)
+  * Make Diff Detail on Pull Request Changed File UI always on Top (#9280)
+  * Switch CSS minifier to cssnano (#9260)
+  * Fix latest docker image haven't include static files. (#9252)
+  * Don't link wiki revision to commit (#9244)
+  * Change review content column to type text in db (#9229)
+  * Fixed topic regex pattern and added search by topic links after save (#9219)
+  * Add language to user API response (#9215)
+  * Correct tooltip message blocked by dependencies (#9211)
+  * Add SimpleMDE and Fix Image Paste for Issue/Comment Editor (#9197)
+  * Fix panic when diff (#9187)
+  * Fix #9151 - smtp logger configuration sendTos should be an array (#9154)
+  * Fix max length check and limit in multiple repo forms (#9148)
+  * Always Show Password Field on Link Account Sign-in Page (#9147)
+  * Properly fix displaying virtual session provider in admin panel (#9137)
+  * Fix race condition on indexer (#9136)
+  * Fix team links in HTML rendering (#9127)
+  * Fix race condition in ReplaceSanitizer (#9123)
+  * Fix what information is shown about user in API (#9115)
+  * Fix nil context user for template repositories (#9099)
+  * Hide given credentials for migrated repos. (#9097)
+  * Fix reCAPTCHA API URL (#9083)
+  * Fix password checks on admin create/edit user (#9076)
+  * Update golang.org/x/crypto vendor to use acme v2 (#9056)
+  * Ensure Written is set in GZIP ProxyResponseWriter (#9018)
+  * Fix wrong system notice when repository is empty (#9010)
+  * Fix broken link to branch from issue list (#9003)
+  * Fix bug when pack js (#8992)
+  * New review approvals shouldn't require a message (#8991)
+  * Shadow password correctly for session config (#8984)
+  * Don't send notification on pending reviews (#8943)
+  * Fix Notify Create Ref Error on tag creation (#8936)
+  * Convert EOL to UNIX-style to render MD properly (#8925)
+  * Migrate temp_repo.go to use git.NewCommand  (#8918)
+  * Fix issue with user.fullname (#8902)
+  * Add Close() method to gogitRepository (#8901)
+  * Enable punctuations ending mentions (#8889)
+  * Fix password complexity check on registration (#8887)
+  * Fix require external registration password (#8885)
+  * Fix edit content button on migrated issue content (#8877)
+  * Fix permission checks for close/reopen from commit (#8875)
+  * Fix API Bug (fail on empty assignees) (#8873)
+  * Stop using git count-objects and use raw directory size for repository (#8848)
+  * Fix count for commit graph last page (#8843)
+  * Fix to close opened io resources as soon as not needed (#8839)
+  * Improve notification (#8835)
+  * Fix new user form for non-local users (#8826)
+  * Fix: remove duplicated signed commit icons (#8820)
+  * Fix (open/closed) issue count when label excluded (#8815)
+  * Fix SSH2 conditional in key parsing code (#8806)
+  * Fix 500 when edit hook (#8782)
+  * On windows set core.longpaths true (#8776)
+  * Fix commit expand button to not go to commit link (#8745)
+  * Avoid re-issuing redundant cross-references. (#8734)
+  * Fix milestone close timestamp function (#8728)
+  * Move webhook codes from service to webhook notification (#8712)
+  * Show zero lines on the line counter if the file empty (#8700)
+  * Fix deadline on update issue or PR via API (#8696)
+  * make call createMilestoneComment on newIssue func (#8678)
+  * Send tag create and push webhook when release created on UI (#8671)
+  * Prevent chrome download page as html with alt + click (#8669)
+  * Fix 500 when getting user as unauthenticated user (#8653)
+  * Graceful fixes (#8645)
+  * Add SubURL to redirect path (#8632) (#8634)
+  * Fix extra columns from `label` table (#8633)
+  * Add SubURL to redirect path for transferred/renamed repos (#8632)
+  * Fix bug when migrate from API (#8631)
+  * Allow to merge if file path contains " or \ (#8629)
+  * Prevent removal of non-empty emoji panel following selection of duplicate (#8609)
+  * Ensure default gpg settings not nil and found commits have reference to repo (#8604)
+  * Set webhook Content-Type for application/x-www-form-urlencoded (#8599)
+  * Fix #8582 by handling empty repos (#8587)
+  * Fix of the diff statistics view on pull request's (#8581)
+  * Fix bug on pull requests when transfer head repository (#8564)
+  * Fix template error on account page (#8562)
+  * Allow externalID to be UUID (#8551)
+  * Fix ignored error on editorconfig api (#8550)
+  * Fix user avatar name (#8547)
+  * Ensure that GitRepo is set on Empty repositories (#8539)
+  * Add missed close in ServeBlobLFS (#8527)
+  * Fix migrate mirror 500 bug (#8526)
+  * Fix password complexity regex for special characters (on master) (#8525)
+* ENHANCEMENTS
+  * Explicitly refer to PR in squash-merge commit message in case of external tracker (#9844) (#9855)
+  * Add a /user/login landing page option (#9622)
+  * Some more e-mail notification fixes (#9596)
+  * Add branch protection option to block merge on requested changes. (#9592)
+  * Add footer extra links template (#9576)
+  * Fix for a wrong URL in activity page of repository.  (#9571)
+  * Update default issue template (#9568)
+  * Change markdown rendering from blackfriday to goldmark  (#9533)
+  * Extend file create api with dates (#9464)
+  * Add ActionCommentPull action (#9456)
+  * Response for context on retry database connection (#9444)
+  * Refactor webhooks to reduce code duplication (#9422)
+  * update couchbase deps for new license (#9419)
+  * Add .ignore file for search tools (#9417)
+  * Remove unsued struct (#9405)
+  * Hide not allowed Reactions (#9387)
+  * Remove text from action-only webhooks (#9377)
+  * Move PushToBaseRepo from models to services/pull (#9352)
+  * Site admin could view org's members (#9346)
+  * Sleep longer if request speed is over github limitation (#9335)
+  * Refactor comment (#9330)
+  * Refactor code indexer (#9313)
+  * Remove SavePatch and generate patches on the fly (#9302)
+  * Move some pull request functions from models to services (#9266)
+  * Update JS dependencies (#9255)
+  * Show label list on label set (#9251)
+  * Redirect issue if repo has configured external tracker. (#9247)
+  * Allow kbd tags (#9245)
+  * Remove unused comment actions (#9222)
+  * Fixed errors logging in dump.go (#9218)
+  * Expose release counter to repo API response (#9214)
+  * Make consistent links to repository in the Slack/Mattermost notificiations (#9205)
+  * Expose pull request counter to repo API response (#9202)
+  * Extend TrackedTimes API (#9200)
+  * Extend StopWatch API (#9196)
+  * Move code indexer related code to a new package (#9191)
+  * Docker: ask s6 to stop all service when gitea stop (#9171)
+  * Variable expansion in repository templates (#9163)
+  * Add avatar and issue labels to template repositories (#9149)
+  * Show single review comments in the PR conversation tab (#9143)
+  * Extract createComment (#9125)
+  * Move PushUpdateOptions from models to repofiles (#9124)
+  * Alternate syntax for cross references (#9116)
+  * Add USE_SERVICE_WORKER setting (#9110)
+  * Only show part of members on orgnization dashboard and add paging for orgnization members page (#9092)
+  * Explore page: Add topic param to pagination (#9077) (#9078)
+  * Markdown: Sanitizier Configuration (#9075)
+  * Add password requirement info on error (#9074)
+  * Allow authors to use act keywords in PR content (#9059)
+  * Move modules/gzip to gitea.com/macaron/gzip (#9058)
+  * Branch protection: Possibility to not use whitelist but allow anyone with write access (#9055)
+  * Context menus for comments, add quote reply (#9043)
+  * Update branch API endpoint to show effective branch protection. (#9031)
+  * Move git graph from models to modules/graph (#9027)
+  * Move merge actions to notification (#9024)
+  * Move mirror sync actions to notification (#9022)
+  * Add retry for migration http/https requests (#9019)
+  * Rewrite delivery of issue and comment mails (#9009)
+  * Add review comments to mail notifications (#8996)
+  * Refactor pull request review (#8954)
+  * Githook highlighter (#8932)
+  * Add git hooks and webhooks to template repositories; move to services (#8926)
+  * Only view branch or tag if it match refType requested. (#8899)
+  * Drop Admin attribute based on LDAP when login (continue #1743) (#8849)
+  * Add additional periods to activity page (#8829)
+  * Update go-org to optimize code (#8824)
+  * Move some actions to notification/action (#8779)
+  * Webhook support custom proxy (#8760)
+  * Fix API deadline removal (#8759)
+  * Mark review comment as invalidated when file is deleted (#8751)
+  * Move pull list code to a separate file (#8748)
+  * Move webhook to a standalone package under modules (#8747)
+  * Multi repo select on issue page (#8741)
+  * apply exclude label on milestone issue list (#8739)
+  * Move issue notifications and assignee man (#8713)
+  * Move issue change content from models to service (#8711)
+  * Move issue change status from models to service (#8691)
+  * Move more issue assignee code from models to issue service (#8690)
+  * Create PR on Current Repository by Default (#8670)
+  * Improve Open Graph Protocol (#8637)
+  * Batch hook pre- and post-receive calls (#8602)
+  * Improve webhooks (#8583)
+  * Move transfer repository and rename repository on a service package and start action notification (#8573)
+  * Implement/Fix PR review webhooks (#8570)
+  * Rewrite markdown rendering to blackfriday v2 and rewrite orgmode rendering to go-org (#8560)
+  * Move some repositories' operations to a standalone service package (#8557)
+  * Allow more than 255 characters for tokens in external_login_user table (#8554)
+  * Move issue label operations to issue service package (#8553)
+  * Adjust error reporting from merge failures and use LC_ALL=C for git (#8548)
+  * Mail assignee when issue/pull request is assigned (#8546)
+  * Allow committing / adding empty files using the web ui (#8420) (#8532)
+  * Move sync mirror actions to mirror service package (#8518)
+  * Remove arrows on numeric inputs (#8516)
+  * Support inline rendering of CUSTOM_URL_SCHEMES (#8496)
+  * Recalculate repository access only for specific user (#8481)
+  * Add download button for rull request diff- and patch-file (#8470)
+  * Add single sign-on support via SSPI on Windows (#8463)
+  * Move change issue title from models to issue service package (#8456)
+  * Add included tag on  branch view (#8449)
+  * Make static resouces web browser cache time customized on app.ini (#8442)
+  * Enable Uploading/Removing Attachments When Editing an Issue/Comment (#8426)
+  * Add pagination to commit graph page (#8360)
+  * Use templates for issue e-mail subject and body (#8329)
+  * Move clearlabels from models to issue service (#8326)
+  * Move AddTestPullRequestTask to pull service package from models (#8324)
+  * Team permission to create repository in organization (#8312)
+  * Allows external rendering of other filetypes (#8300)
+  * Add 'Alt + click' feature to exclude labels (#8199)
+  * Configurable close and reopen keywords for PRs (#8120)
+  * Configurable URL for static resources (#7911)
+  * Unifies commit list in repository commit table and wiki revision page (#7907)
+  * Allow cross-repository dependencies on issues (#7901)
+  * Auto-subscribe user to repository when they commit/tag to it (#7657)
+  * Restore Graceful Restarting & Socket Activation (#7274)
+  * wiki - add 'write' 'preview' buttons to wiki edit like in issues (#7241)
+  * Change target branch for pull request (#6488)
+  * Display PR commits and diffs using base repo rather than forked (#3648)
+* TESTING
+  * Add debug option to serv to help debug problems (#9492)
+  * Fix the intermittent TestGPGGit failures (#9360)
+  * Testing: Update postgres sequences (#9304)
+  * Missed defer prepareTestEnv (#9285)
+  * Fix "data race" in testlogger (#9159)
+  * Yet another attempt to fix the intermittent failure of gpg git test (#9146)
+  * integrations: Fix Dropped Test Errors (#9040)
+  * services/mirror: fix dropped test errors (#9007)
+  * Fix intermittent GPG Git test failure (#8968)
+  * Update Github Migration Tests (#8893) (#8938)
+  * Update heatmap fixtures to restore tests (#8615)
+* TRANSLATION
+  * Fix Korean locales (#9761) (#9780)
+  * Fix placeholders in the error message (#9060)
+  * Fix spelling of admin.users.max_repo_creation (#8934)
+  * Improve german translation of homepage (#8549)
+* BUILD
+  * Fix webpack polyfills (#9735) (#9738)
+  * Update gitea.com/macaron to 1.4.0 (#9608)
+  * Upgrade lato fonts to v16. (#9498)
+  * Update alpine to 3.11 (#9440)
+  * Upgrade blevesearch (#9177)
+  * Remove built js/css files from git (#9114)
+  * Move semantic.dropdown.custom.js to webpack (#9064)
+  * Check compiled files during build (#9042)
+  * Enable lazy-loading of gitgraph.js (#9036)
+  * Pack web_src/js/draw.js to public/js/index.js (#8975)
+  * Modernize js and use babel (#8973)
+  * Move index.js to web_src and use webpack to pack them (#8598)
+  * Restrict modules/graceful to non-windows build and shim IsChild (#8537)
+  * Upgrade gopkg.in/editorconfig/editorconfig-core-go.v1 (#8501)
+* DOCS
+  * Swagger info corrections (#9441) (#9558)
+  * Add ALLOW_ONLY_EXTERNAL_REGISTRATION to config cheat sheet (#8986)
+  * Rephrase comment about RuntimeDirectory option in systemd config (#8912)
+  * Explicitly indicate the socket unit to use the service unit "gitea.service" (#8804)
+  * Adjust the must-change-password help (#8755)
+  * Add notice to docs for migrating from more recent versions of Gogs (#8724)
+  * Add explicit info about customization of homepage (#8694)
+  * Change external asciidoctor tool to embedded mode (#8677)
+  * Add Docker fail2ban configuration (#8642)
+  * Correct some outdated statements in the contributing guidelines (#8612)
+  * Basic Design guidelines (describing different parts of the code) (#8601)
+  * Display Gitea logo in Readme (#8592)
+  * Fix building from source docs to ref AppWorkPath (#8567)
+  * Update the provided gitea.service to mention socket activation (#8531)
+  * Doc added how to setup email (#8520)
+* MISC
+  * Backport Locales [2020-01-14] (#9773)
+  * Add translatable Powered by Gitea text in footer (#9600)
+  * Add contrib/environment-to-ini (#9519)
+  * Remove unnecessary loading of settings in update hook (#9496)
+  * Update gitignore list (#9437)
+  * Update license list (#9436)
+  * Fix background reactions in the arc-green theme (#9421)
+  * Update and fix chardet import (#9351)
+  * Ensure LF on checkouts and in editors (#9259)
+  * Fixed topics margin (#9248)
+  * Add comment to exported function WindowsServiceName (make revive) (#9241)
+  * Remove empty lines on issues/pulls page (#9232)
+  * Fix Add Comment Button's "+" Position (#9140)
+  * Add first issue comment hashtag (#9052)
+  * Change some label colors (#9051)
+  * Fix double scroll in branch dropdown (#9048)
+  * Add comment highlight when target from url (#9047)
+  * Update display of reactions to issues and comments (#9038)
+  * Button tooltip formatting under Branches (#9034)
+  * Allow setting default branch via API (#9030)
+  * Update dashboard context for PR reviews (#8995)
+  * Show repository size in repo home page and settings (#8940)
+  * Allow to add and remove all repositories to/from team. (#8867)
+  * Show due date in dashboard issues list (#8860)
+  * Theme arc-green: reverse heatmap colors (#8840)
+  * Project files table style update (#8757)
+  * gitignore debugging file from vscode (#8740)
+  * Add API for Issue set Subscription (#8729)
+  * Make 100% width search bar (#8710)
+  * Update color theme for heatmap (#8709)
+  * Add margin to title_wip_desc (#8705)
+  * Improve visibility of "Pending" indicator (#8685)
+  * Improve accessibility of dropdown menus (#8638)
+  * Make /users/{username}/repos list private repos the current user has access to (#8621)
+  * Prevent .code-view from overriding font on icon fonts (#8614)
+  * Add id references on all issue events to allow internal linking (#8608)
+  * Upgrade xorm to v0.8.0 (#8536)
+  * Upgrade gopkg.in/ini.v1 (#8500)
+  * Update CodeMirror to version 5.49.0 (#8381)
+  * Wiki editor: enable side-by-side button (#7242)
+
+## [1.10.6](https://github.com/go-gitea/gitea/releases/tag/v1.10.6) - 2020-03-10
+
+This is a re-tag version of v1.10.5 and also explicitly built with Go 1.13.
+
+WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should __not__ be used.
+
+## [1.10.5](https://github.com/go-gitea/gitea/releases/tag/v1.10.5) - 2020-03-06
+
+* BUGFIXES
+  * Fix release attachments being deleted while upgrading (#10572) (#10574)
+
+## [1.10.4](https://github.com/go-gitea/gitea/releases/tag/v1.10.4) - 2020-02-16
+
+* FEATURE
+  * Prevent empty LDAP search from deactivating all users (#9879) (#9890)
+* BUGFIXES
+  * Fix reply on code review (#10261) (#10227)
+  * Fix branch page pull request title and link error (#10092) (#10098)
+  * Fix milestone API state parameter unhandled (#10049) (#10053)
+  * Fix wiki raw view on sub path (#10002) (#10041)
+  * Fix RocketChat Webhook (#9908) (#9921) (#9925)
+  * Fix bug about wrong dependencies permissions check and other wrong permissions check (#9884) (Partial backport #9842)
+  * Ensure that 2fa is checked on reset-password (#9857) (#9877)
+
+## [1.10.3](https://github.com/go-gitea/gitea/releases/tag/v1.10.3) - 2020-01-17
+
+* SECURITY
+  * Hide credentials when submitting migration (#9102) (#9704)
+  * Never allow an empty password to validate (#9682) (#9684)
+  * Prevent redirect to Host (#9678) (#9680)
+  * Hide public repos owned by private orgs (#9609) (#9616)
+* BUGFIXES
+  * Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9838)
+  * Fix download file wrong content-type (#9825) (#9835)
+  * Fix wrong identify poster on a migrated pull request when submit review (#9827) (#9831)
+  * Fix dump non-exist log directory (#9818) (#9820)
+  * Fix compare (#9808) (#9815)
+  * Fix missing msteam webhook on organization (#9781) (#9795)
+  * Fix add team on collaborator page when same name as organization (#9783)
+  * Fix cache problem on dashboard (#9358) (#9703)
+  * Send tag create and push webhook when release created on UI (#8671) (#9702)
+  * Branches not at ref commit ID should not be listed as Merged (#9614) (#9639)
+
+## [1.10.2](https://github.com/go-gitea/gitea/releases/tag/v1.10.2) - 2020-01-02
+
+* BUGFIXES
+  * Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
+  * Add ErrReactionAlreadyExist error (#9550) (#9564)
+  * Fix bug when migrate from API (#8631) (#9563)
+  * Use default avatar for ghost user (#9536) (#9537)
+  * Fix repository issues pagination bug when there are more than one label filter (#9512) (#9528)
+  * Fix deleted branch not removed when push the branch again (#9516) (#9524)
+  * Fix missing repository status when migrating repository via API (#9511)
+  * Trigger webhook when deleting a branch after merging a PR (#9510)
+  * Fix paging on /repos/{owner}/{repo}/git/trees/{sha} API endpoint (#9482)
+  * Fix NewCommitStatus (#9434) (#9435)
+  * Use OriginalURL instead of CloneAddr in migration logging (#9418) (#9420)
+  * Fix Slack webhook payload title generation to work with Mattermost (#9404)
+  * DefaultBranch needs to be prefixed by BranchPrefix (#9356) (#9359)
+  * Fix issue indexer not triggered when migrating a repository (#9333)
+  * Fix bug that release attachment files not deleted when deleting repository (#9322) (#9329)
+  * Fix migration releases (#9319) (#9326) (#9328)
+  * Fix File Edit: Author/Committer interchanged (#9297) (#9300)
+
+## [1.10.1](https://github.com/go-gitea/gitea/releases/tag/v1.10.1) - 2019-12-05
+
+* BUGFIXES
+  * Fix max length check and limit in multiple repo forms (#9148) (#9204)
+  * Properly fix displaying virtual session provider in admin panel (#9137) (#9203)
+  * Upgrade levelqueue to 0.1.0 (#9192) (#9199)
+  * Fix panic when diff (#9187) (#9193)
+  * Smtp logger configuration sendTos should be an array (#9154) (#9157)
+  * Always Show Password Field on Link Account Sign-in Page (#9150)
+  * Create PR on Current Repository by Default (#8670) (#9141)
+  * Fix race on indexer (#9136) (#9139)
+  * Fix reCAPTCHA URL (#9119)
+  * Hide migrated credentials (#9098)
+  * Update golang.org/x/crypto vendor to use acme v2 (#9056) (#9085)
+  * Fix password checks on admin create/edit user (#9076) (#9081)
+  * Fix add search as a reserved username (#9063) (#9065)
+  * Fix permission checks for close/reopen from commit (#8875) (#9033)
+  * Ensure Written is set in GZIP ProxyResponseWriter (#9018) (#9025)
+  * Fix broken link to branch from issue list (#9003) (#9021)
+  * Fix wrong system notice when repository is empty (#9020)
+  * Shadow password correctly for session config (#8984) (#9002)
+
+## [1.10.0](https://github.com/go-gitea/gitea/releases/tag/v1.10.0) - 2019-11-13
+
+* BREAKING
+  * Fix deadline on update issue or PR via API (#8698)
+  * Hide some user information via API if user doesn't have enough permission (#8655) (#8657)
+  * Remove legacy handling of drone token (#8191)
+  * Change repo search to use exact match for topic search. (#7941)
+  * Add pagination for admin api get orgs and fix only list public orgs bug (#7742)
+  * Implement the ability to change the ssh port to match what is in the gitea config (#7286)
+* SECURITY
+  * Fix issue with user.fullname (#8903)
+  * Ignore mentions for users with no access (#8395)
+  * Be more strict with git arguments (#7715)
+  * Extract the username and password from the mirror url (#7651)
+  * reserve .well-known username (#7637)
+* FEATURES
+  * Org/Members: display 2FA members states + optimize sql requests (#7621)
+  * SetDefaultBranch on pushing to empty repository (#7610)
+  * Adds side-by-side diff for images (#6784)
+  * API method to list all commits of a repository (#6408)
+  * Password Complexity Checks  (#6230)
+  * Add option to initialize repository with labels (#6061)
+  * Add additional password hash algorithms (#6023)
+* BUGFIXES
+  * Allow to merge if file path contains " or \ (#8629) (#8771)
+  * On windows set core.longpaths true (#8776) (#8786)
+  * Fix 500 when edit hook (#8782) (#8789)
+  * Fix Checkbox at RepoSettings Protected Branch (#8799) (#8801)
+  * Fix SSH2 conditional in key parsing code (#8806) (#8810)
+  * Fix commit expand button to not go to commit link (#8745) (#8825)
+  * Fix new user form for non-local users (#8826) (#8828)
+  * Fix to close opened io resources as soon as not needed (#8839) (#8846)
+  * Fix edit content button on migrated issue content (#8877) (#8884)
+  * Fix require external registration password (#8885) (#8890)
+  * Fix password complexity check on registration (#8887) (#8888)
+  * Update Github Migration Tests (#8896) (#8938) (#8945)
+  * Enable punctuations ending mentions (#8889) (#8894)
+  * Add Close() method to gogitRepository (#8901) (#8956)
+  * Hotfix for review actions and notifications (#8965)
+  * Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618)
+  * Fix milestone close timestamp (#8728) (#8730)
+  * Fix 500 when getting user as unauthenticated user (#8653) (#8663)
+  * Fix 'New Issue Missing Milestone Comment' (#8678) (#8681)
+  * Use AppSubUrl for more redirections (#8647) (#8651)
+  * Add SubURL to redirect path (#8632) (#8634)
+  * Fix template error on account page (#8562) (#8622)
+  * Allow externalID to be UUID (#8551) (#8624)
+  * Prevent removal of non-empty emoji panel following selection of duplicate (#8609) (#8623)
+  * Update heatmap fixtures to restore tests (#8615) (#8616)
+  * Ensure that diff stats can scroll independently of the diff (#8581) (#8621)
+  * Webhook: set Content-Type for application/x-www-form-urlencoded (#8600)
+  * Fix #8582 by handling empty repos (#8587) (#8594)
+  * Fix bug on pull requests when transfer head repository (#8564) (#8569)
+  * Add missed close in ServeBlobLFS (#8527) (#8542)
+  * Ensure that GitRepo is set on Empty repositories (#8539) (#8541)
+  * Fix migrate mirror 500 bug (#8526) (#8530)
+  * Fix password complexity regex for special characters (#8524)
+  * Prevent .code-view from overriding font on icon fonts (#8614) (#8627)
+  * Allow more than 255 characters for tokens in external_login_user table (#8554)
+  * Fix errors in create org UI regarding team access permission (#8506)
+  * Fix bug on FindExternalUsersByProvider (#8504)
+  * Create .ssh dir as necessary (#8486)
+  * IsBranchExist: return false if provided name is empty (#8485)
+  * Making openssh listen on SSH_LISTEN_PORT not SSH_PORT (#8477)
+  * Add check for empty set when dropping indexes during migration (#8471)
+  * LFS files are relative to LFS content path, ensure that when deleting they are made relative to this (#8455)
+  * Ensure Request Body Readers are closed in LFS server (#8454)
+  * Fix template bug on mirror repository setting page (#8438)
+  * Fix migration v96 to keep issue attachments (#8435)
+  * Update strk.kbt.io/projects/go/libravatar to latest (#8429)
+  * Singular form for files that has only one line (#8416)
+  * Check for either escaped or unescaped wiki filenames (#8408)
+  * Allow users with explicit read access to give approvals (#8382)
+  * Fix editor commit to new branch if PR disabled (#8375)
+  * readd .markdown class to all markup renderers (#8357)
+  * Upgrade xorm to v0.7.9 to fix some bugs (#8354)
+  * Fix column name ambiguity in GetUserIssueStats() (#8347)
+  * Change general form binding to gogs form (#8334)
+  * Fix pull request commit status in user dashboard list (#8321)
+  * Fix repo_admin_change_team_access always checked in org settings (#8319)
+  * Update to github.com/lafriks/xormstore@v1.3.0 (#8317)
+  * Show correct commit status in PR list (#8316)
+  * Bugfix for image compare and minor improvements to image compare (#8289)
+  * Update xorm (#8286)
+  * Fix API for edit and delete release attachment (#8285)
+  * Fix nil object access in some conditions when parsing cross references (#8281)
+  * Fix label count (#8267)
+  * Only show teams access for organization repositories on collaboration setting page (#8265)
+  * Test more reserved usernames (#8263)
+  * Rewrite reference processing code in preparation for opening/closing from comment references (#8261)
+  * Fix assets key on release webhook (#8253)
+  * Allow registration when button is hidden (#8237)
+  * Fix release API URL generation (#8234)
+  * Fix milestone num_issues (#8221)
+  * MS Teams webhook misses commit messages (#8209)
+  * Fix data race (#8204)
+  * Fix team user api (#8172)
+  * Fix pull merge 500 error caused by git-fetch breaking behaviors (#8161)
+  * Make show private icon when repo avatar set (#8144)
+  * Add reviewers as participants (#8121)
+  * Fix Go 1.13 private repository go get issue (#8112)
+  * feat: highlight issue references with : (#8101)
+  * Make AllowedUsers configurable in sshd_config (#8094)
+  * Strict name matching for Repository.GetTagID() (#8074)
+  * Avoid ambiguity of branch/directory names for the git-diff-tree command (#8066)
+  * Add change title notification for issues (#8061)
+  * [ssh] fix the config specification in the authorized_keys template (#8031)
+  * Fix reading git notes from nested trees (#8026)
+  * Fixes synchronize tags to releases for repository - makes sure we are only getting tag refs (#7990)
+  * Fix adding default Telegram webhook (#7972)
+  * Run CORS handler first for /api routes (#7967)
+  * Abort synchronization from LDAP source if there is some error. (#7960)
+  * Fix wrong sender when send slack webhook (#7918)
+  * Fix bug when migrating a private repository (#7917)
+  * Evaluate emojis in commit messages in list view (#7906)
+  * Fix upload file type check (#7890)
+  * lfs/lock: round locked_at timestamp to second (#7872)
+  * fix non existent milestone with 500 error instead of 404 (#7867)
+  * gpg/bugfix: Use .ExpiredUnix.IsZero to display green color of forever valid gpg key (#7846)
+  * Fix duplicate call of webhook (#7821)
+  * Enable switching to a different source branch when PR already exists (#7819)
+  * Convert files to utf-8 for indexing (#7814)
+  * Do not fetch all refs in pull-request compare (#7797)
+  * Fix multiple bugs with statuses endpoints at API (#7785)
+  * Restore functionality for early gits (#7775)
+  * Fix Slack webhook fork message (#7774)
+  * Rewrite existing repo units if setting is not included in api body (#7763)
+  * Fix rename failed when rewrite public keys (#7761)
+  * Fix approvals counting (#7757)
+  * Add migration step to remove old repo_indexer_status orphaned records (#7746)
+  * Fix repo_index_status lingering when deleting a repository (#7734)
+  * Remove camel case tokenization from repo indexer (#7733)
+  * Fix milestone completness calculation when migrating (#7725)
+  * Regression: Include "executable" files in the index, as they are not necessarily … (#7718)
+  * Fixes indexed repos keeping outdated indexes when files grow too large (#7712)
+  * Skip non-regular files (e.g. submodules) on repo indexing (#7711)
+  * Fix dropTableColumns sqlite implementation (#7710)
+  * Update gopkg.in/src-d/go-git.v4 to v4.13.1 (#7705)
+  * improve branches list performance and fix protected branch icon when no-login (#7695)
+  * Correct wrong datetime format for git (#7689)
+  * Move add to hook queue for created repo to outside xorm session. (#7675)
+  * sugestion to use range .Branches (#7674)
+  * Fix bug on migrating milestone from github (#7665)
+  * hide delete/restore button on archived repos (#7658)
+  * css: use flex to fix floating paginate (#7656)
+  * Fix syntax highlight initialization (#7617)
+  * Fix panic on push at - Merging pull request causes 500 error (#7615)
+  * Make PKCS8, PEM and SSH2 keys work (#7600)
+  * Fix mistake in arc-green.less split-diff css code. (#7587)
+  * Handle ErrUserProhibitLogin in http git (#7586)
+  * Fix bug create/edit wiki pages when code master branch protected (#7580)
+  * Fixes Malformed URLs in API git/commits response (#7565)
+  * Fix file header overflow in file and blame views (#7562)
+  * Improve SSH key parser to handle newlines in keys (#7522)
+  * Fix empty commits now showing in repo overview (#7521)
+  * Fix repository's pull request count error (#7518)
+  * Fix markdown invoke sequence (#7513)
+  * Remove duplicated webhook trigger (#7511)
+  * Update User.NumRepos atomically in createRepository (#7493)
+  * Fix settings page of repo you aren't admin print error - Settings pages giving UnitType error message (#7482)
+  * Fix redirection after file edit - Handles all redirects for Web UI File CRUD (#7478)
+  * cmd/serv: actually exit after fatal errors (#7458)
+  * Fix an issue with some pages throwing 'not defined' js exceptions (#7450)
+  * fix Dropzone.js integration (#7445)
+  * Fix regex for issues in commit messages (#7444)
+  * Diff: Fix indentation on unhighlighted code (#7435)
+  * Only show "New Pull Request" button if repo allows pulls (#7426)
+  * Upgrade macaron/captcha to fix random error problem (#7407)
+  * create class for inline positioned lists (#7393)
+  * Fetch refs for successful testing for tag (#7388)
+  * add missing template variable on organisation settings (#7385)
+  * fix post parameter - on issue list - unset assignee (#7380)
+  * fix/define autochecked checkboxes on issue list in firefox (#7320)
+  * only return head: null if source branch was deleted (#6705)
+* ENHANCEMENTS
+  * Add nofollow to sign in links (#8509)
+  * vendor: update mvdan.cc/xurls/v2 to v2.1.0 (#8495)
+  * Update milestone issues numbers when save milestone and other code improvements (#8411)
+  * Add extra user information when migrating release (#8331)
+  * Require overall success if no context is given for status check (#8318)
+  * Transaction-aware retry create issue to cope with duplicate keys (#8307)
+  * Change link on issue milestone (#8246)
+  * Alwaywas return local url for users avatar (#8245)
+  * Move some milestone functions to a standalone package (#8213)
+  * Move create issue comment to comments package (#8212)
+  * Disable max height property of comment textarea (#8203)
+  * Add 'Mentioning you' group to /issues page (#8201)
+  * oauth2 with remote Gitea (#8149)
+  * Reference issues from pull requests and other issues (#8137)
+  * Fix webhooks to use proxy from environment (#8116)
+  * Add merged commit id on pull view when it's merged (#8062)
+  * Add teams to repo on collaboration page. (#8045)
+  * Update swagger to 0.20.1  (#8010)
+  * Make link last commit massages in repository home page and commit tables (#8006)
+  * Add API endpoint for accessing repo topics (#7963)
+  * Include description in repository search (#7942)
+  * Use gitea forked macaron (#7933)
+  * Fix pull creation with empty changes (#7920)
+  * Allow token as authorization for accessing attachments (#7909)
+  * Retry create issue to cope with duplicate keys (#7898)
+  * Move git diff codes from models to services/gitdiff (#7889)
+  * migrate gplus to google oauth2 provider (#7885)
+  * Remove unique filter from repo indexer analyzer. (#7878)
+  * Detect delimiter in CSV rendering (#7869)
+  * Import topics during migration (#7851)
+  * Move CreateReview to modules/pull (#7841)
+  * vendor: update pdf.js to v2.1.266 (#7834)
+  * Support SSH_LISTEN_PORT env var in docker app.ini template (#7829)
+  * Add Ability for User to Customize Email Notification Frequency (#7813)
+  * Move database settings from models to setting (#7806)
+  * Display ui time with customize time location (#7792)
+  * Implement webhook branch filter (#7791)
+  * Restrict repository indexing by glob match (#7767)
+  * Api: advanced settings for repository (external wiki, issue tracker etc.) (#7756)
+  * Update migrated repositories' issues/comments/prs poster id if user has a github external user saved (#7751)
+  * deps: Upgrade gopkg.in/editorconfig/editorconfig-core-go.v1 (#7749)
+  * Apply emoji on commit graph page (#7743)
+  * Add a lot of extension to language mappings for syntax highlights (#7741)
+  * Add SQL execution on log and indexes on table repository and comment (#7740)
+  * Set DB connection error level to error (#7724)
+  * Check commit message hashes before making links (#7713)
+  * remove unnecessary fmt on generate bindata (#7706)
+  * Fix specific highlighting (CMakeLists.txt ...) (#7686)
+  * Add file status on API (#7671)
+  * Add support for DEFAULT_ORG_MEMBER_VISIBLE (#7669)
+  * Provide links in commit summaries in commits table/view list (#7659)
+  * Change length of some repository's columns (#7652)
+  * Move commit repo action from models to repofiles package (#7645)
+  * fix wrong email when use gitea as OAuth2 provider (#7640)
+  * [Branch View] add download button (#7604)
+  * Update to xorm@v0.7.4 (#7596)
+  * use 403 instead of 401 for ErrUserProhibitLogin (#7591)
+  * Removed unnecessary conversions (#7557)
+  * Un-lambda base.FileSize (#7556)
+  * Added missing error checks in tests (#7554)
+  * Move create release from models to a standalone package (#7539)
+  * Make default branch name link to default branch (#7519)
+  * Added total count of contributions to heatmap (#7517)
+  * Move mirror to a standalone package from models (#7486)
+  * Move models.PushUpdate to repofiles.PushUpdate (#7485)
+  * Include thread related headers in issue/coment mail (#7484)
+  * Refuse merge until all required status checks success (#7481)
+  * convert all js var to let/const (#7464)
+  * Only create branches for opened pull requestes when migrating from github (#7463)
+  * jQuery 3 (#7425)
+  * Add notification placeholder (#7409)
+  * Search Commits via Commit Hash (#7400)
+  * Move status table to cron package (#7370)
+  * wiki - page revisions list  (#7369)
+  * Display original author and URL information when showing migrated issues/comments (#7352)
+  * Refactor filetype is not allowed errors (#7309)
+  * switch to use gliderlabs/ssh for builtin server (#7250)
+  * Remove setting dependency on modules/session (#7237)
+  * Move all mail related codes from models to services/mailer (#7200)
+  * Support git.PATH entry in app.ini (#6772)
+  * Support setting cookie domain (#6288)
+  * Move migrating repository from frontend to backend (#6200)
+  * Delete releases attachments if release is deleted (#6068)
+* TRANSLATION
+  * Latvian translation for home page (#8468)
+  * Add home template italian translation (#8352)
+  * fix misprint (#7452)
+* BUILD
+  * use go 1.13 (#8088)
+* MISC
+  * add file line count info on UI (#8396)
+  * Make issues page left menu 100% width and add reponame as title attribute (#8359)
+  * [arc-green] white on hover for active menu items (#8344)
+  * Move ref (branch or tag) location on issue list page (#8157)
+  * apply emoji on dashboard issue list labels (#8156)
+  * 1148: Take up the full width when viewing the diff in split view. (#8114)
+  * Display description of 'make this repo private' as help text, not as tooltip (#8097)
+  * Fixes deformed emoji in pull request reviews (#8047)
+  * Add strike to old header on comment (#8046)
+  * Add tooltip for the visibility checkbox in /repo/create (#8025)
+  * Update github.com/lafriks/xormstore and tidy up mod.go (#8020)
+  * keep blame view buttons sequence consistent with normal view when view a file (#8007)
+  * Use "Pull Request" instead of "Merge Request" (#8003)
+  * Move line number to :before attr to hide from search on browser (#8002)
+  * Changed black color to white for (read) number label on issue list page (#8000)
+  * [Branch View] show "New Pull Request" Button only if posible (#7977)
+  * Fix hook problem by only setting the git environment variables if we are passed them (#7854)
+  * Prevent Commit Status and Message From Overflowing On Branch Page (#7800)
+  * Fix global search result CSS, misc CSS tweaks (#7789)
+  * Tweak label border CSS (#7739)
+  * Fix create menu item widths (#7708)
+  * [Branch View] Delete duplicate protection symbol (#7624)
+  * [Branch View] Delete Table Header (#7622)
+  * [Branch View] icons to buttons (#7602)
+  * update js dependencies (#7462)
+  * Add Extra Info to Branches Page (#7461)
+  * Bump lodash from 4.17.11 to 4.17.14 (#7459)
+  * wiki history improvements (#7391)
+  * ui fixes - compare view and archieved repo issues (#7345)
+  * dark theme scrollbars (#7269)
+  * wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243)
+  * Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141)
+
+## [1.9.6](https://github.com/go-gitea/gitea/releases/tag/v1.9.6) - 2019-11-13
+
+* BUGFIXES
+  * Allow to merge if file path contains " or \ (#8629) (#8772)
+  * Fix 500 when edit hook (#8782) (#8790)
+  * Fix issue with user.fullname (#8904)
+  * Update Github Migration Test (#8897) (#8946)
+  * Add Close() method to gogitRepository (#8901) (#8958)
+
+## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
+
+* BREAKING
+  * Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
+* BUGFIXES
+  * Fix milestone close timestamp (#8728) (#8731)
+  * Fix deadline on update issue or PR via API (#8699)
+  * Fix 'New Issue Missing Milestone Comment' (#8678) (#8682)
+  * Fix 500 when getting user as unauthenticated user (#8653) (#8662)
+  * Use AppSubUrl for more redirections (#8647) (#8652)
+  * Add SubURL to redirect path (#8632) (#8634) (#8640)
+  * Fix #8582 by handling empty repos (#8587) (#8593)
+  * Fix bug on pull requests when transfer head repository (#8571)
+  * Add missed close in ServeBlobLFS (#8527) (#8543)
+  * Return false if provided branch name is empty for IsBranchExist (#8485) (#8492)
+  * Create .ssh dir as necessary (#8369) (#8486) (#8489)
+  * Restore functionality for early gits (#7775) (#8476)
+  * Add check for empty set when dropping indexes during migration (#8475)
+  * Ensure Request Body Readers are closed in LFS server (#8454) (#8459)
+  * Ensure that LFS files are relative to the LFS content path (#8455) (#8458)
+* SECURITY
+  * Ignore mentions for users with no access (#8395) (#8484)
+* TESTING
+  * Update heatmap fixtures to restore tests (#8615) (#8617)
+
+## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
+
+* BUGFIXES
+  * Highlight issue references (#8101) (#8404)
+  * Fix bug when migrating a private repository #7917 (#8403)
+  * Change general form binding to gogs form (#8334) (#8402)
+  * Fix editor commit to new branch if PR disabled (#8375) (#8401)
+  * Fix milestone num_issues (#8221) (#8400)
+  * Allow users with explicit read access to give approvals (#8398)
+  * Fix commit status in PR #8316 and PR #8321 (#8339)
+  * Fix API for edit and delete release attachment (#8290)
+  * Fix assets on release webhook (#8283)
+  * Fix release API URL generation (#8239)
+  * Allow registration when button is hidden (#8238)
+  * MS Teams webhook misses commit messages (backport v1.9) (#8225)
+  * Fix data race (#8206)
+  * Fix pull merge 500 error caused by git-fetch breaking behaviors (#8194)
+  * Fix the SSH config specification in the authorized_keys template (#8193)
+  * Fix reading git notes from nested trees (#8189)
+  * Fix team user api (#8172) (#8188)
+  * Add reviewers as participants (#8124)
+* BUILD
+  * Use vendored go-swagger (#8087) (#8165)
+  * Fix version-validation for GO 1.13 (go-macaron/cors) (#8389)
+* MISC
+  * Make show private icon when repo avatar set (#8144) (#8175)
+
+## [1.9.3](https://github.com/go-gitea/gitea/releases/tag/v1.9.3) - 2019-09-06
+
+* BUGFIXES
+  * Fix go get from a private repository with Go 1.13 (#8100)
+  * Strict name matching for Repository.GetTagID() (#8082)
+  * Avoid ambiguity of branch/directory names for the git-diff-tree command (#8070)
+  * Add change title notification for issues (#8064)
+  * Run CORS handler first for /api routes (#7967) (#8053)
+  * Evaluate emojis in commit messages in list view (#8044)
+  * Fix failed to synchronize tags to releases for repository (#7990) (#7994)
+  * Fix adding default Telegram webhook (#7972) (#7992)
+  * Abort synchronization from LDAP source if there is some error (#7965)
+  * Fix deformed emoji in commit message (#8071)
+* ENHANCEMENTS
+  * Keep blame view buttons sequence consistent with normal view when viewing a file (#8007) (#8009)
+
+## [1.9.2](https://github.com/go-gitea/gitea/releases/tag/v1.9.2) - 2019-08-22
+
+* BUGFIXES
+  * Fix wrong sender when send slack webhook (#7918) (#7924)
+  * Upload support text/plain; charset=utf8 (#7899)
+  * Lfs/lock: round locked_at timestamp to second (#7872) (#7875)
+  * Fix non existent milestone with 500 error (#7867) (#7873)
+* SECURITY
+  * Fix No PGP signature on 1.9.1 tag (#7874)
+  * Release built with go 1.12.9 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!msg/golang-announce/oeMaeUnkvVE/a49yvTLqAAAJ
+* ENHANCEMENTS
+  * Fix pull creation with empty changes (#7920) (#7926)
+* BUILD
+  * Drone/docker: prepare multi-arch release + provide arm64 image (#7571) (#7884)
+
+## [1.9.1](https://github.com/go-gitea/gitea/releases/tag/v1.9.1) - 2019-08-14
+
+* BREAKING
+  * Add pagination for admin api get orgs and fix only list public orgs bug (#7742) (#7752)
+* SECURITY
+  * Be more strict with git arguments (#7715) (#7762)
+  * Release built with go 1.12.8 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!topic/golang-nuts/fCQWxqxP8aA
+* BUGFIXES
+  * Fix local runs of ssh-requiring integration tests (#7855) (#7857)
+  * Fix hook problem (#7856) (#7754)
+  * Use .ExpiredUnix.IsZero to display green color of forever valid gpg key (#7850) (#7846)
+  * Do not fetch all refs (#7797) (#7837)
+  * Fix duplicate call of webhook (#7824) (#7821)
+  * Enable switching to a different source branch when PR already exists (#7823)
+  * Rewrite existing repo units if setting is not included in api body (#7811)
+  * Prevent Commit Status and Message From Overflowing On Branch Page (#7800) (#7808)
+  * API: fix multiple bugs with statuses endpoints (Backport #7785) (#7807)
+  * Fix Slack webhook fork message (1.9 release backport) (#7783)
+  * Fix approvals counting (#7757) (#7777)
+  * Fix rename failed when rewrite public keys (#7761) (#7769)
+  * Fix dropTableColumns sqlite implementation (#7710) (#7765)
+  * Fix repo_index_status lingering when deleting a repository (#7738)
+  * Fix milestone completness calculation when migrating (#7725) (#7732)
+  * Fixes indexed repos keeping outdated indexes when files grow too large (#7731)
+  * Skip non-regular files (e.g. submodules) on repo indexing (#7717)
+  * Improve branches list performance and fix protected branch icon when no-login (#7695) (#7704)
+  * Correct wrong datetime format for git (#7689) (#7690)
+
+## [1.9.0](https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - 2019-07-30
+
+* BREAKING
+  * Better logging (#6038) (#6095)
+* SECURITY
+  * Shadow the password on cache and session config on admin panel (#7300)
+  * Fix markdown invoke sequence (#7513) (#7560)
+  * Reserve .well-known username (#7638)
+  * Do not leak secrets via timing side channel (#7364)
+  * Ensure that decryption of cookie actually succeeds (#7363)
+* FEATURES
+  * Content API for Creating, Updating, Deleting Files (#6314)
+  * Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
+  * Add command to convert mysql database from utf8 to utf8mb4 (#7144)
+  * Fixes #2738 - Adds the /git/tags API endpoint (#7138)
+  * Compare branches, commits and tags with each other (#6991)
+  * Show Pull Request button or status of latest PR in branch list (#6990)
+  * Repository avatars (#6986)
+  * Show git-notes (#6984)
+  * Add commit statuses reports on pull request view (#6845)
+  * Number of commits ahead/behind in branch overview (#6695)
+  * Add CLI commands to manage LDAP authentication source (#6681)
+  * Add support for MS Teams webhooks (#6632)
+  * OAuth2 Grant UI (#6625)
+  * Add SUBJECT_PREFIX mailer config option (#6605)
+  * Include custom configuration file in dump (#6516)
+  * Add API for manipulating Git hooks (#6436)
+  * Improve migrations to support migrating milestones/labels/issues/comments/pullrequests (#6290)
+  * Add option to blame files (#5721)
+  * Implement Default Webhooks (#4299)
+  * Telegram webhook (#4227)
+* BUGFIXES
+  * Send webhook after commit when creating issue with assignees (#7681) (#7684)
+  * Upgrade macaron/captcha to fix random error problem (#7407) (#7683)
+  * Move add to hook queue for created repo to outside xorm session. (#7682) (#7675)
+  * Show protection symbol if needed on default branch (#7660) (#7668)
+  * Hide delete/restore button on archived repos (#7660)
+  * Fix bug on migrating milestone from github (#7665) (#7666)
+  * Use flex to fix floating paginate (#7656) (#7662)
+  * Change length of some repository's columns (#7652) (#7655)
+  * Fix wrong email when use gitea as OAuth2 provider (#7640) (#7647)
+  * Fix syntax highlight initialization (#7617) (#7626)
+  * Fix bug create/edit wiki pages when code master branch protected (#7580) (#7623)
+  * Fix panic on push at #7611 (#7615) (#7618)
+  * Handle ErrUserProhibitLogin in http git (#7586, #7591) (#7590)
+  * Fix color of split-diff view in dark theme (#7587) (#7589)
+  * Fix file header overflow in file and blame views (#7562) (#7579)
+  * Malformed URLs in API git/commits response (#7565) (#7567)
+  * Fix empty commits now showing in repo overview (#7521) (#7563)
+  * Fix repository's pull request count error (#7518) (#7524)
+  * Remove duplicated webhook trigger (#7511) (#7516)
+  * Handles all redirects for Web UI File CRUD (#7478) (#7507)
+  * Fix regex for issues in commit messages (#7444) (#7466)
+  * cmd/serv: actually exit after fatal errors (#7458) (#7460)
+  * Fix an issue with some pages throwing 'not defined' js exceptions #7450 (#7453)
+  * Fix Dropzone.js integration (#7445) (#7448)
+  * Create class for inline positioned lists (#7439) (#7393)
+  * Diff: Fix indentation on unhighlighted code (#7435) (#7443)
+  * jQuery 3 (#7442) (#7425)
+  * Only show "New Pull Request" button if repo allows pulls (#7426) (#7432)
+  * Fix vendor references (#7394) (#7396)
+  * Only return head: null if source branch was deleted (#6705) (#7376)
+  * Add missing template variable on organisation settings (#7386) (#7385)
+  * Fix post parameter on issue list which had unset assignee (#7380) (#7383)
+  * Fix migration tests due to issue 7 being resolved (#7375) (#7381)
+  * Correctly adjust mirror url (#6593)
+  * Handle early git version's lack of get-url (#7065)
+  * Fix icon position in issue view (#7354)
+  * Cut timeline length with last element on issue view (#7355)
+  * Fix mirror repository webhooks (#7366)
+  * Fix api route for hooks (#7346)
+  * Fix bug conflict between SyncReleasesWithTags and InsertReleases (#7337)
+  * Fix pull view ui merge section (#7335)
+  * Fix 7303 - remove unnessesary buttons on archived repos (#7326)
+  * Fix topic bar to allow prefixes (#7325)
+  * Fixes #7152 - Allow create/update/delete message to be empty, use default message (#7324)
+  * Fixes #7238 - Annotated tag commit ID incorrect (#7321)
+  * Dark theme fixes (#7319)
+  * Gitea own dark codemirror theme (#7317)
+  * Fixes #7292 - API File Contents bug (#7301)
+  * Fix API link header (#7298)
+  * Fix extra newlines when copying from diff in Firefox (#7288)
+  * Make diff line-marker non-selectable (#7279)
+  * Fix Submodule dection in subdir (#7275)
+  * Fix error log when loading issues caused by a xorm bug (#7271)
+  * Add .fa icon margin like .octicon (#7258)
+  * Fix hljs unintenionally highlighting commit links (#7244)
+  * Only check and config git on web subcommand but not others (#7236)
+  * Fix migration panic when Head.User is not exist (#7226)
+  * Only warn on errors in deleting LFS orphaned files during repo deletion (#7213)
+  * Fix duplicated file on pull request conflicted files (#7211)
+  * Allow colon between fixing word and issue (#7207)
+  * Fix overflow issues in repo (#7190)
+  * API error cleanup (#7186)
+  * Add error for fork already existing (#7185)
+  * Fixes diff on merged pull requests (#7171)
+  * If milestone id is zero don't get it from database (#7169)
+  * Fix pusher name via ssh push (#7167)
+  * Fix database lock when use random repository fallback image (#7166)
+  * Various fixes for issue mail notifications (#7165)
+  * Allow archived repos to be (un)starred and (un)watched (#7163)
+  * Fix GCArgs load from ini (#7156)
+  * Detect noreply email address as user (#7133)
+  * Avoid arbitrary format strings upon calling fail() function (#7112)
+  * Validate External Tracker URL Format (#7089)
+  * Repository avatar fallback configuration (#7087)
+  * Fix #732: Add LFS objects to base repository on merging  (#7082)
+  * Install page - Handle invalid administrator username better (#7060)
+  * Workaround for posting single comments in split diff view (#7052)
+  * Fix possbile mysql invalid connnection error (#7051)
+  * Fix charset was not saved after installation finished (#7048)
+  * Handle insecure and ports in go get (#7041)
+  * Avoid bad database state after failed migration (#7040)
+  * Fix wrong init dependency on markup extensions (#7038)
+  * Fix default for allowing new organization creation for new users (#7017)
+  * Fix content download and /verify LFS handler expecting wrong content-type (#7015)
+  * Fix missing repo description when migrating (#7000)
+  * Fix LFS Locks over SSH (#6999)
+  * Do not attempt to return blob on submodule (#6996)
+  * Fix U2F for Chrome >= 74 (#6980)
+  * Fix index produces problem when issues/pulls deleted (#6973)
+  * Allow collaborators to view repo owned by private org (#6965)
+  * Stop running hooks on pr merge (#6963)
+  * Run hooks on merge/edit and cope with protected branches (#6961)
+  * Webhook Logs show proper HTTP Method, and allow change HTTP method in form (#6953)
+  * Stop colorizing log files by default (#6949)
+  * Rotate serv.log, http.log and hook logs and stop stacktracing in these (#6935)
+  * Fix plain text overflow line wrap (#6915)
+  * Fix input size for dependency select (#6913)
+  * Change drone token name to let users know to use oauth2 (#6912)
+  * Fix syntax highlight in blame view #6895 (#6909)
+  * Use AppURL for Oauth user link (#6894)
+  * Fixes #6881 - API users search fix (#6882)
+  * Fix 404 when send pull request some situation  (#6871)
+  * Enforce osusergo build tag for releases (#6862)
+  * Fix 500 when reviewer is deleted with integration tests (#6856)
+  * Fix v85.go (#6851)
+  * Make dropTableColumns drop columns on sqlite and constraints on all (#6849)
+  * Fix double-generation of scratch token (#6832) (#6833)
+  * When mirroring we should set the remote to mirror (#6824)
+  * Fix the v78 migration "Drop is_bare" on MSSQL #6707 (#6823)
+  * Change verbose flag in dump command to avoid colliding with global version flag (#6822)
+  * Fix #6813: Allow git.GetTree to take both commit and tree names (#6816)
+  * Remove `seen` map from `getLastCommitForPaths` (#6807)
+  * Show scrollbar only when needed (#6802)
+  * Restore IsWindows variable assignment (#6722) (#6790)
+  * Service worker js is a missing comma (#6788)
+  * Fix team edit API panic (#6780)
+  * Set user search base field optional in LDAP (simple auth) edit page (#6779)
+  * Ignore already existing public keys after ldap sync (#6766)
+  * Fix pulls broken when fork repository deleted (#6754)
+  * Fix missing return (#6751)
+  * Fix new team 500 (#6749)
+  * OAuth2 token can be used in basic auth (#6747)
+  * Fix org visibility bug when git cloning (#6743)
+  * Fix bug when sort repos on org home page login with non-admin (#6741)
+  * Stricter domain name pattern in email regex (#6739)
+  * Fix admin template error (#6737)
+  * Drop is_bare IDX only when it exists for MySQL and MariaDB (#6736)
+  * UI: Detect and restore encoding and BOM in content  (#6727)
+  * Load issue attributes when editing an issue with API (#6723)
+  * Fix team members API (#6714)
+  * Unfortunately MemProvider Init does not actually Init properly (#6692)
+  * Fix partial reversion of #6657 caused by #6314 (#6685)
+  * Prevent creating empty sessions (#6677)
+  * Fixes #6659 - Swagger schemes selection default to page's protocol (#6660)
+  * Update highlight.js to 9.15.6 (#6658)
+  * Properly escape on the redirect from the web editor (#6657)
+  * Fix #6655 - Don't EscapePound .Link as it is already escaped (#6656)
+  * Use ctx.metas for SHA hash links (#6645)
+  * Fix wrong GPG expire date (#6643)
+  * upgrade version of lib/pq to v1.1.0 (#6640)
+  * Fix forking an empty repository (#6637)
+  * Fix issuer of OTP URI should be URI-encoded. (#6634)
+  * Return a UserList from /api/v1/admin/users (#6629)
+  * Add json tags for oauth2 form (#6627)
+  * Remove extra slash from twitter card (#6619)
+  * remove bash requirement in makefile (#6617)
+  * Fix Open Graph og:image link (#6612)
+  * Fix cross-compile builds (#6609)
+  * Change commit summary to full message in API (#6591)
+  * Fix bug user search API pagesize didn't obey ExplorePagingNum (#6579)
+  * Prevent server 500 on compare branches with no common history (#6555)
+  * Properly escape release attachment URL (#6512)
+  * Delete local branch when repo branch is deleted (#6497)
+  * Fix bug when user login and want to resend register confirmation email (#6482)
+  * Fix upload attachments (#6481)
+  * Avoid multi-clicks in oauth2 login (#6467)
+  * Hacky fix for alignment of the create-organization dialog (#6455)
+  * Change order that PostProcess Processors are run (#6445)
+  * Clean up ref name rules (#6437)
+  * Fix Hook & HookList in Swagger (#6432)
+  * Fixed unitTypeCode not being used in accessLevelUnit (#6419)
+  * Display correct error for invalid mirror interval (#6414)
+  * Don't Unescape redirect_to cookie value (#6399)
+  * Fix dump table name error and add some test for dump database (#6394)
+  * Fix migrations 82 to ignore unsynced tags between database and git data and missing is_archived on repository table (#6387)
+  * Make sure units of a team are returned (#6379)
+  * Fix bug manifest.json will not request with cookie so that session will created every request (#6372)
+  * Disable benchmarking during tag events on DroneIO (#6365)
+  * Comments list performance optimization (#5305)
+* ENHANCEMENTS
+  * Update Drone docker generation to standard format (#7480) (#7496) (#7504)
+  * Add API Endpoint for Repo Edit (#7006)
+  * Add state param to milestone listing API (#7131)
+  * Make captcha and password optional for external accounts (#6606)
+  * Detect migrating batch size (#7353)
+  * Fix 7255 - wrap long texts on user profile info (#7333)
+  * Use commit graph files for listing pages (#7314)
+  * Add git command line commitgraph support global default true when git version >= 2.18 (#7313)
+  * Add LFS_START_SERVER option to control git-lfs support (#7281)
+  * Dark theme markdown fixes (#7260)
+  * Update go-git to v4.12.0 (#7249)
+  * Show lfs config on admin panel (#7220)
+  * Disable same user check for internal SSH (#7215)
+  * Add LastLogin to the User API (#7196)
+  * Add missing description of label on API (#7159)
+  * Use go method to calculate ssh key fingerprint (#7128)
+  * Enable Rust highlighting (#7125)
+  * Refactor submodule URL parsing (#7100)
+  * Change issue mail title. (#7064)
+  * Use batch insert on migrating repository to make the process faster (#7050)
+  * Improve github downloader on migrations (#7049)
+  * When git version >= 2.18, git command could run with git wire protocol version 2 param if enabled (#7047)
+  * Fix Erlang and Elixir highlight mappings (#7044)
+  * API Org Visibility (#7028)
+  * Improve handling of non-square avatars (#7025)
+  * Bugfix: Align comment label and actions to the right (#7024)
+  * Change UpdateRepoIndex api to include watchers (#7012)
+  * Move serv hook functionality & drop GitLogger (#6993)
+  * Add support of utf8mb4 for mysql (#6992)
+  * Make webhook http connections reusable (#6976)
+  * Move xorm logger bridge from log to models so that log module could be a standalone package (#6944)
+  * Refactor models.NewRepoContext to extract git related codes to modules/git (#6941)
+  * Remove macaron dependent on models (#6940)
+  * Add less linter via npx (#6936)
+  * Remove macaron dependent on modules/log (#6933)
+  * Remove macaron dependent on models/mail.go (#6931)
+  * Clean less files (#6921)
+  * Fix code overflow (#6914)
+  * Style orgs list in user profile (#6911)
+  * Improve description of branch protection (fix #6886) (#6906)
+  * Move sdk structs to modules/structs (#6905)
+  * update sdk to latest (#6903)
+  * Escape the commit message on issues update and title in telegram hook (#6901)
+  * SearchRepositoryByName improvements and unification (#6897)
+  * Change the color of issues/pulls list, merged is purple and closed is red (#6874)
+  * Refactor table width to have more info shown in file list (#6867)
+  * Monitor all git commands; move blame to git package and replace git as a variable (#6864)
+  * Fix config ui error about cache ttl (#6861)
+  * Improve localization of git activity stats (#6848)
+  * Generate access token in admin cli (#6847)
+  * Update github.com/urfave/cli to version 1.2.0 (#6838)
+  * Rename LFS_JWT_SECRET cli option to include OAUTH2 as well (#6826)
+  * internal/ssh: ignore env command totally (#6825)
+  * Allow Recaptcha service url to be configured (#6820)
+  * update github.com/mcuadros/go-version to v0.0.0-20190308113854-92cdf37c5b75 (#6815)
+  * Use modules/git for git commands (#6775)
+  * Add GET requests to webhook (#6771)
+  * Move PushUpdate dependency from models to repofiles (#6763)
+  * Tweak tab text and icon colors (#6760)
+  * Ignore non-standard refs in git push (#6758)
+  * Disable web preview for telegram webhook (#6719)
+  * Show full name if DEFAULT_SHOW_FULL_NAME setting enabled (#6710)
+  * Reorder file actions (#6706)
+  * README WordPress the code is overflowing #6679 (#6696)
+  * Improve issue reference on commit (#6694)
+  * Handle redirects for git clone commands (#6688)
+  * Fix one performance/correctness regression in #6478 found on Rails repository. (#6686)
+  * API OTP Context (#6674)
+  * Remove local clones & make hooks run on merge/edit/upload (#6672)
+  * Bump github.com/stretchr/testify from 1.2.2 to 1.3.0 (#6663)
+  * Bump gopkg.in/src-d/go-git.v4 from 4.8.0 to 4.10.0 (#6662)
+  * Fix dropdown icon padding (#6651)
+  * Add more title attributes on shortened names (#6647)
+  * Update UI for topics labels on projects (#6639)
+  * Trace Logging on Permission Denied & ColorFormat (#6618)
+  * Add .gpg url (match github behaviour) (#6610)
+  * Support for custom GITEA_CUSTOM env var in docker(#6608)
+  * Show "delete branch" button on closed pull requests (#6570) (#6601)
+  * Add option to disable refresh token invalidation (#6584)
+  * Fix new repo dropdown alignment (#6583)
+  * Fix mail notification when close/reopen issue (#6581)
+  * Pre-calculate the absolute path of git (#6575)
+  * Minor CSS cleanup for the navbar (#6553)
+  * Render SHA1 links as code blocks (#6546)
+  * Add username flag in create-user command (#6534)
+  * Unifies pagination template usage (#6531) (#6533)
+  * Fixes pagination width on mobile view (#5711) (#6532)
+  * Improve SHA1 link detection (#6526)
+  * Fixes #6446 - Sort team members and team's repositories (#6525)
+  * Use stricter boundaries for auto-link detection (#6522)
+  * Use regular line-height on frontpage entries (#6518)
+  * Fixes #6514 - New Pull Request on files and pulls pages the same (#6515)
+  * Make distinction between DisplayName and Username in email templates (#6495)
+  * Add X-Auto-Response-Suppress header to outgoing messages (#6492)
+  * Cleaned permission checks for API -> site admin can now do anything (#6483)
+  * Support search operators for commits search (#6479)
+  * Improve listing performance by using go-git (#6478)
+  * Fix repo sub_menu font color in arc-green (#6477)
+  * Show last commit status in pull request lists (#6465)
+  * Add signatures to webhooks (#6428)
+  * Optimize all images in public/img (#6427)
+  * Add golangci (#6418)
+  * Make "Ghost" not link to 404 page (#6410)
+  * Include more variables on admin/config page (#6378)
+  * Markdown: enable some more extensions (#6362)
+  * Include repo name in page title tag (#6343)
+  * Show locale string on timestamp (#6324)
+  * Handle CORS requests (#6289)
+  * Improve issue autolinks (#6273)
+  * Migration Tweaks (#6260)
+  * Add title attributes to all items in the repo list viewer (#6258)
+  * Issue indexer queue redis support (#6218)
+  * Add bio field for user (#6113)
+  * Make the version within makefile overwriteable (#6080)
+  * Updates to API 404 responses (#6077)
+  * Use Go1.11 module (#5743)
+  * UX + Security current user password reset (#5042)
+  * Refactor: append, build variable and type switch (#4940)
+  * Git statistics in Activity tab (#4724)
+  * Drop the bits argument when generating an ed25519 key (#6504)
+* TESTING
+  * Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
+  * Refactor and improve git test (#7086)
+  * Fix TestSearchRepo by waiting till indexing is done (#7004)
+  * Add mssql migration tests (needs #6823) (#6852)
+  * Add tests for Org API (#6731)
+  * Context.ServerError and NotFound should log from their caller (#6550)
+* TRANSLATION
+  * Add french specific rule for translating plural texts (#6846)
+* BUILD
+  * Update mssql driver to last working version 20180314172330-6a30f4e59a44 (#7306)
+  * Alpine 3.10 (#7256)
+  * Use vfsgen instead of go-bindata (#7080)
+  * remove and disable package-lock (#6969)
+  * add make targets for js and css, add js linter (#6952)
+  * Added tags pull step to drone config to show correct version hashes i… (#6836)
+  * Make CustomPath, CustomConf and AppWorkPath configurable at build (#6631)
+  * chore: update drone format to 1.0 (#6602)
+  * Fix race in integration testlogger (#6556)
+  * Quieter Integration Tests (#6513)
+  * Drop the docker Makefile from the image (#6507)
+  * Add make version on gitea version (#6485)
+  * Fix #6468 - Uses space match and adds newline for all sed flavors (#6473)
+  * Move code.gitea.io/git to code.gitea.io/gitea/modules/git (#6364)
+  * Update npm dependencies and various tweaks (#7344)
+  * Fix updated drone file (#7336)
+  * Add 'npm' and 'npm-update' make targets and lockfile (#7246)
+* DOCS
+  * Add work path CLI option (#6922)
+  * Fix logging documentation (#6904)
+  * Some logging documentation (#6498)
+  * Fix link to Hacking on Gitea on From-Source doc page (#6471)
+  * Fix typos in docs command-line examples (#6466)
+  * Added docker example for backup (#5846)
+
+## [1.8.3](https://github.com/go-gitea/gitea/releases/tag/v1.8.3) - 2019-06-17
+
+* BUGFIXES
+  * Always set userID on LFS authentication (#7224) (Part of #6993)
+  * Fix LFS Locks over SSH (#6999) (#7223)
+  * Fix duplicated file on pull request conflicted files (#7211) (#7214)
+  * Detect noreply email address as user (#7133) (#7195)
+  * Don't get milestone from DB if ID is zero (#7169) (#7174)
+  * Allow archived repos to be (un)starred and (un)watched (#7163) (#7168)
+  * Fix GCArgs load from ini (#7156) (#7157)
+
+## [1.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
+
+* BUGFIXES
+  * Fix possbile mysql invalid connnection error (#7051) (#7071)
+  * Handle invalid administrator username on install page (#7060) (#7063)
+  * Disable arm7 builds (#7037) (#7042)
+  * Fix default for allowing new organization creation for new users (#7017) (#7034)
+  * SearchRepositoryByName improvements and unification (#6897) (#7002)
+  * Fix u2f registrationlist ToRegistrations() method (#6980) (#6982)
+  * Allow collaborators to view repo owned by private org (#6965) (#6968)
+  * Use AppURL for Oauth user link (#6894) (#6925)
+  * Escape the commit message on issues update (#6901) (#6902)
+  * Fix regression for API users search (#6882) (#6885)
+  * Handle early git version's lack of get-url (#7065) (#7076)
+  * Fix wrong init dependency on markup extensions (#7038) (#7074)
+
+## [1.8.1](https://github.com/go-gitea/gitea/releases/tag/v1.8.1) - 2019-05-08
+
+* BUGFIXES
+  * Fix 404 when sending pull requests in some situations (#6871) (#6873)
+  * Enforce osusergo build tag for releases (#6862) (#6869)
+  * Don't post process commit summary in templates (#6842) (#6868)
+  * Fix 500 when reviewer is deleted (#6856) (#6860)
+  * Fix v78 migration for MSSQL (#6823) (#6854)
+  * Added tags pull step to drone config to show correct version hashes (#6836) (#6839)
+  * Fix double-generation of scratch token (#6833) (#6835)
+  * When mirroring we should set the remote to mirror (#6824) (#6834)
+  * Show scrollbar only when needed (#6802) (#6803)
+  * Service worker js is missing a comma (#6788) (#6795)
+  * Set user search base field optional in LDAP (simple auth) edit page (#6779) (#6789)
+  * Fix team edit API panic (#6780) (#6785)
+  * Minor CSS cleanup for the navbar (#6553) (#6781)
+  * Stricter domain name pattern in email regex (#6739) (#6768)
+  * Detect and restore encoding and BOM in content (#6727) (#6765)
+  * Fix org visibility bug when git cloning (#6743) (#6762)
+  * OAuth2 token can be used in basic auth (#6747) (#6761)
+  * Fix missing return (#6751) (#6756)
+  * Fix sorting repos on org home page with non-admin login (#6741) (#6746)
+  * Drop is_bare IDX only when it exists for MySQL and MariaDB (#6736) (#6744)
+  * Fix team members API (#6714) (#6729)
+  * Load issue attributes when editing an issue with API (#6723) (#6725)
+  * Fix config ui error about cache ttl (#6861) (#6865)
+
+## [1.8.0](https://github.com/go-gitea/gitea/releases/tag/v1.8.0) - 2019-04-20
+
+* SECURITY
+  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6594)
+  * Resolve 2FA bypass on API (#6676) (#6674)
+  * Prevent the creation of empty sessions for non-logged in users (#6690) (#6677)
+* BREAKING
+  * Add "ghost" and "notifications" to list of reserved user names. (#6208)
+  * Change sqlite DB path default to data directory (#6198)
+  * Adds MustChangePassword to user create/edit API (#6193)
+  * Disable redirect for i18n (#5910)
+  * Releases API paging (#5831)
+  * Allow Macaron to be set to log through to gitea.log (#5667)
+  * Don't close issues via commits on non-default branch (#5622)
+* FEATURES
+  * Add regenerate secret feature for oauth2 (#6291)
+  * Expose issue stopwatch toggling via API (#5970)
+  * Add other session providers (#5963)
+  * Pull request conflict files detection (#5951)
+  * Integrate OAuth2 Provider (#5378)
+  * Implement "conversation lock" for issue comments (#5073)
+  * Feature: Archive repos (#5009)
+  * Discord Oauth2 support (#4476)
+  * Allow to set organization visibility (public, internal, private) (#1763)
+  * Added URL mapping for Release attachments like on github.com (#1707)
+* ENHANCEMENTS
+  * Add support for client basic auth for exchanging access tokens (#6293)
+  * Add ability to sort issues by due date (#6206) (#6244)
+  * Style tweaks to issue selection (#6196)
+  * Increase Username and Orgname MaxSize 35 -> 40 (#6178)
+  * Coverage profile with multiple packages (#6167)
+  * Split setting.go to multiple files (#6154)
+  * Allow labels to contain emoji (#6063)
+  * Disable git fsck for mirrored repos by default (#6018)
+  * Add default time out for git operations (#6015)
+  * Split setting.go as multiple files (#6014)
+  * Make dashboard navbar and footer full-width (#6013)
+  * Add lang specific font stacks for CJK (#6007)
+  * Fix header menu misalignment (#6002)
+  * Enhance closed PR and Issue status in the list (#6000)
+  * Make navbar full width (#5998)
+  * Add option to close issues via commit on a non master branch (#5992)
+  * Support n as a line highlight prefix (#5987)
+  * Search for org repos (#3031) (#5986)
+  * Minor UI tweaks (#5980)
+  * Use native golang SSH library but ssh-keygen when enable built-in SSH server to remove dependent on that command lines (#5976)
+  * Dashboard tweaks (#5974)
+  * Fixes for repo topic editor (#5971)
+  * Display the branch name in the commit view (#5950)
+  * handle milestone events for issues and PR (#5947)
+  * Add label names as filter in issue search api (#5946)
+  * Repo header tweaks (#5945)
+  * Better support for long repo names (#5932)
+  * Fix wrapping long code lines (#5927)
+  * Change GPG Validation colors and remove inline CSS (#5404) (#5896)
+  * Fix "pulls.blocked_by_approvals" text (#5879)
+  * Rename reject to 'request changes' (#5858)
+  * Move input fields to add members to a team and repos to a team (#5853)
+  * Config option to disable automatic repo watching (#5852)
+  * New Issue ?body= query (#5851)
+  * Add API to list tags (#5850)
+  * Pagination for git tree API (#5838)
+  * Add InternalTokenURI to load InternalToken from an external file (#5812)
+  * Allow markdown files to read from the LFS (#5787)
+  * Add the ability to use multiple labels as filters (#5786)
+  * Adjust log settings when a user is not found. (#5771)
+  * Log IP of failed ssh connection (#5766)
+  * Moved defaults in defaults.go to setting.go (#5764)
+  * Make DB connect more robust (#5738)
+  * Add Default Pull Request Title (#5735)
+  * Refactor repo.isBare to repo.isEmpty #5629 (#5714)
+  * Add flag to skip repository dumping (#5695)
+  * Prioritize "readme.md" (#5691)
+  * Improve "Fork button" for guests by showing a pop up asking them to log in before forking (#5690)
+  * Allow for user specific themes (#5668)
+  * Display branch name in delete branch confirmation modal. (#5654)
+  * New API routes added (#5594)
+  * Refactor notification for indexer (#5111)
+  * Refactor mail notification (#5110)
+  * Show email if the authenticated user owns the profile page being requested for (#4981)
+  * Optimize pulls merging (#4921)
+  * Sort Repositories widget by most recently updated (#3963) (#4599)
+  * Allow markdown table to scroll (#4401)
+  * Automatically clear stopwatch on merging a PR (#4327)
+  * Add the Owner Name to differentiate when merging (#3807)
+  * Add title attributes to all items in the repo list viewer (#6258) (#6650)
+* BUGFIXES
+  * Fix dropdown icon padding (#6651) (#6654)
+  * Fix wrong GPG expire date (#6643) (#6644)
+  * Fix forking an empty repository (#6637) (#6653)
+  * Remove call to EscapePound .Link as it is already escaped (#6656) (#6666)
+  * Properly escape on the redirect from the web editor (#6657) (#6667)
+  * Allow resend of confirmation email when logged in (#6482) (#6486)
+  * Fix mail notification when close/reopen issue (#6581) (#6588)
+  * Change API commit summary to full message (#6591) (#6592)
+  * Add option to disable refresh token invalidation (#6584) (#6587)
+  * Fix bug user search API pagesize didn't obey ExplorePagingNum (#6579) (#6586)
+  * Fix new repo alignment (#6583) (#6585)
+  * Prevent server 500 on compare branches with no common history (#6555) (#6558)
+  * Properly escape release attachment URL (#6512) (#6523)
+  * Hacky fix for alignment of the create-organization dialog (#6455) (#6462)
+  * Disable benchmarking during tag events on DroneIO (#6365) (#6366)
+  * Make sure units of a team are returned (#6379) (#6381)
+  * Don't Unescape redirect_to cookie value (#6399) (#6401)
+  * Fix dump table name error and add some test for dump database (#6394) (#6402)
+  * Fix migration v82 to ignore unsynced tags between database and git data; Add missing is_archived column on repository table (#6387) (#6403)
+  * Display correct error for invalid mirror interval (#6414) (#6429)
+  * Clean up ref name rules (#6437) (#6439)
+  * Fix Hook & HookList in Swagger (#6432) (#6440)
+  * Change order that PostProcess Processors are run (#6445) (#6447)
+  * Clean up various use of escape/unescape functions for URL generation (#6334)
+  * Return 409 when creating repo if it already exists. (#6330)
+  * Add same changes from issues page to milestone->issues page (#6328)
+  * Fix ParsePatch function to work with quoted diff --git strings (#6323)
+  * Fix reported issue in repo description (#6306)
+  * Use url.PathEscape to escape the branchname (#6304)
+  * Add robots.txt as reserved username (#6272)
+  * Replace linkRegex with xurls library (#6261)
+  * Remove visitLinksForShortLinks features (#6257)
+  * Add unit types to repo action URL to correctly show 404 when archived (#6247)
+  * Check organization visibility before everything else (#6234) (#6235)
+  * Prevent double-close of issues (#6233)
+  * Override xorm type mapping for U2F counter (#6232)
+  * Add isAdmin to user API response (#6231)
+  * Update git vendor to fix wrong release commit id and add migrations (#6224)
+  * Fix fork button (#6223)
+  * Fix renames over redirects (#6216)
+  * Fix display dashboard even if require to change password (#6214)
+  * Create a repo redirect when transferring ownership (#6210) (#6211)
+  * Fix issue update race condition (#6194)
+  * Fix bug when migrate repository 500 when repo is existed (#6188)
+  * Fix scrollbar always present on page body (#6177)
+  * Fix bug when set indexer as db and add tests (#6173)
+  * Modify linkRegex to require http|https (#6171)
+  * Fix bug user could change private repository to public when force private enabled. (#6156)
+  * Fix admin list user/org API (#6143)
+  * Make repo creation for API similar to UI (#6142)
+  * Make document body a flexbox (#6139)
+  * Refactor issue indexer, add some testing and fix a bug (#6131)
+  * Load Issue attributes for API call (#6122)
+  * Fix bug when update owner team then visit team's repo return 404 (#6119)
+  * Fix heatmap and repository menu display in Internet Explorer 9+ (#6117)
+  * Show private organization for admin, fix #6111 (#6112)
+  * Fix prohibit login check on authorization (#6106)
+  * Move to ldap.v3 to fix #5928 (#6105)
+  * Remove use MakeAssigneeList in webhooks to fix deadlock (#6102)
+  * Allow display of LFS stored Readme.md on directory page (#6073) (#6099)
+  * Make sure labels are actually returned (#6053)
+  * Fix panic: template: repo/issue/list:210: unexpected "=" in operand (#6041)
+  * After deleting a repo on admin panel, UI should remember the last sort type (#6033)
+  * Default create repository on organisation on its dashboard (#6026)
+  * Swagger: Remove spaces in MergePullRequestOption enum (#6016)
+  * Fix metrics auth token detection (#6006)
+  * Fix repo header issues (#5995)
+  * Fix bug when deleting a linked account will removed all (#5989)
+  * Make organization dropdown scrollable when using mouse wheel (#5988)
+  * Fix empty ssh key importing in ldap (#5984)
+  * Admin config page mailertype setting option update (#5973)
+  * Fix redirect loop during forced password change (#5965)
+  * Show user who created the repository instead of the organisation in action feed (#5948)
+  * Remove all CommitStatus when a repo is deleted (#5940)
+  * Fix ssh deploy and user key constraints (#1357) (#5939)
+  * Fix log output (#5938)
+  * Set PusherName and PusherID to owner on deploy key to fix pushing with deploy keys (#5935)
+  * Fix compare button (#5929)
+  * Fix bug when read public repo lfs file (#5912)
+  * Only allow local login if password is non-empty (#5906)
+  * Recover panic in orgmode.Render if bad orgfile (#4982) (#5903)
+  * Provide better panic handling (#5902)
+  * Respect value of REQUIRE_SIGNIN_VIEW (#5901)
+  * Show a 404 not a 500 if a repo does not exist (#5900)
+  * Ensure repo is loaded in mailer (Completely fix #5891) (#5895)
+  * Ensure issue.Poster is loaded in mailIssueCommentToParticipants (#5891)
+  * Correct footer height if screen-width is to small (fixes #5878) (#5889)
+  * In gitea serv switch off console logger to fix #5866 (#5887)
+  * Don't allow pull requests to be created on an archived repository (#5883)
+  * Support reviews on a deleted file path (#5880)
+  * Fix compare button on upstream repo leading to 404 (#5877)
+  * Fix null pointer on not logged in attempt to Sudo (#5872)
+  * Fix new release creation API to allow empty target (#5870)
+  * Fix an error while adding a dependency via UI. (#5862)
+  * Fix failing migration v67 (#5849)
+  * Fix delete correct temp directory (#5839)
+  * Make sure .git/info is created before generating .git/info/sparse-che… (#5825)
+  * Fix topics saving internal error and disable for archived repos (#5821)
+  * Fix TLS errors when using acme/autocert for local connections (#5820)
+  * When creating new repository fsck option should be enabled (#5817)
+  * Request for public keys only if LDAP attribute is set  (#5816)
+  * Fix serving of raw wiki files other than .md (#5814)
+  * Fix migration 78 error mssql (#5791)
+  * Disallow empty titles (#5785)
+  * Fix the v78 migration script (#5776)
+  * Ensure valid git author names passed in signatures (#5774)
+  * Fix wrong assumption where a user is always said to have unassigned (her)himself (#5769)
+  * Upgrade go-sql-driver/mysql to fix invalid connection error (#5748)
+  * Fixing PostgreSQL dump creation (#5747)
+  * Add proper CORS preflight origin validation (#5740)
+  * Disable auto-migrate in docker container (#5730)
+  * In basic auth check for tokens before call UserSignIn (#5725)
+  * Pooled and buffered gzip implementation (#5722)
+  * Ensure that sessions are passed into queries that could use the database to prevent deadlocks (#5718)
+  * Keep file permissions during database migration (#5707)
+  * Use correct value for "MSpan Structures Obtained" #4742 (#5706)
+  * Refactor editor upload, update and delete to use git plumbing and add LFS support (#5702)
+  * Update xorm to fix issue #5659 and #5651 (#5680)
+  * Fix public will not be reused as public key after deleting as deploy key (#5671)
+  * When redirecting, clean the path (#5669)
+  * Don't list an issue on its own dependency list UI. (#5658)
+  * Fix commit page showing status for current default branch (#5649) (#5650)
+  * Only count users own actions for heatmap contributions (#5647)
+  * Fix sqlite deadlock when assigning to a PR (#5640)
+  * Refactor issue indexer (#5363)
+* TESTING
+  * Run benchmark at tag to track performances (#6035)
+  * Add test environment for MySQL8 (#5234)
+* BUILD
+  * Use go 1.12 for tests and deprecate go 1.9 (#6186)
+  * Makefile changes for Windows and easier development (#6103)
+  * Update bleve dependency to latest master revision (#6100)
+  * Switch to more recent build of xgo (#6070)
+  * Add autoprefixer to css build (#6029)
+  * Update the version of less (#6010)
+  * Make log mailer for testing (#5893)
+* DOCS
+  * Add more tests and docs for issue indexer, add db indexer type for searching from database (#6144)
+  * update default value of `--must-change-password` cli flag (#6032)
+  * Update and expand information about building Gitea (#6019)
+  * Update U2F Section of app.ini.sample (#5994)
+  * Update swagger for release API pagination (#5841)
+  * Added docs for the tree api (#5834)
+* MISC
+  * Add single commit API support (#5843)
+  * Add missing GET teams endpoints (#5382)
+  * Migrate database if app.ini found (#5290)
+
+## [1.7.6](https://github.com/go-gitea/gitea/releases/tag/v1.7.6) - 2019-04-12
+
+* SECURITY
+  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6595)
+* BUGFIXES
+  * Allow resend of confirmation email when logged in (#6482) (#6487)
+
+## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
+
+* BUGFIXES
+  * Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
+  * Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
+  * Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
+
+## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
+
+* SECURITY
+  * Fix potential XSS vulnerability in repository description. (#6306) (#6308)
+* BUGFIXES
+  * Fix wrong release commit id (#6224) (#6300)
+  * Fix panic on empty signed commits (#6292) (#6300)
+  * Fix organization dropdown not being scrollable when using mouse wheel (#5988) (#6246)
+  * Fix displaying dashboard even if required to change password (#6214) (#6215)
+
+## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
+
+* BUGFIXES
+  * Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
+  * Load Issue attributes for API /repos/{owner}/{repo}/issues/{index} (#6122) (#6185)
+  * Fix bug whereby user could change private repository to public when force private enabled. (#6156) (#6165)
+  * Fix bug when update owner team then visit team's repo return 404 (#6119) (#6166)
+  * Fix heatmap and repository menu display in Internet Explorer 9+ (#6117) (#6137)
+  * Fix prohibit login check on authorization (#6106) (#6115)
+  * Fix LDAP protocol error regression by moving to ldap.v3 (#6105) (#6107)
+  * Fix deadlock in webhook PullRequest (#6102) (#6104)
+  * Fix redirect loop when password change is required and Gitea is installed as a suburl (#5965) (#6101)
+  * Fix compare button regression (#5929) (#6098)
+  * Recover panic in orgmode.Render if bad orgfile (#4982) (#5903) (#6097)
+
+## [1.7.2](https://github.com/go-gitea/gitea/releases/tag/v1.7.2) - 2019-02-14
+
+* BUGFIXES
+  * Remove all CommitStatus when a repo is deleted (#5940) (#5941)
+  * Fix notifications on pushing with deploy keys by setting hook environment variables (#5935) (#5944)
+  * Silence console logger in gitea serv (#5887) (#5943)
+  * Handle milestone webhook events for issues and PR (#5947) (#5955)
+  * Show user who created the repository instead of the organization in action feed (#5948) (#5956)
+  * Fix ssh deploy and user key constraints (#1357) (#5939) (#5966)
+  * Fix bug when deleting a linked account will removed all (#5989) (#5990)
+  * Fix empty ssh key importing in ldap (#5984) (#6009)
+  * Fix metrics auth token detection (#6006) (#6017)
+  * Create repository on organisation by default on its dashboard (#6026) (#6048)
+  * Make sure labels are actually returned in API (#6053) (#6059)
+  * Switch to more recent build of xgo (#6070) (#6072)
+  * In basic auth check for tokens before call UserSignIn (#5725) (#6083)
+
+## [1.7.1](https://github.com/go-gitea/gitea/releases/tag/v1.7.1) - 2019-01-31
+
+* SECURITY
+  * Disable redirect for i18n (#5910) (#5916)
+  * Only allow local login if password is non-empty (#5906) (#5908)
+  * Fix go-get URL generation (#5905) (#5907)
+* BUGFIXES
+  * Fix TLS errors when using acme/autocert for local connections (#5820) (#5826)
+  * Request for public keys only if LDAP attribute is set (#5816) (#5819)
+  * Fix delete correct temp directory (#5840) (#5839)
+  * Fix an error while adding a dependency via UI (#5862) (#5876)
+  * Fix null pointer in attempt to Sudo if not logged in (#5872) (#5884)
+  * When creating new repository fsck option should be enabled (#5817) (#5885)
+  * Prevent nil dereference in mailIssueCommentToParticipants (#5891) (#5895) (#5894)
+  * Fix bug when read public repo lfs file (#5913) (#5912)
+  * Respect value of REQUIRE_SIGNIN_VIEW (#5901) (#5915)
+  * Fix compare button on upstream repo leading to 404 (#5877) (#5914)
+* DOCS
+  * Added docs for the tree api (#5835)
+* MISC
+  * Include Go toolchain to --version (#5832) (#5830)
+
+## [1.7.0](https://github.com/go-gitea/gitea/releases/tag/v1.7.0) - 2019-01-22
+
+* SECURITY
+  * Do not display the raw OpenID error in the UI (#5705) (#5712)
+  * When redirecting clean the path to avoid redirecting to external site (#5669) (#5679)
+  * Prevent DeleteFilePost doing arbitrary deletion (#5631)
+* BREAKING
+  * Restrict permission check on repositories and fix some problems (#5314)
+  * Show only opened milestones on issues page milestone filter (#5051)
+* FEATURES
+  * Implement git refs API for listing references (branches, tags and other) (#5354)
+  * Approvals at Branch Protection (#5350)
+  * Add raw blob endpoint to get objects by SHA ID (#5334)
+  * Add api for user to create org (#5268)
+  * Create AuthorizedKeysCommand (#5236)
+  * User action heatmap (#5131)
+  * Refactor heatmap to vue component (#5401)
+  * Webhook for Pull Request approval/rejection (#5027)
+  * Add command for migrating database (#4954)
+  * Search keyword by splitting provided values by , (#4939)
+  * Create Progressive Web App (#4730)
+  * Give user a link to create PR after push (#4716)
+  * Add rebase with merge commit merge style (#3844) (#4052)
+* BUGFIXES
+  * Disallow empty titles (#5785) (#5794)
+  * Fix sqlite deadlock when assigning to a PR (#5640) (#5642)
+  * Don't close issues via commits on non-default branch. (#5622) (#5643)
+  * Fix commit page showing status for current default branch (#5650) (#5653)
+  * Only count users own actions for heatmap contributions (#5647) (#5655)
+  * Update xorm to fix issue postgresql dumping issues (#5680) (#5692)
+  * Use correct value for "MSpan Structures Obtained" (#5706) (#5716)
+  * Fix bug on modifying sshd username (#5624)
+  * Delete tags in mirror which are removed for original repo. (#5609)
+  * Fix wrong text getting saved on editing second comment on an issue. (#5608)
+  * Fix nil pointer when adding a due date  (#5587)
+  * Fix type mismatch of format string (#5574)
+  * Fix bug on upload file name (#5571)
+  * Issue is not overdue when it is on the same date #5566 (#5568)
+  * Fix indexer reindex bug when gitea restart (#5563)
+  * Fix table name typo on SQL (#5562)
+  * Synchronize SSH keys on login with LDAP + Fix SQLite deadlock on ldap ssh key deletion (#5557)
+  * Fix makefile generate buildstep (#5556)
+  * Fix nil pointer base branch bug (#5555)
+  * Fix permission check on api create org (#5523)
+  * Fix detect force push failure on deletion of protected branches (#5522)
+  * Fix approvals limitation (#5521)
+  * Fix bug when a read perm user to edit his issue (#5516)
+  * Fix adding reaction fail for read permission user (#5515)
+  * Fixing MSSQL timestamp type (#5511)
+  * Fix forgot deletion of notification when delete repository (#5506)
+  * Fix empty wiki (#5504)
+  * Fix clone wiki failed via ssh (#5503)
+  * Fix code review on mssql (#5502)
+  * Fix lfs version check warning log when using ssh protocol (#5501)
+  * Fix topic name length on database (#5493)
+  * Ensure that the `closed_at` is set for closed issues (#5449)
+  * Admin should be able to delete repos via the API even if he is not a member of the organization (#5443)
+  * Word-Break the WebHook url to prevent a ui-break (#5432)
+  * Fix forgot removed records when deleting user (#5429)
+  * Fix repository deletion when there is large number of issues in it (#5426)
+  * Fix heatmap colors for Chrome/Safari (#5421)
+  * Fix password variable shadowing (#5405)
+  * Fix dependent issue searching when gitea is run in subpath (#5392)
+  * Don't force a password change for the admin user when creating an account via cli (#5391)
+  * API: '/orgs/:org/repos': return private repos with read access (#5383)
+  * Don't send assign webhooks when creating issue (#5365)
+  * Removing Labels via EditPullRequest API (#5348)
+  * Migration fixes for gogs (0.11.66) to gitea (1.6.0) #5318 (#5341)
+  * Fix bug when users have serval teams with different units on different repositories (#5307)
+  * Fix U2F if gitea is configured in subpath (#5302)
+  * Fix file edit change preview functionality (#5300)
+  * Update gitignore list (#5258)
+  * Fixed heatmap not working in mssql (#5248)
+  * Fixed wrong api request url for instances running in subfolders (#5247)
+  * Fix compatibility heatmap with mysql 8 (#5232)
+  * Fix data race on migrate repository (#5224)
+  * Fix sqlite and mssql lock (#5214)
+  * Fix sqlite lock (#5210)
+  * Fix: Accept web-command cli flags if web-command is committed (#5200)
+  * Fix: Add secret to all webhook's payload where it has been missing (#5199)
+  * Fix race on updatesize (#5190)
+  * Fix create team, update team missing units (#5188)
+  * Fix sqlite lock (#5184 & #5176)
+  * Fix showing pull request link when delete a branch (#5166)
+  * Fix JSON result of empty array in heatmap data array (#5154)
+  * Update build tags for sqlite_unlock notify (#5144)
+  * This commit will reduce join star, repo_topic, topic tables on repo search, so that fix extra columns problem on mssql (#5136)
+  * Fix deadlock when sqlite (#5118)
+  * Add comment replies (#5104)
+  * Fix home page template regression (#5102)
+  * Fix regex to support optional end line of old section in diff hunk (#5096)
+  * LDAP via simple auth separate bind user and search base (#5055)
+  * Fix markdown image with link (#4675)
+  * Fix to 3819 - Filtering issues by tags on main screen issues (#3824)
+* ENHANCEMENTS
+  * Delete organization endpoint added (#5601)
+  * Update Licenses (#5558)
+  * Support reverse proxy providing email (#5554)
+  * Add git protocol v2 support via SSH on Docker image (#5520)
+  * Add tests for api user orgs (#5494)
+  * Allow link verification for services like Mastodon (#5481)
+  * Improve team members and repositories settings UI (#5457)
+  * Remove the required class from optional ssh port in installation page (#5428)
+  * Explicitly disable Git credential helper (#5367)
+  * Setting Labels via EditPullRequest API (#5347)
+  * Implement pasting image from clipboard for browsers that supports that (#5317)
+  * Milestone issues and pull requests (#5293)
+  * Support envs on external render commands (#5278)
+  * Add option to disable automatic mirror syncing. (#5242)
+  * Remove unused db init on commands serv, update, hooks (#5225)
+  * Serve audio files using HTML5 audio tag (#5221)
+  * Pass link prefixes to external markup parsers (#5201)
+  * Add AutoHead functionality. (#5186)
+  * Fix emojis not showing in commit messages (#5168)
+  * Block registration based on email domain (#5157)
+  * Update vendor/go-sqlite3 (#5133 & #5162)
+  * Update x/net lib (#5169)
+  * Show review summary in pull requests (#5132)
+  * Use type switch (#5122)
+  * Remove duplicated if bodies (#5121)
+  * Remove check for negative length (#5120)
+  * Make switch more clear (#5119)
+  * Use named const instead of a raw string (#5115)
+  * Fix issue where ecdsa and other key types are not synced from LDAP (#5092) (#5094)
+  * Refactor: err != nil check, just return error instead (#5093)
+  * Add notification interface and refactor UI notifications (#5085)
+  * Use APP_NAME on home page (#5048)
+  * Explicitly decide whether to  use TLS in mailer's configuration (#5024)
+  * Generate random password (#5023)
+  * UX of link account (Step 1) (#5006)
+  * Make sure argsSet verifies string isn't empty too (#4980)
+  * Improve performance of dashboard (#4977)
+  * Keys API changes (#4960)
+  * Add must-change-password flag to cli for creating a user (#4955)
+  * Use native go method to get current user rather than environment variable (#4930)
+  * Make gitea serv use api/internal (#4886)
+  * Add support for search by uid (#4876)
+  * Allow to add organization members as collaborators on organization owned repositories (#4748)
+* TESTING
+  * Kill testing processes if the test takes too long (#5174)
+  * Update outdated Go toolchain version for .drone.yml (#5146)
+  * Increase the retry limit to 20 times and the interval to 200ms (#5134)
+  * Retry test-fixtures loading in case of transaction rollback (#5125)
+  * Added test environment for mssql (#4282)
+* BUILD
+  * Replace lint to revive (#5422)
+  * Update golang version in Dockerfile (#5246)
+* DOCS
+  * Typo in routers/api/v1/org/org.go fixed. (#5598)
+  * Update the docs for sqlite_unlock_notify (#5145)
+  * CN translation of docs part (#5049)
+  * Kubernetes deployment file (#5046)
+* MISC
+  * Upgrade alpine to 3.8 (#5423)
+  * Git-Trees API (#5403)
+  * Only chown directories during docker setup if necessary. Fix #4425 (#5064)
+
+## [1.6.4](https://github.com/go-gitea/gitea/releases/tag/v1.6.4) - 2019-01-15
+
+* BUGFIX
+  * Fix SSH key now can be reused as public key after deleting as deploy key (#5671) (#5685)
+  * When redirecting clean the path to avoid redirecting to external site (#5669) (#5703)
+  * Fix to use correct value for "MSpan Structures Obtained" (#5706) (#5715)
+
+## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
+
+* SECURITY
+  * Prevent DeleteFilePost doing arbitrary deletion (#5631)
+* BUGFIX
+  * Fix wrong text getting saved on editing second comment on an issue (#5608)
+
+## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
+
+* SECURITY
+  * Sanitize uploaded file names (#5571) (#5573)
+  * HTMLEncode user added text (#5570) (#5575)
+* BUGFIXES
+  * Fix indexer reindex bug when gitea restart (#5563) (#5564)
+  * Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
+  * Fix bug when a read perm user to edit his issue (#5516) (#5534)
+  * Detect force push failure on deletion of protected branches (#5522) (#5531)
+  * Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
+  * Fix forgot deletion of notification when delete repository (#5506) (#5514)
+  * Fix undeleted content when deleting user (#5429) (#5509)
+  * Fix empty wiki (#5504) (#5508)
+
+## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
+
+* BUGFIXES
+  * Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
+  * API: '/orgs/:org/repos': return private repos with read access (#5393)
+  * Fix repository deletion when there is large number of issues in it (#5426) (#5434)
+  * Word-break the WebHook url to prevent a ui-break (#5445)
+  * Admin should be able to delete repos via the API even if they are not a member of the organization (#5443) (#5447)
+  * Ensure that the `closed_at` is set for closed (#5450)
+  * Fix topic name length on database (#5493) (#5495)
+
+## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
+
+* BREAKING
+  * Respect email privacy option in user search via API (#4512)
+  * Simply remove tidb and deps (#3993)
+  * Swagger.v1.json template (#3572)
+* SECURITY
+  * Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
+  * Improve URL validation for external wiki  and external issues (#4710)
+  * Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
+  * Don't disclose emails of all users when sending out emails (#4664)
+  * Check that repositories can only be migrated to own user or organizations (#4366)
+* FEATURES
+  * Add comment replies (#5147) (#5104)
+  * Pull request review/approval and comment on code (#3748)
+  * Added dependencies for issues (#2196) (#2531)
+  * Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
+  * Add sudo functionality to the API (#4809)
+  * Add oauth providers via cli (#4591)
+  * Disable merging a WIP Pull request (#4529)
+  * Force user to change password (#4489)
+  * Add letsencrypt to Gitea (#4189)
+  * Add push webhook support for mirrored repositories (#4127)
+  * Add csv file render support defaultly (#4105)
+  * Add Recaptcha functionality to Gitea (#4044)
+* ENHANCEMENTS
+  * Fix milestones sorted wrongly (#4987)
+  * Allow api to create tags for releases if they don't exist (#4890)
+  * Fix #4877 to follow the OpenID Connect Audiences spec (#4878)
+  * Enforce token on api routes [fixed critical security issue #4357] (#4840)
+  * Update legacy branch and tag URLs in dashboard to new format (#4812)
+  * Slack webhook channel name cannot be empty or just contain an hashtag (#4786)
+  * Add whitespace handling to PR-comparison (#4683)
+  * Make reverse proxy auth optional (#4643)
+  * MySQL TLS (#4642)
+  * Make sure to set PR split view when creating/previewing a pull request  (#4617)
+  * Log user in after a successful sign up (#4615)
+  * Fix typo IsPullReuqestBroken -> IsPullRequestBroken (#4578)
+  * Allow admin toggle forcing a password change for newly created users (#4563)
+  * Update jQuery to v1.12.4 (#4551)
+  * Env var GITEA_PUSHER_EMAIL (#4516)
+  * Feat(repo): support search repository by topic name (#4505)
+  * Small improvements to dependency UI (#4503)
+  * Make max commits in graph configurable (#4498)
+  * Add valid for lfs oid (#4461)
+  * Add shortcut to save wiki page (#4452)
+  * Allow administrator to create repository for any organization (#4368)
+  * Fix repository last updated time update when delete a user who watched the repo (#4363)
+  * Switch plaintext scratch tokens to use hash instead (#4331)
+  * Increase default TOTP secret size to 320 bits (#4287)
+  * Keep preseeded database password (#4284)
+  * Implemented hover text showing user FullName (#4261)
+  * Add ability to delete a token (#4235)
+  * Fix typos in i18n variable names. (#4080)
+  * Api: repos/search: add parameters to control the sort order (#3964)
+  * Add missing path in the Docker app.ini template (#2181)
+  * Add file name and branch to page title (#4902)
+  * Offline use of google fonts (#4872)
+  * Add missing History link to directory listings v2 (#4829)
+  * Locale for Edit and Remove due date issue (#4802)
+  * Disable 'May Import Local Repository' when is disabled by setting (Is… (#4780)
+  * API /admin/users/{username} missing parameter (#4775)
+  * Display error when adding a user to a team twice (#4746)
+  * Remove UsePrivilegeSeparation from the Docker sshd_config, see #2876 (#4722)
+  * Focus title input when clicking helper link (#4696)
+  * Add vendor to user reserved words and format words list according alphabet (#4685)
+  * Add gitea/issues link to 500 page (#4654)
+  * Hide home button when landing page is not set to home (#4651)
+  * Remove link to GitHub issues in 404 template (#4639)
+  * Cmd/serve: pprof cpu and memory profile dumps to disk (#4560)
+  * Add flash message after an account has been successfully activated (#4510)
+  * Prevent html entity escaping on delete branch (#4471)
+  * Locale for button Edit on protected branch (#4442)
+  * Update notification icon (#4343)
+  * Added front-end topics validation (#4316)
+  * Don't display buttons if there are no system notifications (#4280)
+  * Issue due date api (#3890)
+* BUGFIXES
+  * dont' send assign webhooks when creating issue (#5365)
+  * Fix create team, update team missing units (#5188)
+  * Fix file edit change preview functionality (#5300)
+  * *ix bug when users have serval teams with different units on different repositories (#5307)
+  * Fix U2F if gitea is configured in subpath (#5302)
+  * Fix markdown image with link (#4675)
+  * Remove maxlines option for file logger (#5282)
+  * Fix wrong api request url for instances running in subfolders (#5261) (#5247)
+  * Accept web-command cli flags if web-command is committed (#5245) (#5200)
+  * Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
+  * Fix data race on migrate repository (#5224) (#5230)
+  * Add secret to all webhook's payload where it has been missing (#5208) (#5199)
+  * Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
+  * Fix race on updatesize (#5190) (#5215)
+  * Fix filtering issues by tags on main screen issues (#5219) (#3824)
+  * Fix SQL quoting (#5137) (#5117)
+  * Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
+  * Fix release creation via API (#5076)
+  * Remove links from topics in edit mode  (#5026)
+  * Fix missing AppSubUrl in few more templates (fixup) (#5021)
+  * Fix missing AppSubUrl in some templates (#5020)
+  * Hide outdated comments in file view (#5017)
+  * Upgrade gopkg.in/testfixtures.v2 (#4999)
+  * Disable debug routes unless PPROF is enabled in configuration (#4995)
+  * Fix user menu item styling (#4985)
+  * Fix layout of the topics editing form (#4971)
+  * Fix null pointer dereference in ParseCommitWithSignature (#4962)
+  * Fix url in discord webhook (#4953)
+  * Detect charset and convert non UTF-8 files for display (#4950)
+  * Make sure to catch the right error so it is displayed on the UI (#4945)
+  * Fix(topics): don't redirect to explore page. (#4938)
+  * Fix bug forget to remove Stopwatch when remove repository (#4928)
+  * Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
+  * Fix: Crippled diff (#4726) (#4900)
+  * Fix trimming of markup section names (#4863)
+  * Issues api allow pulls and fix #4832 (#4852)
+  * Do not autocreate directory for new users/orgs (#4828) (#4849)
+  * Fix redirect with non-ascii branch names (#4764) (#4810)
+  * Fix missing release title in webhook (#4783) (#4796)
+  * User shouldn't be able to approve or reject his/her own PR (#4729)
+  * Make sure to reset commit count in the cache on mirror syncing (#4720)
+  * Fixed bug where team with admin privilege type doesn't get any unit  (#4719)
+  * Fix incorrect caption of webhook setting (#4701) (#4717)
+  * Allow WIP marker to contains < or > (#4709)
+  * Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
+  * Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
+  * Fix custom templates being ignored (#4638)
+  * Fix starring icon after semantic ui update (#4628)
+  * Fix Split-View line adjustment (#4622)
+  * Fix integer constant overflows in tests (#4616)
+  * Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
+  * Fix bugs when too many IN variables (#4594)
+  * Fix failure on creating pull request with assignees (#4419) (#4583)
+  * Fix panic issue on update avatar email (#4580) (#4581)
+  * Fix status code label for a successful webhook (#4540)
+  * An inactive user shouldn't be able to be added as a collaborator (#4535)
+  * Don't fail silently if trying to add a collaborator twice (#4533)
+  * Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
+  * Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
+  * Fix migration from older releases (#4495)
+  * Accept 'Data:' in commit graph (#4487)
+  * Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
+  * Relative URLs for LibreJS page (#4460)
+  * Redirect to correct page after using scratch token (#4458)
+  * Fix column droping for MSSQL that need new transaction for that (#4440)
+  * Replace src with raw to fix image paths (#4377)
+  * Add default merge options when creating new repository (#4369)
+  * Fix docker build (#4358)
+  * Fixes repo membership check in API (#4341)
+  * Dep upgrade mysql lib (#4161)
+  * Fix some issues with special chars in branch names (#3767)
+  * Responsive design fixes (#4508)
+* TRANSLATION
+  * Fix punctuation in English translation (#4958)
+  * Fix translation (#4355)
+
+## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
+
+* SECURITY
+  * Fix remote command execution vulnerability in upstream library (#5177) (#5196)
+
+## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
+
+* SECURITY
+  * Enforce token on api routes (#4840) (#4905)
+* BUGFIXES
+  * Remove links from topics in edit mode (#5030)
+  * Detect charset and convert non UTF-8 files for display (#4950) (#4994)
+  * Fix layout of the topics editing form (#4971) (#4993)
+  * Fix null pointer dereference in ParseCommitWithSignature (#4964)
+  * Fix url in discord webhook (#4951)
+  * Fix font-cropping UI bug in diff (#4726) (#4929)
+  * Fix bug forget to remove Stopwatch when remove repository (#4933)
+  * Fix bug when repo remained bare if multiple branches pushed (#4927)
+  * Fix redirect with non-ascii branch names (#4764) (#4887)
+  * Fix issues api allow pulls (#4852) (#4862)
+  * Fix trimming of markup section names (#4864)
+
+## [1.5.1](https://github.com/go-gitea/gitea/releases/tag/v1.5.1) - 2018-09-03
+
+* SECURITY
+  * Don't disclose emails of all users when sending out emails (#4784)
+  * Improve URL validation for external wiki and external issues (#4710) (#4740)
+  * Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706) (#4707)
+* BUGFIXES
+  * Fix missing release title in webhook (#4783) (#4800)
+  * Make sure to reset commit count in the cache on mirror syncing (#4770)
+  * Fixed bug where team with admin privilege type doesn't get any unit (#4759)
+  * Fix failure on creating pull request with assignees (#4583) (#4727)
+  * Hide org/create menu item in Dashboard if user has no rights (#4678) (#4686)
+* TRANSLATION
+  * Fix incorrect caption of webhook setting (#4701) (#4718)
+
+## [1.5.0](https://github.com/go-gitea/gitea/releases/tag/v1.5.0) - 2018-08-10
+
+* SECURITY
+  * Check that repositories can only be migrated to own user or organizations (#4366) (#4370)
+  * Limit uploaded avatar image-size to 4096px x 3072px by default (#4353)
+  * Do not allow to reuse TOTP passcode (#3878)
+* BUGFIXES
+  * Fix column droping for MSSQL that need new transaction for that (#4440) (#4484)
+  * Redirect to correct page after using scratch token (#4458) (#4472)
+  * Replace src with raw to fix image paths (#4377) (#4386)
+  * Fixes repo membership check in API (#4341) (#4379)
+  * Add default merge options when adding new repository (#4369) (#4373)
+  * Fix repository last updated time update when delete a user who watched the repo (#4363) (#4371)
+  * Fix html entity escaping in branch deletion message (#4471) (#4485)
+  * Fix out-of-transaction query in removeOrgUser (#4521) (#4524)
+  * Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519)
+  * Fix panic issue on update avatar email (#4580) (#4590)
+  * Fix bugs when too many IN variables (#4594) (#4597)
+  * Push whitelist now doesn't apply to branch deletion (#4601) (#4640)
+  * Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645) (#4650)
+* FEATURES
+  * Add cli commands to regen hooks & keys (#3979)
+  * Add support for FIDO U2F (#3971)
+  * Added user language setting (#3875)
+  * LDAP Public SSH Keys synchronization (#1844)
+  * Add topic support (#3711)
+  * Multiple assignees (#3705)
+  * Add protected branch whitelists for merging (#3689)
+  * Global code search support (#3664)
+  * Add label descriptions (#3662)
+  * Add issue search via API (#3612)
+  * Add repository setting to enable/disable health checks (#3607)
+  * Emoji Autocomplete (#3433)
+  * Implements generator cli for secrets (#3531)
+* ENHANCEMENTS
+  * Add more webhooks support and refactor webhook templates directory (#3929)
+  * Add new option to allow only OAuth2/OpenID user registration (#3910)
+  * Add option to use paged LDAP search when synchronizing users (#3895)
+  * Symlink icons (#1416)
+  * Improve release page UI (#3693)
+  * Add admin dashboard option to run health checks (#3606)
+  * Add branch link in branch list (#3576)
+  * Reduce sql query times in retrieveFeeds (#3547)
+  * Option to enable or disable swagger endpoints (#3502)
+  * Add missing licenses (#3497)
+  * Reduce repo indexer disk usage (#3452)
+  * Enable caching on assets and avatars (#3376)
+  * Add repository search ordered by stars/forks. Forks column in admin repo list (#3969)
+  * Add Environment Variables to Docker template (#4012)
+  * LFS: make HTTP auth period configurable (#4035)
+  * Add config path as an optionial flag when changing pass via CLI (#4184)
+  * Refactor User Settings sections (#3900)
+  * Allow square brackets in external issue patterns (#3408)
+  * Add Attachment API (#3478)
+  * Add EnableTimetracking option to app settings (#3719)
+  * Add config option to enable or disable log executed SQL (#3726)
+  * Shows total tracked time in issue and milestone list (#3341)
+* TRANSLATION
+  * Improve English grammar and consistency (#3614)
+* DEPLOYMENT
+  * Allow Gitea to run as different USER in Docker (#3961)
+  * Provide compressed release binaries (#3991)
+  * Sign release binaries (#4188)
+
+## [1.4.3](https://github.com/go-gitea/gitea/releases/tag/v1.4.3) - 2018-06-26
+
+* SECURITY
+  * HTML-escape plain-text READMEs (#4192) (#4214)
+  * Fix open redirect vulnerability on login screen (#4312) (#4312)
+* BUGFIXES
+  * Fix broken monitoring page when running processes are shown (#4203) (#4208)
+  * Fix delete comment bug (#4216) (#4228)
+  * Delete reactions added to issues and comments when deleting repository (#4232) (#4237)
+  * Fix wiki URL encoding bug (#4091) (#4254)
+  * Fix code tab link when viewing tags (#3908) (#4263)
+  * Fix webhook type conflation (#4285) (#4285)
+
+## [1.4.2](https://github.com/go-gitea/gitea/releases/tag/v1.4.2) - 2018-06-04
+
+* BUGFIXES
+  * Adjust z-index for floating labels (#3939) (#3950)
+  * Add missing token validation on application settings page (#3976) #3978
+  * Webhook and hook_task clean up (#4006)
+  * Fix webhook bug of response info is not displayed in UI (#4023)
+  * Fix writer cannot read bare repo guide (#4033) (#4039)
+  * Don't force due date to current time (#3830) (#4057)
+  * Fix wiki redirects (#3919) (#4065)
+  * Fix attachment ENABLED (#4064) (#4066)
+  * Added deletion of an empty line at the end of file (#4054) (#4074)
+  * Use ResolveReference instead of path.Join (#4073)
+  * Fix #4081 Check for leading / in base before removing it (#4083)
+  * Respository's home page not updated after first push (#4075)
+
+## [1.4.1](https://github.com/go-gitea/gitea/releases/tag/v1.4.1) - 2018-05-03
+
+* BREAKING
+  * Add "error" as reserved username (#3882) (#3886)
+* SECURITY
+  * Do not allow inactive users to access repositories using private key (#3887) (#3889)
+  * Fix path cleanup in file editor, when initilizing new repository and LFS oids  (#3871) (#3873)
+  * Remove unnecessary allowed safe HTML (#3778) (#3779)
+  * Correctly check http git access rights for reverse proxy authorized users (#3721) (#3743)
+* BUGFIXES
+  * Fix to use only needed columns from tables to get repository git paths (#3870) (#3883)
+  * Fix GPG expire time display when time is zero (#3584) (#3884)
+  * Fix to update only issue last update time when adding a comment (#3855) (#3860)
+  * Fix repository star count after deleting user (#3781) (#3783)
+  * Use the active branch for the code tab (#3720) (#3776)
+  * Set default branch name on first push (#3715) (#3723)
+  * Show clipboard button if disable HTTP of git protocol (#3773) (#3774)
+
+## [1.4.0](https://github.com/go-gitea/gitea/releases/tag/v1.4.0) - 2018-03-25
+
+* BREAKING
+  * Drop deprecated GOGS\_WORK\_DIR use (#2946)
+  * Fix API status code for hook creation (#2814)
+* SECURITY
+  * Escape branch name in dropdown menu (#3691) (#3692)
+  * Refactor and simplify to correctly validate redirect to URL (#3674) (#3676)
+  * Fix escaping changed title in comments (#3530) (#3534)
+  * Escape search query (#3486) (#3488)
+  * Sanitize logs for mirror sync (#3057)
+* FEATURES
+  * Serve .patch and .diff for pull requests (#3305, #3293)
+  * Add repo-sync-releases admin command (#3254)
+  * Support default private when creating or migrating repository (#3239)
+  * Writable deploy keys (closes #671) (#3225)
+  * Add Pull Request merge options - Ignore white-space for conflict checking, Rebase, Squash merge (#3188)
+  * Added progressbar for issues with checkboxes (#1146). (#3171)
+  * Mention completion for issue editor. (#3136)
+  * Add 'mark all read' option to notifications (#3097)
+  * Git LFS lock api (#2938)
+  * Add reactions to issues/PR and comments (#2856)
+  * Add dingtalk webhook  (#2777)
+  * Responsive view (#2750)
+* BUGFIXES
+  * Fix wiki inter-links with spaces (#3560) (#3632)
+  * Fix query protected branch bug (#3563) (#3571)
+  * Fix remove team member issue (#3566) (#3570)
+  * Fix the protected branch panic issue (#3567) (#3569)
+  * If Mirrors repository no content is fetched, updated time should not be changed (#3551) (#3565)
+  * Bug fix for mirrored repository releases sorted (#3522) (#3555)
+  * Add issue closed time column to fix activity closed issues list (#3537) (#3540)
+  * Update markbates/goth library to support OAuth2 with new dropbox API (#3533) (#3539)
+  * Fixes missing avatars in offline mode (#3471) (#3477)
+  * Fix synchronization bug in repo indexer (#3455) (#3461)
+  * Fix rendering of wiki page list if wiki repo contains other files (#3454) (#3463)
+  * Fix webhook X-GitHub-* headers casing for better compatibility (#3429)
+  * Add content type and doctype to requests made with go-get (#3426, #3423)
+  * Fix SQL type error for webhooks (#3424)
+  * Fix PR merge error (#3421)
+  * Recognize more characters in crossreferenced repo name (#3413)
+  * Fix MSSQL bug on org (#3405)
+  * HTML escape all lines of the search result (#3402)
+  * Change local copy origin url after repository rename (#3399)
+  * Force-push to base repo's ref/pull/#/head (#3393)
+  * Fix bug when a user delete but assigned on issue (#3318)
+  * Use issue number/index instead of id for API URL. Fix #3297 (#3298)
+  * Fix repo-transfer-and-team-repo-count bug (#3241)
+  * Fix always-on SSL Mode checkbox in admin page (#3208)
+  * Fix source download link when no code unit allowed (#3166)
+  * Fix org owner cannot be removed if he is not in owner team (#3164)
+  * Fix run web with -p push failed (#3154)
+  * Fix gpg tmpl (#3153)
+  * Fix SSH auth lfs locks (#3152)
+  * Improvements for supporting UI Location (#3146)
+  * Fix new pull request link (#3133)
+  * Fix missing branch in release bug (#3108)
+  * Allow adding collaborators with (fullname) (#3103)
+  * Fix repo links (#3093)
+  * fix lfs url refs + keep path upper/lowercase in db. (#3092)
+  * Fix redis session failed (#3086)
+  * Fix bugs in issue dashboard stats (#3073)
+  * Fix avatar URLs (#3069)
+  * Fix ref parsing in commit messages (#3067)
+  * Fix issue list branch link broken (#3061)
+  * sendmail: correct option to set envelope-sender (#3044)
+  * Fix missing password length check when change password (#3039)
+  * Fix git lfs path (#3016)
+  * Fix API-Endpoint release (#3005) (#3012)
+  * Set OpenID support on by default when installing new instance (#3010)
+  * Various wiki bug fixes (#2996)
+  * Fix go-get, src and raw urls to new scheme (#2978)
+  * Fix error when add user has full name to team (#2973)
+  * Fix memcache support when value is returned as string always (#2924)
+* ENHANCEMENTS
+  * Use GiteaServer as the user agent for http requests (#3404)
+  * Delete indexer DB entries when (re)creating index (#3385)
+  * Change how merged PR commit info are prepared (#3368)
+  * Asynchronously populate the repo indexer (#3366)
+  * Make the default action for the gitea executable that of running the webserver (#3331)
+  * Templates for extra links in top navbar and repo tool tabs. (#3308)
+  * Fixed asterisk based tasklist items #3295 (#3296)
+  * Add more additional template snippets (#3286)
+  * Open external tracker in blank window, consistently with wiki (#3227)
+  * Fix repo links on user profile (#3197)
+  * Enable emoji for wiki view (#3158)
+  * Small improve on deleting attachements (#3145)
+  * Reduce overhead of upgrades for users with custom stylesheets/JS (#3051)
+  * Default log level to Info without hardcoding it in installer (#3041)
+  * Memory usage improvements (#3013)
+  * Add fingerprint to ssh key endpoints. (#3009)
+  * Improve memory usage when reaching diff limits (#2990)
+  * Expandable commit bodies (#2980)
+  * Update gitgraph.js to fix blurry commit graph on HiDPI screens (#2957)
+  * Fix language names (#2955)
+  * Remove render issue link (#2954)
+  * Page parameter for repo search API (#2915)
+  * Apply LANDING\_PAGE config options for logged in users (#2894)
+  * Enable admin to search by email (#2888)
+  * Hide add key button if SSH is disabled (#2873)
+  * Fix comment API paths (#2813)
+  * Add an option to allow redirect of http port 80 to https. (#1928)
+* MISC
+  * Fix organization profile on mobile devices (#3332)
+  * Fix guide link for webhooks in repository settings (#3291) (#3292)
+  * Enable Libravatar by default in new installations (#3287)
+  * Improve suppressed diff boxes (#3193)
+  * fix button heights on commits page (#3091)
+  * Minor copy changes (#3074)
+  * Sort repos in issues dashboard sidebar (#3072)
+  * Remove box-shadow from UI, fix dashboard issue (#3065)
+  * Adjust branch button size (#3063)
+  * Fix misalignment issue in repo header (#3062)
+  * Delete a user's public key via admin api (closes #3014) (#3059)
+  * Dashboard: Fix line height problem in issue titles (#3054)
+  * Remove duplicate "Max Diff Lines" from config view (#2987)
+  * Drop unmaintained gogs migration script (#2947)
+  * App restarts to quickly if it fails to start. (#2945)
+  * Add owner to delete repo message (#2886)
+
+## [1.3.1](https://github.com/go-gitea/gitea/releases/tag/v1.3.1) - 2017-12-08
+
+* BUGFIXES
+  * Sanitize logs for mirror sync (#3057, #3082) (#3078)
+  * Fix missing branch in release bug (#3108) (#3117)
+  * Fix repo indexer and submodule bug (#3107) (#3110)
+  * Fix legacy URL redirects (#3100) (#3106)
+  * Fix redis session failed (#3086) (#3089)
+  * Fix issue list branch link broken (#3061) (#3070)
+  * Fix missing password length check when change password (#3039) (#3071)
+
+## [1.3.0](https://github.com/go-gitea/gitea/releases/tag/v1.3.0) - 2017-11-29
+
+* BREAKING
+  * Make URL scheme unambiguous (#2408)
+* FEATURES
+  * Add branch overiew page (#2108)
+  * Code/repo search (#2582)
+  * Add Activity page to repository (#2674)
+  * Issue Timetracking (#2211)
+  * Add orgmode document type on file view and readme (#2525)
+  * Add external markup render support (#2570)
+  * Implementation of discord webhook (#2402)
+  * Webhooks for repo creation/deletion (#1663)
+  * Complete push webhooks (#2530)
+  * Add possibility to record branch information in an issue (#780)
+  * Create new branch from branch selection dropdown (#2130)
+  * Implementation of all repositories of a user from user->settings (#1740)
+  * Add LFS object verification step after upload (#2868)
+  * Configurable SSH cipher suite (#913)
+  * Disable custom Git Hooks globally via configuration file (#2450)
+  * Sync releases table with tags on push and for mirrors (#2459)
+* BUGFIXES
+  * Fix label comments for French locale (#3017)
+  * Remove duplicate "Max Diff Lines" from config view (#3001)
+  * Fix over-escaped characters (#2992)
+  * Fix go-get, src and raw urls to new scheme (#2986)
+  * Fix error when add user has full name to team (#2975)
+  * Fix files/commits of merged PRs (#2970)
+  * Update golang x/crypto dependencies - Fix SSH transport fail (#2951)
+  * Fix memcache support when value is returned as string always (#2950)
+  * Fix issue link rendering in commit messages (#2897)
+  * Fix adding a new authentication source after selecting OAuth (#2889)
+  * Fix new branch creation to new url scheme (#2884)
+  * Allow spaces in username for LDAP users (#2880)
+  * Fix LFS not returning correct content length when requesting a range … (#2864)
+  * Fix fork repository cycle to self (#2860)
+  * Fix click create pull request button 404 (#2859)
+  * Fix API raw file content access for default branch (#2849)
+  * Clean repository ROOT directory name with filepath.Clean (#2846)
+  * Fix API raw requests for commits and tags (#2841)
+  * Fix order of comments (#2835)
+  * Issue content should not be updated when closing with comment (#2833)
+  * Fix ordering in app.ini and fix run mode option (#2829)
+  * Fix redirect url of legacy commits route (#2825)
+  * Fix commits page url (#2823)
+  * Fix wrong translations (#2818)
+  * Fix dropdown menu position when explore repos (#2808)
+  * Fix Git LFS object/repo link storage in database and small refactoring (#2803)
+  * Use relative URLs for avatars on the dashboard (#2800)
+  * Add checks for commits with missing author and time (#2771)
+  * Fix emojify image URL (#2769)
+  * Hide unactive on explore users and some refactors (#2741)
+  * Fix IE unsupported javascript construction in branch dropdown (#2736)
+  * Only update mirror last update after successful sync (#2730)
+  * Fix semantic-ui style conflict with v-cloak (#2722)
+  * Fixing wrong translation on sort type oldest/latest (#2720)
+  * Fix PR, milestone and label functionality if issue unit is disabled (#2710)
+  * Fix plain readme didn't render correctly on repo home page (#2705)
+  * Fix organization removal from watch table migration (#2703)
+  * Fix repository search function (#2689)
+  * fix panic on gogs webhook creation (#2675)
+  * Fix orgnization user watch repository (#2670)
+  * GPG key email verification no longer case sensitive (#2661) (#2663)
+  * Fix index column deletion (#2651)
+  * table `pull_request` wasn't updated correctly (#2649)
+  * Fix go get response if only app URL is custom in configuration (#2634)
+  * Fix doubled issue tab introduced in migration v16 (#2611)
+  * Rewrite migrations to not depend on future code changes (#2604)
+  * Fix implementation of repo Home func (#2601)
+  * Fix translation upload to crowdin (#2599)
+  * Reduce usage of allcols on update (#2596)
+  * fix go get subpackage bug (#2584)
+  * Fix broken migration to add can_push field back to table (#2574)
+  * fix readme view bug (#2566)
+  * Fix sending mail with a non-latin display name. #2102 (#2559)
+  * Restricting access to fork functioanlity to users with Code access (#2534)
+  * fix updated update on public key (#2514)
+  * Added bucket name to s3 drone plugin (#2505)
+  * fixes 500 error on dashboard when using MSSQL (#2504)
+  * fix wrong rendering of commit detail page (#2503)
+  * Hotfix: Add time manually adds time in nanoseconds (#2499)
+  * Remove repository mirrors from "collaborative" list (#2497)
+  * fix release failed since the wrong token name (#2496)
+  * Fix slice out of bounds error in mailer (#2479)
+  * Fix #2470 (#2477)
+  * fix orgnization webhooks (#2422)
+  * fix webhook test (#2415)
+  * fix missing orgnization discord webhook (#2414)
+  * Fix route handler order (#2409)
+  * Prevent sending emails and notifications to inactive users (#2384)
+  * Move themes to plugin directory. Fixes #2372 (#2375)
+  * fix duplicated feed (#2370)
+  * Fix missing collabrative repos (#2367)
+  * Only check at least one email gpg key (#2266)
+  * don't check minimum key size when disabled (#1754)
+  * Fix run command race (#1470)
+  * fix .netrc authentication (#2700)
+  * Fix so that user can still fork his own repository to his organizations (#2699)
+  * Fix can_push value to false in protected_branch (#2560)
+  * Fix copy in email templates (#2801)
+  * Fix inconsistencies in user settings UI (#2901)
+  * Fix attachments icon size on zoom in/out (#2853)
+  * Fix ignored errors in API route (#2850)
+  * Fix activity css conflict with semantic ui (#2758)
+  * Fix notifications tabs according to semantic-ui docs (#2733)
+  * Fix typos in app.ini (#2732)
+  * Fix duplicated rel attribute (#2549)
+  * Fix tests code to prevent some runtime errors (#2381)
+* ENHANCEMENTS
+  * Memory usage improvements and lower minimal git requirement to 1.7.2 (#3013) (#3028)
+  * Set OpenID support on by default when installing new instance (#3010) (#3027)
+  * Use api.TrackedTime in API (#2807)
+  * Configurable SSH key exchange algorithm and MAC suite (#2806)
+  * Add Safari pinned tab icon (#2799)
+  * Improve force push detect when push (#2798)
+  * Add wrapping to long diff lines (#2789)
+  * Link members and repositories count to each page on org home. (#2787)
+  * Show Sendmail settings on admin config page (#2782)
+  * Add commit count caching (#2774)
+  * Use identicon image for default gravatar. (#2767)
+  * Add default ssh ciphers (#2761)
+  * Remove manual of unsupported option (#2757)
+  * Add search mode option to /api/repo/search (#2756)
+  * Move swagger-ui under /api/v1 (#2746)
+  * Add support for extra sendmail arguments (#2731)
+  * Use buffersize to reduce database connection when iterate (#2724)
+  * Render plain text README.txt monospaced (#2721)
+  * Integration test for activity page (#2704)
+  * Merge password and 2fa page on user settings (#2695)
+  * Allow custom SSH user in UI for built-in SSH server (#2617) (#2678)
+  * Refactor duplicated code in repo handlers (#2657)
+  * Replace deprecated Id method with ID (#2655)
+  * Remove redudant functions and code (#2652)
+  * hide navbar when only 1 sign-in method is available (#2444) (#2648)
+  * Change default sort order (#2647)
+  * Change pull description text (#2075) (#2646)
+  * Remove direct user adding to organization members (#2641)
+  * Use session when creating user (#2638)
+  * Use Semantic UI's Search component for user and repo search (#2636)
+  * Use AfterLoad instead of AfterSet on Structs (#2628)
+  * Remove redudant CheckUnit calls in router (#2627)
+  * Remove repo unit index (#2621)
+  * Remove redudant issue LoadAttributes() calls (#2614)
+  * Make indexer code more reusable (#2590)
+  * Use custom type and constants to hold available order by options (#2572)
+  * Use named ActionType constants in template helper (#2545)
+  * Make basic functionality work without JavaScript (#2541)
+  * Ctrl + Enter to submit forms (#2540)
+  * Automatically regenerate indexer for incompatible versions (#2524)
+  * Set default lfs content path to data/lfs (#2521)
+  * Convert spaces to tabs in footer.tmpl (#2520)
+  * Sort repository tree entries in natural way (#2506)
+  * Open external wiki in new window (#2489)
+  * Use created & updated instead BeforeInsert & BeforeUpdate (#2482)
+  * Hide branch on pull request view or create UI (#2454)
+  * improve protected branch to add whitelist support (#2451)
+  * some refactors for issue and comments (#2419)
+  * Restructure markup & markdown to prepare for multiple markup language… (#2411)
+  * Improve issue search (#2387)
+  * Add UseCompatSSHURI setting (#2356)
+  * Use custom search for each filter type in dashboard (#2343)
+  * Failed authentication are now properly logged (#2334)
+  * Add environment variable support for Docker image (#2201)
+  * Set session and indexers' data files rel to AppDataPath (#2192)
+  * Display commit status on landing page of repo (#1784)
+* TESTING
+  * Add integration test for logging out (#2892)
+  * Integration test for user deleting account (#2891)
+  * Use different directories for session files in integration tests (#2834)
+  * Add deleted_branch table fixture (#2832)
+  * Include HTTP method in test error message (#2815)
+  * Add repository search unit and integration tests (#2575)
+  * Expand fixtures (#2571)
+  * Fix /api/repo/search integration tests (#2550)
+  * Make integration tests more user-friendly (#2536)
+  * Fix unit test race condition (#2516)
+  * Add missing fixture to clean gpg_key table (#2494)
+  * Hotfix for integration testing (#2473)
+  * Make repo private to not interfere with other tests (#2467)
+  * Error message for integration test (#2410)
+  * Fix "index out of range" runtime error in repo_list tests (#2376)
+  * Add git clone test on integration test (#1682)
+* TRANSLATION
+  * Fix localization texts that contain semicolon (#2900)
+  * Fix activity locale (#2709)
+  * Update translation from crowdin (#2368)
+* BUILD
+  * change the email and name to GitBot account. (#2848)
+  * Fix removing backslash before quotes in translations (#2831)
+  * add gitea remote in drone. (#2817)
+  * add remote name for git push. (#2816)
+  * Launch Gitea with custom UID/GID for 'git' user (fixes #2286) (#2791)
+  * Download and pushing translations (#2727)
+  * Automatic update of translations (#2585)
+  * Add pre-build step for nodejs stuff (#2581)
+  * Compress css with nodejs (#2580)
+  * Remove go version check for make fmt (#2558)
+  * Fix lint errors (#2547)
+  * Always run fmt check in CI (#2546)
+  * Fix fmt errors (#2544)
+  * add codecov.io service. (#2493)
+  * Fix some tests : make coverage -> test (#2492)
+  * Fix fmt error in mailer (#2490)
+  * Allow changing integration test database connection using env variables (#2484)
+  * Add changelog config file for generate changelog (#2461)
+  * Changes for latest DroneCI (#2362)
+  * Use standard lessc and minify CSS using Node.js (#2337)
+* DOCS
+  * Update screenshots on README (#2910)
+  * Gogs -> Gitea (#2909)
+  * Update swagger documentation (#2899)
+  * Fix typo (#2810)
+  * Fix Polish language name spelling (#2766)
+  * Fix Various Grammar Issues and Adjust Unnatural Wording (#2737)
+  * Add maintainer label for docker file (#2658)
+  * Link to gitea-specific Vagrant example (#2624)
+  * add release notes of v1.1.4 (#2463)
+  * Wrap most paragraphs to 80 columns (#2396)
+  * Update CONTRIBUTING following #2329  discussion (#2394)
+  * Update hard-coded version to 1.3.0+dev (#2390)
+  * Clarify Translation Process. Also fix branch names (#2378)
+  * Admin grammar fixes and improvements (#2056)
+* MISC
+  * Sync MaxGitDiffLineCharacters with conf/app.ini (#2779)
+  * Dockerfile: Updated alpine image to 3.6. (#2486)
+  * Basic VSCode configuration for building and debugging (#2483)
+  * Added vendor dir for js/css libs; Documented sources (#1484) (#2241)
+
+## [1.2.3](https://github.com/go-gitea/gitea/releases/tag/v1.2.3) - 2017-11-03
+
+* BUGFIXES
+  * Only require one email when validating GPG key (#2266, #2467, #2663) (#2788)
+  * Fix order of comments (#2835) (#2839)
+
+## [1.2.2](https://github.com/go-gitea/gitea/releases/tag/v1.2.2) - 2017-10-26
+
+* BUGFIXES
+  * Add checks for commits with missing author and time (#2771) (#2785)
+  * Fix sending mail with a non-latin display name (#2559) (#2783)
+  * Sync MaxGitDiffLineCharacters with conf/app.ini (#2779) (#2780)
+  * Update vendor git (#2765) (#2772)
+  * Fix emojify image URL (#2769) (#2773)
+
+## [1.2.1](https://github.com/go-gitea/gitea/releases/tag/v1.2.1) - 2017-10-16
+
+* BUGFIXES
+  * Fix PR, milestone and label functionality if issue unit is disabled (#2710) (#2714)
+  * Fix plain readme didn't render correctly on repo home page (#2705) (#2712)
+  * Fix so that user can still fork his own repository to his organizations (#2699) (#2707)
+  * Fix .netrc authentication (#2700) (#2708)
+  * Fix slice out of bounds error in mailer (#2479) (#2696)
+
+## [1.2.0](https://github.com/go-gitea/gitea/releases/tag/v1.2.0) - 2017-10-10
+
+* SECURITY
+  * Sanitation fix from Gogs (#1461)
+* BREAKING
+  * Rename /forget_password url to /forgot_password (#1219)
+* FEATURES
+  * Logo: Add task to generate images from SVG and change to new logo (#2194)
+  * Status-API (#1332)
+  * Show commit status icon in commits table (#1688)
+  * Additional OAuth2 providers (#1010)
+  * GPG commit validation (#1150)
+  * Rework SSH key management UI to add GPG (#1293)
+  * Implement GPG api (#710)
+  * Login via OpenID-2.0 (#618)
+  * Add units to team (#947)
+  * Batch updates for issues (#926)
+  * Add Gitea Webhook (#1755)
+  * API: support '/orgs/:org/repos' (#2047)
+  * Display all organization from user settings (#1739)
+  * LDAP user synchronization (#1478)
+  * Adding #issuecomment to the URL in E-Mail notifications (#1674)
+  * Add download count field and unit testing for attachment. (#1512)
+  * Add repo mirror sync API endpoint (#1508)
+  * Add markup package to prepare for org markup format (#1493)
+  * Support for custom html meta  (#1423)
+  * Per issue/PR watch/unwatch (#1410)
+  * Allow ENABLE_OPENID_SIGNUP to depend on DISABLE_REGISTRATION (#1369)
+  * Repo size in admin panel (#1482)
+  * Show user OpenID URIs in their profile (#1314)
+  * Add change-password admin command (#1304)
+  * Only use issue and wiki on repo. (#1297)
+  * Allow push to init a wiki repo (#1279)
+* ENHANCEMENTS
+  * Make time diff translatable (#2057)
+  * Smaller watch, star, and fork buttons (#2052)
+  * Display config file path on admin panel (#2030)
+  * Only show SSH clone URL if signed in (#2169) (#2170)
+  * Only show "No Description" to repo admins (#2167)
+  * Always return valid go-get meta, even if unauthorized (#2010)
+  * Enable assignee e-mail notification (#2003)
+  * Let not-logged-in users view releases (#1999)
+  * No highlighting for .txt files (#1922)
+  * Make side nav on dashboard stackable (#1778)
+  * Setting to disable authorized_keys backup (#1856)
+  * Hide the create organization button (in dashboard/organization section) (#1705)
+  * LFS: Return 404 for unimplemented endpoints (#1330)
+  * Show a link to password reset from user settings requiring a password (#862)
+  * Reserve the "explore" user/org name (#1222)
+  * Send notifications to participants in issue comments (#1217)
+  * Improve style of user OpenID setting page (#1324)
+  * Use font-awesome OpenID icon more (#1320)
+  * Use readonly input form to show the validated OpenID URI (#1308)
+  * Add captcha support to OpenID based signup (#1307)
+  * Minor improvements on commit graph UI (#1380)
+  * Mirror sync interval specified as duration string (#1407)
+  * Make issue in commit graph "clickable" (#1392)
+  * Use whole button (commit graph) as link (#1390)
+  * Autofocus on 2fa passcode fields (#1460)
+  * Sort on repo size in admin panel (#1654)
+  * Improve dashboard repo search (#1652)
+  * Use a better default MAX_GIT_DIFF_LINE_CHARACTERS (#1845)
+  * Adds Parent property to the repo API (#1687)
+  * Add configuration option for default permission to create Organizations (#1686)
+  * Remove sha1 hash display in repository table (#1678)
+  * Download files to their original filename (#1676)
+  * Exposes in API the Repo entity's Size and IsBare property (#1668)
+  * Change two factor code entry box from text to number (#1733)
+  * Directly show error if user hit repository limit  (#1767)
+  * Generate small and large logos at 4x resolution (#2233)
+  * Tags listed in releases tab (#2389) (#2424)
+* BUGFIXES
+  * Fix adding branch as protected to not allow pushing to it (#2556)
+  * Orgs: fix org page title when full name is not defined (#1495)
+  * Fix double borders on edit page (#1152) (#1153)
+  * Search bar fixes for #1187 and #1205 (#1207)
+  * Fix upgrade failed after ever rollback (#1194)
+  * Fix FCGI (over TCP) support (#1368)
+  * Backport of migration fixes (#2604) (#2677)
+  * fix panic on gogs webhook creation (#2675) (#2676)
+  * Backport: Fixes 500 error on dashboard when using MSSQL (#2504) (#2662)
+  * Fix go get response if only app URL is custom in configuration (#2634) (#2640)
+  * Fix deletion of unprotected branches (#2630)
+  * Backport of 2611 / Fix doubled issue tab introduced in migration v16 (#2622)
+  * v38 migration used an outdated version of RepoUnit model (#2602)
+  * fix go get subpackage bug (#2584) (#2589)
+  * Backport: Sync releases table with tags on push and for mirrors (#2459) (#2554)
+  * Backport: Restricting access to fork functioanlity to users with Code access (#2542)
+  * Fix migration from pre-v15 to 1.2.0 (#2460) (#2465)
+  * Fix migration from pre-v15 to 1.2.0 (#2460)
+  * fix duplicated feed (#2370) (#2413)
+  * Fix releases to be counted from database not tags (#2389)
+  * Fix missing collabrative repos (#2367) (#2382)
+  * Add more test for login links and fix a bug on action retrieve (#2361)
+  * Fix SQL condition bug in GetFeeds(..) (#2360)
+  * fix bug on create repo link on dashboard (#2359)
+  * Fix order of elements in dashboard html (#2344)
+  * Fix repo-search template errors for go1.7 (#2336)
+  * Add missing forks key for dashboard repository component (#2325)
+  * fix template error on explore repos (#2319)
+  * Trigger sync webhooks on UI commit (#2302)
+  * fix 500 error when view an issue which's milestone deleted (#2297)
+  * Only update needed columns when update user (#2296)
+  * Fix rendering of external links (#2292)
+  * Fix and improve dashboard repo UI (#2285)
+  * Make short link pattern greedy (#2259)
+  * Temporarily patch go-ini/ini with fork (#2255)
+  * Convert xorm literal queries to method calls (#2253)
+  * update code.gitea.io/git in vendor to fix delete branch fails (#2250)
+  * Replace calls to xorm UseBool with Where (#2237)
+  * rhel7 has a git version with four digits (1.8.3.1) (#2236)
+  * Fix internal requests when gitea listens to unix socket or only external IP (#2234)
+  * Check for access in /repositories/:id (#2227)
+  * Fixed robots.txt 404 error (#2226)
+  * Fix counts on issues dashboard (#2215)
+  * Fix unclosed session bug (#2214)
+  * Add collaborative repositories to the dashboard (#2205)
+  * Fix issue updated_unix bug (#2204)
+  * Fix Commits nil pointer dereference (#2203)
+  * Fix bare-repo bugs (#2199)
+  * Fix PR nil-dereference bug (#2195)
+  * Allow only single fork per user/organization (#2193)
+  * Fix key usage time update if the key is used in parallel for multiple operations (#2185)
+  * Only allow token authentication with 2FA enabled (#2184)
+  * Fix profile update for non-local users (#2178)
+  * Fix compiling without sqlite and gcc (#2177)
+  * Make compare button URL aware if current repo is a fork (#2162) (#2163)
+  * Remove unit types commits and settings (#2161)
+  * Fix OpenID registration route (#2160)
+  * Fix repository settings collobration list display (#2151)
+  * Ignore invalid issue numbers in commit messages. Fixes  #2022 (#2150)
+  * Fix SHA1 hash linking (#2143)
+  * Fix repo API bug (#2133)
+  * Use POSIX complaint ! operator in find (#2132)
+  * Fix GET /users/:username/repos endpoint (#2125)
+  * Fix username rendering bug (#2122)
+  * Fix wiki preview links (#2119)
+  * vendor: update sqlite to fix "database is locked" errors (#2116)
+  * Fix unchecked error bug (#2110)
+  * Fix missing-return bug (#2109)
+  * Fix API for branches with slashes (#2096)
+  * Fix git hooks update to receive required arguments (#2095)
+  * upgrade git source code. (#2094)
+  * Fix SQL bug in models.PullRequests (#2092)
+  * Don't ignore gravatar error (#2083)
+  * Fix release display and correct paging (#2080)
+  * remove unnecessary blank lines and wrong error log (#2079)
+  * Check for valid renamed usernames (#2077)
+  * Update git module (#2074)
+  * Fix org hooks UI (#2072)
+  * Fix #1271: Call location.reload after XHR finishes (#2071)
+  * Fix default ghost assignee bug (#2069)
+  * Fix bug in issue labels API (#2048)
+  * Load label ID in NewLabels (#2045)
+  * Fix: `http: multiple response.WriteHeader calls` (#2038)
+  * Pagination on releases page (#2035)
+  * repo/editor: fix breadcrumb path cuts parent dirs (#3859) (#2032)
+  * Fix displaying commits and files of PR created from now deleted fork (#2023)
+  * Fix #2001 and fix issue comments hidden (#2016)
+  * Update code.gitea.io/git (#2014)
+  * Keep sort when switching page (#2013)
+  * Important: wrong PR merge commit ID saved (#2007)
+  * Don't show non-comments in comments API (#2001)
+  * Fix "Dashboard shows deleted comments" (#1995)
+  * Make branch deletion URL more like GitHub's, fixes #1397 (#1994)
+  * Fix fast-forward PR bug (#1989)
+  * Fix GPG email checking to be case insensitive (#1988)
+  * fix bug for normal user visit public repo (#1984)
+  * fix collborators lack of units on orgnization repositories (#1968)
+  * Fix diff of renamed and modified file (#1967)
+  * Fix uppercase default branch bug (#1965)
+  * Fix bug in Action.loadRepo() (#1959)
+  * Fix deleted milestone bug (#1942)
+  * Fix engine bug in getIssueByID (#1934)
+  * Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
+  * Fix setting.AppPath for integration tests (#1923)
+  * Fix search by issue type (#1914)
+  * Fix ghost user bug (#1913)
+  * Require token before checking membership/ownership (#1905)
+  * Bug fixes for org member API (#1904)
+  * A missing / to provide a correct endpoint (#1903)
+  * Fix 500 in public activity page (#1901)
+  * Center-aligned login topbar (#1880)
+  * Migration to fix existing owner team units (#1873)
+  * Fix paginater length (#1866)
+  * Fix bug in removeOrgRepo (#1858)
+  * Display draft releases (#1854)
+  * Fix 404 for external tracking issues (#1852)
+  * Update code.gitea.io/git (#1849)
+  * Fix user profile activity feed (#1848)
+  * Don't ignore error in getMergeCommit (#1843)
+  * Fix locking bug in removeOrgRepo (#1842)
+  * Fix status table race condition (#1835)
+  * Fix PR template error (#1834)
+  * Fix pull request compare link (#1832)
+  * Use ghost users in issues/PRs (#1831)
+  * Commitless repos should be bare (#1829)
+  * Update code.gitea.io/git (#1824)
+  * Fix invalid reference in feeds template (#1820)
+  * fix bug to deny to add orgnization as a member of an orgnization or team (#1815)
+  * xxx_active_code_live setting in printed in hours and minutes instead … (#1814)
+  * Fix deadlock in updateRepository (#1813)
+  * Give all units to owner team (#1812)
+  * Fix 500 for GET /teams/:id endpoints (#1811)
+  * fix bug not to trim space of login username (#1796)
+  * Fix renaming bug (#1786)
+  * Fix activity feed (#1779)
+  * Make navbar scroll on overflow (#1777)
+  * Delete repo redirects on repo deletion (#1776)
+  * Fix unloaded owner bug (#1770)
+  * Admin should always be allowed to create repositories even if hit limit (#1765)
+  * Update HighlightJS and fix YAML files highlighting (#1764)
+  * fix: #1757 fix set MAX_CREATION_LIMIT as zero. (#1762)
+  * fix admin lost permission caused by #947 (#1753)
+  * More fixes for dashboard search (#1750)
+  * fixes wrong after field in webhook payload (#1746)
+  * fix avatar update bug (#1729)
+  * Fix FOUC on Firefox (#1728)
+  * Fix changes introduce by update of go-swagger. (#1727)
+  * Fix #1719 (#1722)
+  * Correct flash after sending password reset email (#1718)
+  * Fix and test for delete user (#1713)
+  * Fix rendering of issue checkboxes (#1709)
+  * Enforce netgo build tag while cross-compilation (#1690)
+  * fix bug when push a branch name with / & fix an integration test bug (#1689)
+  * fix potential sqlite lock (#1680)
+  * Fix commit sha1 URL rendering in markdown (#1677)
+  * Fix static files permission under public/ (#1675)
+  * fix: tag contain character ) will http 500 on release page (#1670)
+  * Fix CSS for code in wiki markdown (#1660)
+  * fix multiple readme file rendering and fix #1657 (#1658)
+  * Add primary key and index to external login user table (#1656)
+  * fix #1643 and improve integration test (#1645)
+  * Fix version in Makefile (#1636)
+  * Handle display of GPG key without end date (#1628)
+  * fix bug on issue view when not login (#1624)
+  * bug fixed for API to get user's repos (#1622)
+  * fix lost text color on button on set as primary email (#1621)
+  * Add create_at and updated_at in PR json (#1616)
+  * update git and fix #1133 (#1614)
+  * fix bug on status API (#1533)
+  * Do not show empty collaborators segment (#1531)
+  * Fix markdown rendering (#1530)
+  * fix go get sub package and add domain on installation to let go get work defaultly (#1518)
+  * fix #1501 ssh hangs caused by #1461 (#1513)
+  * Fix empty file download (#1506)
+  * Fix broken v27 migration - change mirror interval from int to bigint (#1504)
+  * Do not allow committing to protected branch from online editor (#1502)
+  * Add internal routes for ssh hook comands (#1471)
+  * Fix races within code.gitea.io/git.(*Command).RunInDirTimeoutPipeline (#1465)
+  * Simple quick fix for #1418 (#1456)
+  * fix gpg API panic when no verification (#1451)
+  * fix migrate failed and org dashboard failed on MSSQL database (#1448)
+  * Optimize and fix autolink function (#1442) (#1444)
+  * Fix and simplify repo branches (settings) UI (#1435)
+  * Fix disabled fields in repo settings UI (#1431)
+  * fixes pull request hanging when it contains normal and LFS files (#1425)
+  * Fix races in the log module by using syncmap (#1421)
+  * Add length check for the return string (#1420)
+  * Fix "Error: No issue number specified"  when pushing (#1393)
+  * Corrected Mirror.NextUpdate not set (#1388)
+  * fix: remove `str2html` from org full name (#1360)
+  * Correct broken unaligned load/store in armv5 (#1355)
+  * Remove href on first/last link when on first/last page (#1345)
+  * Fix broken table layout (#1344)
+  * LFS: Fix SSH authentication for trailing arguments (#1328)
+  * Remove empty file (#1326)
+  * Fix delete user failed on sqlite (#1321)
+  * Fix inconsistency in layout (#1316)
+  * Fix gpg wrong column types (#1303)
+  * Fix wiki bugs (#1294)
+  * Fix missing less sources for oauth (#1288)
+  * Make sure both scripts/ can live side by side (#1264)
+  * Fix nil-dereference bug (#1258)
+  * rewrite pre-commit, post-commit and options hooks (fixes #1250) (#1257)
+  * Commit search appearance fixes (#1254)
+  * Fix forget migration for wiki hooks (#1227)
+  * Fix repo settings external tracker failed and check external urls (#1215)
+  * Fix 500 caused by branches settings introduced by #1198 (#1214)
+  * fix #1189, commit messages containing a pipe (#1203)
+  * Bug fixed for delete repo failed (#1193)
+  * Fix migration failed when authorized_keys is not exist (#1180)
+  * Fix ini format incomiptable with crowdin (#1177)
+* TESTING
+  * Integration tests for issues API (#2059)
+  * Add integration tests for signin (#2363)
+  * Add INTERNAL_TOKEN to integration .ini file (#2346)
+  * Add public links check (#2323)
+  * Fix hooks for integration repo (#2216)
+  * More integration tests for comment API (#2156)
+  * Cache session cookies in tests (#2128)
+  * Less verbose integration tests (#2123)
+  * Fix improper setup for integration tests (#2050)
+  * Improve integration test helper functions (#2049)
+  * Add integration test for issue creating (#2002)
+  * Use testing/benchmark interface (#1993)
+  * Add integration test for repository migration (#1983)
+  * Consolidate boilerplate in integration tests (#1979)
+  * Set console to debug for integration tests (#1976)
+  * Add pull-create integration test (#1972)
+  * Coverage reports for integration tests (#1960)
+  * Add integration test for pull-request merge (#1912)
+  * Add integration test for file editing (#1907)
+  * Add integration test for repository forking (#1896)
+  * Run unused test (#1875)
+  * Don't recreate database in integration tests (#1697)
+  * remove sqlite tag when integration test with mysql/postgres and recreate database when init integration test (#1693)
+  * MySQL, Postgres integration tests in drone (#1638)
+  * improve integration test to resue models/fixtures and store git repos with tests (#1627)
+  * Improve govendor testing (#1623)
+  * Integration test framework (#1290)
+  * Unit tests for issue_list (#1209)
+  * Add integration test for signup (#1135)
+* TRANSLATION
+  * update translation from crowdin (#2368) (#2380)
+  * Small fixes (#2144)
+  * Missing signed commit display translations (#2134)
+  * Sync latest translations from crowdin (#2104)
+  * Add make command update-translations for update translations from crodwin (#2097)
+  * Fix some mistakes (#1833)
+  * Improve clarity between is_activated and prohibit_login (#1788)
+  * Improve grammar (#1775)
+  * Fix bad grammar and wordiness (#1741)
+  * Make strings translatable (#1188) (#1198)
+* BUILD
+  * Dockerfile for aarch64 (#1128) (#1130)
+  * backport from v1.2 branch: add secrets for github release (#2588) (#2598)
+  * Add secrets for github release to fix drone failed (#2588)
+  * Backport changes for latest drone (#2586)
+  * Removing .drone.yml.sig (#2579)
+  * Fix drone for tags (#2573) (#2576)
+  * Backport: Remove go version check for make fmt (#2558) (#2561)
+  * Backport: Fix lint, fmt and integration testing errors (#2553)
+  * update latest xorm version to vendor (#2353)
+  * Remove integration test executables on `make clean` (#2340)
+  * refactor(Makefile): allow overriding default go program (#2310)
+  * Revert to upstream ini dependency (#2304)
+  * Use /dev/urandom to create random password (#2298)
+  * update drone sig file. (#2262)
+  * go get github.com/wadey/gocovmerge when needed (#2235)
+  * fix typo (#2145)
+  * Revert "Reduce number of layer" (#2086)
+  * Reduce number of layer (#2078)
+  * Skip sqlite integration in CI (#2058)
+  * fix golint error and rename func for suggestion. (#1997)
+  * fix misspell (#1996)
+  * update drone sig file (#1981)
+  * send notification if status changed (#1973)
+  * switch gitter to discord for drone. (#1971)
+  * Fix missing backslash in Dockerfile.rpi (#1952)
+  * Don't run 'make release' on PRs (#1908)
+  * Update code.gitea.io/git (#1892)
+  * Use production version of vuejs (#1869)
+  * Add a variable for docker tag (#1825)
+  * resign drone and fix #1816 (#1819)
+  * Separate generate swagger + fix sed os specific (#1791)
+  * Only run coverage on merges/pushes to master (#1783)
+  * Remove stale rule from Makefile (#1782)
+  * feat: upgrade drone docker image to support multi-stage build. (#1732)
+  * Really don't cache apk index (#1694)
+  * Limit clone depth when drone-building (#1644)
+  * Refactor Dockerfile (#1632)
+  * Check if missing/modified/unused deps in vendor and fix errors (#1468)
+  * Add GOFLAGS and EXTRA_GOFLAGS (#1438)
+  * Include formatting check to the `make test` (and thus also `check`) rule (#1366)
+* DOCS
+  * fix wrong changelog title (#2395)
+  * fix webhook link (#2289)
+  * Improve swagger doc (#2274)
+  * Add link to forum in issue template (#2070)
+  * add missing lfs config on example file (#2039)
+  * Add discourse link (#2027)
+  * Fix wording (#2024)
+  * Fix typo (#1974)
+  * Swagger docs for list/create forks (#1941)
+  * Update links to Discord server (#1940)
+  * [ci skip] update discord badge. (#1930)
+  * Change join chat from gitter to discord (#1929)
+  * Update changelog with v1.1.1 (#1926)
+  * Correct grammar in APIEmpty documentation (#1748)
+  * Add swagger comment for MirrorSync (#1747)
+  * Add "Table of Contents" in CONTRIBUTING.md (#1634)
+  * Fix service description in Debian init file (#1538)
+  * Use MAINTAINERS file in repository in CONTRIBUTING (#1489)
+  * Generate swagger json (#1402)
+  * Changed text when password reset disabled. (#1364)
+  * Removed email copyright year (#1348)
+  * Specify that time interval units are seconds (#1311)
+  * Gitea OpenID-2.0 login has been tested with livejournal.com too (#1306)
+  * Make wording of commit search more clear (#1291)
+  * Add notice that LFS mirroring is not supported (#1251)
+  * Fix typos in models/ and modules/ (#1248)
+  * Refactor and fix incorrect comment (#1247)
+  * Fix migration comment (#1241)
+  * Update locale_en-US.ini (#1235)
+  * Add LibreJS support (#1201)
+  * rename OSX to macOS (#1176)
+  * add mssql to app.ini db config comment (#1172)
+  * Add MSSQL to issues template (#1171)
+* MISC
+  * Add badge and link to the Matrix room (#2348)
+  * ignore coverage steps. (#2257)
+  * Use sqlite3 database as default for Docker image (#2182)
+  * update drone discord plugin to 0.0.4 version (#1992)
+  * fix typo (#1990)
+  * Move 3rd party js/css into `public/vendor` and document sources (#2383)
+  * Prevent conflicting TOTP accounts by adding AppURL to issuer parameter (#2335)
+  * Fix variable name typo (#2327)
+  * Make use of Vue more universal (#2318)
+  * Remove (almost) server side data rendering from repo-search component (#2317)
+  * Add OpenID configuration in install page (#2276)
+  * More tweaks to repo top panel (#2267)
+  * File path tweaks in UI (#2264)
+  * Make SHOW_USER_EMAIL also apply to profiles (#2258)
+  * EnableUnit() -> UnitEnabled() (#2242)
+  * Prevent selection of diff line numbers (#2240)
+  * Remove unused variable on makefile (#2225)
+  * No error log entries for repo 404 (#2200)
+  * Refactor vue delimeters to use es6 template delimeters (#2171)
+  * Replace tmp with TMPDIR. (#2152)
+  * Remove unused files (#2124)
+  * Improve org error handling (#2117)
+  * Absolute path for setting.CustomConf (#2085)
+  * remove deprecated code for Gogs compatible (#2041)
+  * Refactor session close as xorm already does everything needed internally  (#2020)
+  * SQLite has a query timeout. Hopefully fixes most 'database locked' errors (#1961)
+  * Use monospace font in githook editor (#1958)
+  * Fix import order (#1951)
+  * Gracefully handle bare repositories on API operations. (#1932)
+  * Fix errors caused by force push (#1927)
+  * Display URLs in integration test logs (#1924)
+  * Set TMPDIR environment variable for dump command (#1915)
+  * Cache ctx.User in retrieveFeeds (#1902)
+  * Make `LocalCopyPath` a setting instead of a hard-coded path (#1881)
+  * Add check misspelling (#1877)
+  * Fix misspelled variables (#1874)
+  * Gofmt (#1868, #1710, #1662)
+  * Rename misnamed migration (#1867)
+  * Support CRLF when splitting code lines for display (#1862)
+  * Add convert less css file step. (#1861)
+  * Prevent accidental selection of line numbers in code view (#1860)
+  * Delete Public SSH Key tmp file after calculating fingerprint (#1855)
+  * Remove annoying difference in button heights. (#1853)
+  * Only run test coverage on master branch. (#1838)
+  * Error from mktemp command in MacOS. (#1837)
+  * Use writeTmpKeyFile in calcFingerprint (#1828)
+  * ROOT_URL setting use the default as shown in conf/app.ini (#1823)
+  * Rename RepoCreationNum -> MaxCreationLimit (#1766)
+  * Add button to admin ui (#1738)
+  * Correct spelling mistakes (#1703)
+  * Make openid support default false for compatible with v1.1 (#1650)
+  * Send mails as HTML as default. Setting for send as plain text. (#1648)
+  * fix potential lock when sqlite (#1647)
+  * Optimize png images via Google zopflipng [ci skip] (#1639)
+  * Upgrade alpine to v3.5 in Dockerfile (#1633)
+  * remove unused vendor packages (#1620)
+  * markup: microoptimise for many short filenames in directory (#1534)
+  * support health check via / and fix #969 (#1520)
+  * Remove env user salt since no need to use (#1515)
+  * Drop db operations from hook commands (#1514)
+  * Better URL validation (#1507)
+  * Migrate WatchInfo struct to api (#1492)
+  * refactor: show command help message. (#1486)
+  * refactor update ssh key use time (#1466)
+  * Set VERSION from git once, in a variable (#1447)
+  * Remove unused mutex field (#1440)
+  * Simplify settings pages with item list (#1389)
+  * Clean-up PostgreSQL Tests (#1361)
+  * refactor: remove workaround after the golang 1.7 release. (#1349)
+  * Delete the useless code (#1335)
+  * Run "make fmt" with go-1.6 (#1333)
+  * Refactor admin/auth/new.tmpl (#1277)
+  * Refactor repo/issue/view_content.tmpl (#1276)
+  * Cleaner ui for admin, repo settings, and user settings page (#1269) (#1270)
+  * Cleaner UI for explore page (#1253) (#1255)
+  * Synced licenses with github repo (#1246)
+  * Synced gitignores with github repo (#1245)
+  * Simplify RepositoryList.loadAttributes() (#1211)
+  * Move user_follow to separate file (#1210)
+  * Reduce conditionals in signin/signup inner forms (#1138)
+
+## [1.1.4](https://github.com/go-gitea/gitea/releases/tag/v1.1.4) - 2017-09-04
+
+* BUGFIXES
+  * Fix rendering of external links (#2292) (#2315)
+  * Fix deleted milestone bug (#1942) (#2300)
+  * fix 500 error when view an issue which's milestone deleted (#2297) (#2299)
+  * Fix SHA1 hash linking (#2143) (#2293)
+  * back port from #1709 (#2291)
+
+## [1.1.3](https://github.com/go-gitea/gitea/releases/tag/v1.1.3) - 2017-08-03
+
+* BUGFIXES
+  * Fix PR template error (#2008)
+  * Fix markdown rendering (fix #1530) (#2043)
+  * Fix missing less sources for oauth (backport #1288) (#2135)
+  * Don't ignore gravatar error (#2138)
+  * Fix diff of renamed and modified file (#2136)
+  * Fix fast-forward PR bug (#2137)
+  * Fix some security bugs
+
+## [1.1.2](https://github.com/go-gitea/gitea/releases/tag/v1.1.2) - 2017-06-13
+
+* BUGFIXES
+  * Enforce netgo build tag while cross-compilation (Backport of #1690) (#1731)
+  * fix update avatar
+  * fix delete user failed on sqlite (#1321)
+  * fix bug not to trim space of login username (#1806)
+  * Backport bugfixes #1220 and #1393 to v1.1 (#1758)
+
+## [1.1.1](https://github.com/go-gitea/gitea/releases/tag/v1.1.1) - 2017-05-04
+
+* BUGFIXES
+  * Markdown Sanitation Fix [#1646](https://github.com/go-gitea/gitea/pull/1646)
+  * Fix broken hooks [#1376](https://github.com/go-gitea/gitea/pull/1376)
+  * Fix migration issue [#1375](https://github.com/go-gitea/gitea/pull/1375)
+  * Fix Wiki Issues [#1338](https://github.com/go-gitea/gitea/pull/1338)
+  * Forgotten migration for wiki githooks [#1237](https://github.com/go-gitea/gitea/pull/1237)
+  * Commit messages can contain pipes [#1218](https://github.com/go-gitea/gitea/pull/1218)
+  * Verify external tracker URLs [#1236](https://github.com/go-gitea/gitea/pull/1236)
+  * Allow upgrade after downgrade [#1197](https://github.com/go-gitea/gitea/pull/1197)
+  * 500 on delete repo with issue [#1195](https://github.com/go-gitea/gitea/pull/1195)
+  * INI compat with CrowdIn [#1192](https://github.com/go-gitea/gitea/pull/1192)
+
+## [1.1.0](https://github.com/go-gitea/gitea/releases/tag/v1.1.0) - 2017-03-09
+
+* BREAKING
+  * The SSH keys can potentially break, make sure to regenerate the authorized keys
+* FEATURES
+  * Git LFSv2 support [#122](https://github.com/go-gitea/gitea/pull/122)
+  * API endpoints for repo watching [#191](https://github.com/go-gitea/gitea/pull/191)
+  * Search within private repos [#222](https://github.com/go-gitea/gitea/pull/222)
+  * Hide user email address on explore page [#336](https://github.com/go-gitea/gitea/pull/336)
+  * Protected branch system [#339](https://github.com/go-gitea/gitea/pull/339)
+  * Sendmail for mail delivery [#355](https://github.com/go-gitea/gitea/pull/355)
+  * API endpoints for org webhooks [#372](https://github.com/go-gitea/gitea/pull/372)
+  * Enabled MSSQL support [#383](https://github.com/go-gitea/gitea/pull/383)
+  * API endpoints for org teams [#370](https://github.com/go-gitea/gitea/pull/370)
+  * API endpoints for collaborators [#375](https://github.com/go-gitea/gitea/pull/375)
+  * Graceful server restart [#416](https://github.com/go-gitea/gitea/pull/416)
+  * Commitgraph / timeline on commits page [#428](https://github.com/go-gitea/gitea/pull/428)
+  * API endpoints for repo forks [#509](https://github.com/go-gitea/gitea/pull/509)
+  * API endpoints for releases [#510](https://github.com/go-gitea/gitea/pull/510)
+  * Folder jumping [#511](https://github.com/go-gitea/gitea/pull/511)
+  * Stars tab on profile page [#519](https://github.com/go-gitea/gitea/pull/519)
+  * Notification system [#523](https://github.com/go-gitea/gitea/pull/523)
+  * Push and pull through reverse proxy basic auth [#524](https://github.com/go-gitea/gitea/pull/524)
+  * Search for issues and pull requests [#530](https://github.com/go-gitea/gitea/pull/530)
+  * API endpoint for stargazers [#597](https://github.com/go-gitea/gitea/pull/597)
+  * API endpoints for subscribers [#598](https://github.com/go-gitea/gitea/pull/598)
+  * PID file support [#610](https://github.com/go-gitea/gitea/pull/610)
+  * Two factor authentication (2FA) [#630](https://github.com/go-gitea/gitea/pull/630)
+  * API endpoints for org users [#645](https://github.com/go-gitea/gitea/pull/645)
+  * Release attachments [#673](https://github.com/go-gitea/gitea/pull/673)
+  * OAuth2 consumer [#679](https://github.com/go-gitea/gitea/pull/679)
+  * Add ability to fork your own repos [#761](https://github.com/go-gitea/gitea/pull/761)
+  * Search repository on dashboard [#773](https://github.com/go-gitea/gitea/pull/773)
+  * Search bar on user profile [#787](https://github.com/go-gitea/gitea/pull/787)
+  * Track label changes on issue view [#788](https://github.com/go-gitea/gitea/pull/788)
+  * Allow using custom time format [#798](https://github.com/go-gitea/gitea/pull/798)
+  * Redirects for renamed repos [#807](https://github.com/go-gitea/gitea/pull/807)
+  * Track assignee changes on issue view [#808](https://github.com/go-gitea/gitea/pull/808)
+  * Track title changes on issue view [#841](https://github.com/go-gitea/gitea/pull/841)
+  * Archive cleanup action [#885](https://github.com/go-gitea/gitea/pull/885)
+  * Basic Open Graph support [#901](https://github.com/go-gitea/gitea/pull/901)
+  * Take back control of Git hooks [#1006](https://github.com/go-gitea/gitea/pull/1006)
+  * API endpoints for user repos [#1059](https://github.com/go-gitea/gitea/pull/1059)
+* BUGFIXES
+  * Fixed counting issues for issue filters [#413](https://github.com/go-gitea/gitea/pull/413)
+  * Added back default settings for SSH [#500](https://github.com/go-gitea/gitea/pull/500)
+  * Fixed repo permissions [#513](https://github.com/go-gitea/gitea/pull/513)
+  * Issues cannot be created with labels [#622](https://github.com/go-gitea/gitea/pull/622)
+  * Add a reserved wiki paths check to the wiki [#720](https://github.com/go-gitea/gitea/pull/720)
+  * Update website binding MaxSize to 255 [#722](https://github.com/go-gitea/gitea/pull/722)
+  * User can see the private activity on public history [#818](https://github.com/go-gitea/gitea/pull/818)
+  * Wrong pages number which includes private repositories [#844](https://github.com/go-gitea/gitea/pull/844)
+  * Trim whitespaces for search keyword [#893](https://github.com/go-gitea/gitea/pull/893)
+  * Don't rewrite non-gitea public keys [#906](https://github.com/go-gitea/gitea/pull/906)
+  * Use fingerprint to check instead content for public key [#911](https://github.com/go-gitea/gitea/pull/911)
+  * Fix random avatars [#1147](https://github.com/go-gitea/gitea/pull/1147)
+* ENHANCEMENTS
+  * Refactored process manager [#75](https://github.com/go-gitea/gitea/pull/75)
+  * Restrict rights to create new orgs [#193](https://github.com/go-gitea/gitea/pull/193)
+  * Added label and milestone sorting [#199](https://github.com/go-gitea/gitea/pull/199)
+  * Make minimum password length configurable [#223](https://github.com/go-gitea/gitea/pull/223)
+  * Speedup conflict checking on pull requests [#276](https://github.com/go-gitea/gitea/pull/276)
+  * Added button to delete merged pull request branches [#441](https://github.com/go-gitea/gitea/pull/441)
+  * Improved issue references within markdown [#471](https://github.com/go-gitea/gitea/pull/471)
+  * Dutch translation for the landingpage [#487](https://github.com/go-gitea/gitea/pull/487)
+  * Added Gogs migration script [#532](https://github.com/go-gitea/gitea/pull/532)
+  * Support a .gitea folder for issue templates [#582](https://github.com/go-gitea/gitea/pull/582)
+  * Enhanced diff-view coloring [#584](https://github.com/go-gitea/gitea/pull/584)
+  * Added ETag header to avatars [#721](https://github.com/go-gitea/gitea/pull/721)
+  * Added option to config to disable local path imports [#724](https://github.com/go-gitea/gitea/pull/724)
+  * Allow custom public files [#782](https://github.com/go-gitea/gitea/pull/782)
+  * Added pprof endpoint for debugging [#801](https://github.com/go-gitea/gitea/pull/801)
+  * Added `X-GitHub-*` headers [#809](https://github.com/go-gitea/gitea/pull/809)
+  * Fill SSH key title automatically [#863](https://github.com/go-gitea/gitea/pull/863)
+  * Display Git version on admin panel [#921](https://github.com/go-gitea/gitea/pull/921)
+  * Expose URL field on issue API [#982](https://github.com/go-gitea/gitea/pull/982)
+  * Statically compile the binaries [#985](https://github.com/go-gitea/gitea/pull/985)
+  * Embed build tags into version string [#1051](https://github.com/go-gitea/gitea/pull/1051)
+  * Gitignore support for FSharp and Clojure [#1072](https://github.com/go-gitea/gitea/pull/1072)
+  * Custom templates for static builds [#1087](https://github.com/go-gitea/gitea/pull/1087)
+  * Add ProxyFromEnvironment if none set [#1096](https://github.com/go-gitea/gitea/pull/1096)
+* MISC
+  * Replaced remaining Gogs references
+  * Added more tests on various packages
+  * Use Crowdin for translations again
+  * Resolved some XSS attack vectors
+  * Optimized and reduced number of database queries
+
+## [1.0.2](https://github.com/go-gitea/gitea/releases/tag/v1.0.2) - 2017-02-21
+
+* BUGFIXES
+  * Fixed issue counter [#882](https://github.com/go-gitea/gitea/pull/882)
+  * Fixed XSS vulnerability on wiki page [#955](https://github.com/go-gitea/gitea/pull/955)
+  * Add data dir without session to dump [#587](https://github.com/go-gitea/gitea/pull/587)
+  * Fixed wiki page renaming [#958](https://github.com/go-gitea/gitea/pull/958)
+  * Drop default console logger if not required [#960](https://github.com/go-gitea/gitea/pull/960)
+  * Fixed docker docs link on install page [#972](https://github.com/go-gitea/gitea/pull/972)
+  * Handle SetModel errors [#957](https://github.com/go-gitea/gitea/pull/957)
+  * Fixed XSS vulnerability on milestones [#977](https://github.com/go-gitea/gitea/pull/977)
+  * Fixed XSS vulnerability on alerts [#981](https://github.com/go-gitea/gitea/pull/981)
+
+## [1.0.1](https://github.com/go-gitea/gitea/releases/tag/v1.0.1) - 2017-01-05
+
+* BUGFIXES
+  * Fixed localized `MIN_PASSWORD_LENGTH` [#501](https://github.com/go-gitea/gitea/pull/501)
+  * Fixed 500 error on organization delete [#507](https://github.com/go-gitea/gitea/pull/507)
+  * Ignore empty wiki repo on migrate [#544](https://github.com/go-gitea/gitea/pull/544)
+  * Proper check access for forking [#563](https://github.com/go-gitea/gitea/pull/563)
+  * Fix SSH domain on installer [#506](https://github.com/go-gitea/gitea/pull/506)
+  * Fix missing data rows on admin UI [#580](https://github.com/go-gitea/gitea/pull/580)
+  * Do not delete tags with releases by default [#579](https://github.com/go-gitea/gitea/pull/579)
+  * Fix missing session config data on admin UI [#578](https://github.com/go-gitea/gitea/pull/578)
+  * Properly show the version within footer on the UI [#593](https://github.com/go-gitea/gitea/pull/593)
+
+## [1.0.0](https://github.com/go-gitea/gitea/releases/tag/v1.0.0) - 2016-12-23
+
+* BREAKING
+  * We have various changes on the API, scripting against API must be updated
+* FEATURES
+  * Show last login for admins [#121](https://github.com/go-gitea/gitea/pull/121)
+* BUGFIXES
+  * Fixed sender of notifications [#2](https://github.com/go-gitea/gitea/pull/2)
+  * Fixed keyword hijacking vulnerability [#20](https://github.com/go-gitea/gitea/pull/20)
+  * Fixed non-markdown readme rendering [#95](https://github.com/go-gitea/gitea/pull/95)
+  * Allow updating draft releases [#169](https://github.com/go-gitea/gitea/pull/169)
+  * GitHub API compliance [#227](https://github.com/go-gitea/gitea/pull/227)
+  * Added commit SHA to tag webhook [#286](https://github.com/go-gitea/gitea/issues/286)
+  * Secured links via noopener [#315](https://github.com/go-gitea/gitea/issues/315)
+  * Replace tabs with spaces on wiki title [#371](https://github.com/go-gitea/gitea/pull/371)
+  * Fixed vulnerability on labels and releases [#409](https://github.com/go-gitea/gitea/pull/409)
+  * Fixed issue comment API [#449](https://github.com/go-gitea/gitea/pull/449)
+* ENHANCEMENTS
+  * Use proper import path for libravatar [#3](https://github.com/go-gitea/gitea/pull/3)
+  * Integrated DroneCI for tests and builds [#24](https://github.com/go-gitea/gitea/issues/24)
+  * Integrated dependency manager [#29](https://github.com/go-gitea/gitea/issues/29)
+  * Embedded bindata optionally [#30](https://github.com/go-gitea/gitea/issues/30)
+  * Integrated pagination for releases [#73](https://github.com/go-gitea/gitea/pull/73)
+  * Autogenerate version on every build [#91](https://github.com/go-gitea/gitea/issues/91)
+  * Refactored Docker container [#104](https://github.com/go-gitea/gitea/issues/104)
+  * Added short-hash support for downloads [#211](https://github.com/go-gitea/gitea/issues/211)
+  * Display tooltip for downloads [#221](https://github.com/go-gitea/gitea/issues/221)
+  * Improved HTTP headers for issue attachments [#270](https://github.com/go-gitea/gitea/pull/270)
+  * Integrate public as bindata optionally [#293](https://github.com/go-gitea/gitea/pull/293)
+  * Integrate templates as bindata optionally [#314](https://github.com/go-gitea/gitea/pull/314)
+  * Inject more ENV variables into custom hooks [#316](https://github.com/go-gitea/gitea/issues/316)
+  * Correct LDAP login validation [#342](https://github.com/go-gitea/gitea/pull/342)
+  * Integrate conf as bindata optionally [#354](https://github.com/go-gitea/gitea/pull/354)
+  * Serve video files in browser [#418](https://github.com/go-gitea/gitea/pull/418)
+  * Configurable SSH host binding [#431](https://github.com/go-gitea/gitea/issues/431)
+* MISC
+  * Forked from Gogs and renamed to Gitea
+  * Catching more errors with logs
+  * Fixed all linting errors
+  * Made the go linter entirely happy
+  * Really integrated vendoring
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e119d0bec0..04fffd4a4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,148 @@
 # Changelog
 
-This changelog goes through all the changes that have been made in each release
+This changelog goes through the changes that have been made in each release
 without substantial changes to our git log; to see the highlights of what has
 been added to each release, please refer to the [blog](https://blog.gitea.com).
 
+## [1.21.11](https://github.com/go-gitea/gitea/releases/tag/v1.21.11) - 2024-04-07
+
+* SECURITY
+  * Use go1.21.9 to include Golang security fix
+  * Fix possible renderer security problem (#30136) (#30315)
+  * Performance optimization for git push and check permissions for push options (#30104) (#30354)
+* BUGFIXES
+  * Fix close file in the Upload func (#30262) (#30269)
+  * Fix inline math blocks can't be preceeded/followed by alphanumerical characters (#30175) (#30250)
+  * Fix missing 0 prefix of GPG key id (#30245) (#30247)
+  * Include encoding in signature payload (#30174) (#30181)
+  * Move from `max( id )` to `max( index )` for latest commit statuses (#30076) (#30155)
+  * Load attachments for code comments (#30124) (#30126)
+  * Fix gitea doctor will remove repo-avatar files when executing command storage-archives (#30094) (#30120)
+  * Fix possible data race on tests (#30093) (#30108)
+  * Fix duplicate migrated milestones (#30102) (#30105)
+  * Fix panic for fixBrokenRepoUnits16961 (#30068) (#30100)
+  * Fix incorrect SVGs (#30086) (#30087)
+  * Fix create commit status (#30225) (#30340)
+  * Fix misuse of unsupported global variables (#30402)
+  * Fix to delete the cookie when AppSubURL is non-empty (#30375) (#30468)
+  * Avoid user does not exist error when detecting schedule actions when the commit author is an external user (#30357) (#30408)
+  * Change the default maxPerPage for gitbucket (#30392) (#30471)
+  * Check the token's owner and repository when registering a runner (#30406) (#30412)
+  * Avoid losing token when updating mirror settings (#30429) (#30466)
+  * Fix commit status cache which missed target_url (#30426) (#30445)
+  * Fix rename branch 500 when the target branch is deleted but exist in database (#30430) (#30437)
+  * Fix mirror error when mirror repo is empty (#30432) (#30467)
+  * Use db.ListOptions directly instead of Paginator interface to make it easier to use and fix performance of /pulls and /issues (#29990) (#30447)
+  * Fix code owners will not be mentioned when a pull request comes from a forked repository (#30476) (#30497)
+* DOCS
+  * Update actions variables documents (#30394) (#30405)
+* MISC
+  * Update katex to 0.16.10 (#30089)
+  * Upgrade go-sqlite to v1.14.22 (#30462)
+
+## [1.21.10](https://github.com/go-gitea/gitea/releases/tag/v1.21.10) - 2024-03-25
+
+* BUGFIXES
+  * Fix Add/Remove WIP on pull request title failure (#29999) (#30066)
+  * Fix misuse of `TxContext` (#30061) (#30062)
+  * Respect DEFAULT_ORG_MEMBER_VISIBLE setting when adding creator to org (#30013) (#30035)
+  * Escape paths for find file correctly (#30026) (#30031)
+  * Remove duplicate option in admin screen and now-unused translation keys (#28492) (#30024)
+  * Fix manual merge form and 404 page templates (#30000)
+
+## [1.21.9](https://github.com/go-gitea/gitea/releases/tag/v1.21.9) - 2024-03-21
+
+* PERFORMANCE
+  * Only do counting when count_only=true for repo dashboard (#29884) (#29905)
+  * Add cache for dashboard commit status (#29932)
+* ENHANCEMENT
+  * Make runs-on support variable expression (#29468) (#29782)
+  * Show Actions post step when it's running (#29926) (#29928)
+* BUGFIXES
+  * Fix PR creation via API between branches of the same repo with head field namespaced (#26986) (#29857)
+  * Fix and rewrite markup anchor processing (#29931) (#29946)
+  * Notify reviewers added via CODEOWNERS (#29842) (#29902)
+  * Fix template error when comment review doesn't exist (#29888) (#29889)
+  * Fix user id column case (#29863) (#29867)
+  * Make meilisearch do exact search for issues (#29740 & #29671) (#29846)
+  * Fix the `for` attribute not pointing to the ID of the color picker (#29813) (#29815)
+  * Fix codeowner detected diff base branch to mergebase (#29783) (#29807)
+  * Fix Safari spinner rendering (#29801) (#29802)
+  * Fix missing translation on milestones (#29785) (#29789)
+  * Fix user router possible panic (#29751) (#29786)
+  * Fix possible NPE in ToPullReviewList (#29759) (#29775)
+  * Fix the wrong default value of ENABLE_OPENID_SIGNIN on docs (#29925) (#29927)
+  * Solving the issue of UI disruption when the review is deleted without refreshing (#29951) (#29968)
+  * Fix loadOneBranch panic (#29938) (#29939)
+  * Fix invalid link of the commit status when ref is tagged (#29752) (#29908)
+  * Editor error message misleading due to re-used key. (#29859) (#29876)
+  * Fix double border and border-radius on empty action steps (#29845) (#29850)
+  * Use `Temporal.PlainDate` for absolute dates (#29804) (#29808)
+  * Fix incorrect package link method calls in templates (#29580) (#29764)
+  * Fix the bug that the user may log out if GetUserByID returns unknown error (#29962) (#29964)
+  * Performance improvements for pull request list page (#29900) (#29972)
+  * Fix bugs in rerunning jobs (#29983) (#29955)
+
+## [1.21.8](https://github.com/go-gitea/gitea/releases/tag/v1.21.8) - 2024-03-12
+
+* SECURITY
+  * Only use supported sort orders for "/explore/users" page (#29430) (#29443)
+* ENHANCEMENTS
+  * Fix wrong line number in code search result (#29260) (#29623)
+* BUGFIXES
+  * Use Get but not Post to get actions artifacts (#29734) (#29737)
+  * Fix inconsistent rendering of block mathematical expressions (#29677) (#29711)
+  * Fix rendering internal file links in org (#29669) (#29705)
+  * Don't show AbortErrors on logout (#29639) (#29667)
+  * Fix user-defined markup links targets (#29305) (#29666)
+  * Fix incorrect rendering csv file when file size is larger than UI.CSV.MaxFileSize (#29653) (#29663)
+  * Fix hidden test's failure (#29254) (#29662)
+  * Add empty repo check-in DetectAndHandleSchedules (#29606) (#29659)
+  * Fix 500 when deleting an account with an incorrect password or unsupported login type (#29579) (#29656)
+  * Use strict protocol check when redirect (#29642) (#29644)
+  * Avoid issue info panic (#29625) (#29632)
+  * Avoid unexpected panic in graceful manager (#29629) (#29630)
+  * Make "/user/login" page redirect if the current user has signed in (#29583) (#29599)
+  * Fix workflow trigger event IssueChangeXXX bug (#29559) (#29565)
+  * Fix incorrect cookie path for AppSubURL (#29534) (#29552)
+  * Fix queue worker incorrectly stopped when there are still more items in the queue (#29532) (#29546)
+  * Fix incorrect redirection when creating a PR fails (#29537) (#29543)
+  * Fix incorrect subpath in links (#29535) (#29541)
+  * Fix issue link does not support quotes (#29484) (#29487) (#29536)
+  * Fix issue & comment history bugs (#29525) (#29527)
+  * Set pre-step status to `skipped` if the job is skipped (#29489) (#29523)
+  * Fix/Improve `processWindowErrorEvent` (#29407) (#29480)
+  * Fix counter display number incorrectly displayed on the page (#29448) (#29478)
+  * Fix workflow trigger event bugs (#29467) (#29475)
+  * Fix URL calculation in the clone input box (#29470) (#29473)
+  * The job should always run when `if` is `always()` (#29464) (#29469)
+  * Fix template bug (#27581) (#29446)
+  * Not trigger all jobs anymore when re-running the first job (#29439) (#29441)
+  * Ignore empty repo for CreateRepository in action notifier (#29416) (#29424)
+  * Fix incorrect tree path value for patch editor (#29377) (#29421)
+  * Add missing database transaction for new issues (#29490) (#29607)
+  * Fix 500 when pushing release to an empty repo (#29554) (#29564)
+  * Fix incorrect relative/absolute URL usages (#29531) (#29547)
+  * Fix wrong test usage of `AppSubURL` (#29459) (#29488)
+  * Fix missed return (#29450) (#29453)
+  * Fixing the issue when status checks per rule matches multiple actions (#29631) (#29655)
+  * Improve contrast on blame timestamp, fix double border (#29482) (#29485)
+
+## [1.21.7](https://github.com/go-gitea/gitea/releases/tag/v1.21.7) - 2024-02-26
+
+* ENHANCEMENTS
+  * Users with `read` permission of pull requests can be assigned too (#27263) (#29372)
+* BUGFIXES
+  * Do not double close reader (#29354) (#29370)
+  * Display friendly error message (#29105) (#29363)
+  * Fix project counter in organization/individual profile (#28068) (#29361)
+  * Fix validity of the FROM email address not being checked (#29347) (#29360)
+  * Fix tarball/zipball download bug (#29342) (#29352)
+* DOCS
+  * Docker Tag Information in Docs (#29047) (#29362)
+* MISC
+  * Enforce maxlength in frontend (#29389) (#29396)
+
 ## [1.21.6](https://github.com/go-gitea/gitea/releases/tag/v1.21.6) - 2024-02-22
 
 * SECURITY
@@ -159,11 +298,11 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Fix the issue ref rendering for wiki (#28556) (#28559)
   * Fix duplicate ID when deleting repo (#28520) (#28528)
   * Only check online runner when detecting matching runners in workflows (#28286) (#28512)
-  * Initalize stroage for orphaned repository doctor (#28487) (#28490)
+  * Initialize stroage for orphaned repository doctor (#28487) (#28490)
   * Fix possible nil pointer access (#28428) (#28440)
   * Don't show unnecessary citation JS error on UI (#28433) (#28437)
 * DOCS
-  * Update actions document about comparsion as Github Actions (#28560) (#28564)
+  * Update actions document about comparison as Github Actions (#28560) (#28564)
   * Fix documents for "custom/public/assets/" (#28465) (#28467)
 * MISC
   * Fix inperformant query on retrifing review from database. (#28552) (#28562)
@@ -673,7 +812,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Docs: template variables (#26547)
   * Update index doc (#26455)
   * Update zh-cn documentation (#26406)
-  * Fix typos and grammer problems for actions documentation (#26328)
+  * Fix typos and grammar problems for actions documentation (#26328)
   * Update documentation for 1.21 actions (#26317)
   * Doc update swagger doc for POST /orgs/{org}/teams (#26155)
   * Doc sync authentication.md to zh-cn (#26117)
@@ -762,7 +901,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Fix incorrect color of selected assignees when create issue (#26324) (#26372)
   * Display human-readable text instead of cryptic filemodes (#26352) (#26358)
   * Hide `last indexed SHA` when a repo could not be indexed yet (#26340) (#26345)
-  * Fix the topic validation rule and suport dots (#26286) (#26303)
+  * Fix the topic validation rule and support dots (#26286) (#26303)
   * Fix due date rendering the wrong date in issue (#26268) (#26274)
   * Don't autosize textarea in diff view (#26233) (#26244)
   * Fix commit compare style (#26209) (#26226)
@@ -989,7 +1128,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Add dark mode to API Docs (#24971)
   * Display file mode for new file and file mode changes (#24966)
   * Make the 500 page load themes (#24953)
-  * Show `bot` label next to username when rendering autor link if the user is a bot (#24943)
+  * Show `bot` label next to username when rendering author link if the user is a bot (#24943)
   * Repo list improvements, fix bold helper classes (#24935)
   * Improve queue and logger context (#24924)
   * Improve RunMode / dev mode (#24886)
@@ -1384,7 +1523,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Replace `drone exec` to `act_runner exec` in test README.md (#24791)
   * Update packages overview page (#24730)
   * Docs for creating a user to run Gitea on Fedora/RHEL/CentOS (#24725)
-  * Move actions as usage's subdirectory and update comparsion zh-cn version (#24719)
+  * Move actions as usage's subdirectory and update comparison zh-cn version (#24719)
   * Document `redis-cluster` explicitly in config (#24717)
   * Improve reverse-proxy document and fix nginx config bug (#24616)
   * Fix broken `README` link (#24546)
@@ -1462,7 +1601,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Show visibility status of email in own profile (#23900)
   * Refactor authors dropdown (send get request from frontend to avoid long wait time) (#23890)
   * Add self to maintainers (#23644)
-  * Upgrade to npm lockfile v3 and explicitely set it (#23561)
+  * Upgrade to npm lockfile v3 and explicitly set it (#23561)
   * Improve indices for `action` table (#23532)
   * Update JS dependencies, Require Node.js 16 (#23528)
   * Add init file for Ubuntu (#23362)
@@ -1503,7 +1642,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Fix issues list page multiple selection update milestones (#24660) (#24663)
   * Fix: release page for empty or non-existing target (#24659)
   * Fix close org projects (#24588) (#24591)
-  * Refresh the refernce of the closed PR when reopening (#24231) (#24587)
+  * Refresh the references of the closed PR when reopening (#24231) (#24587)
   * Fix the permission of team's `Actions` unit issue (#24536) (#24545)
   * Bump go.etcd.io/bbolt and blevesearch deps (#23062) (#24519)
   * Fix new wiki page mirror (#24518)
@@ -2644,7 +2783,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Feeds: render markdown to html (#19058)
   * Allow users to self-request a PR review (#19030)
   * Allow render HTML with css/js external links (#19017)
-  * Fix script compatiable with OpenWrt (#19000)
+  * Fix script compatible with OpenWrt (#19000)
   * Support ignore all santize for external renderer (#18984)
   * Add note to GPG key response if user has no keys (#18961)
   * Improve Stopwatch behavior (#18930)
@@ -2975,7 +3114,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Update go-org to v1.6.1 (#18932) (#18933)
   * Fix `` html in translation (#18929) (#18931)
   * Fix page and missing return on unadopted repos API (#18848) (#18927)
-  * Allow adminstrator teams members to see other teams (#18918) (#18919)
+  * Allow administrator teams members to see other teams (#18918) (#18919)
   * Don't treat BOM escape sequence as hidden character. (#18909) (#18910)
   * Correctly link URLs to users/repos with dashes, dots or underscores (… (#18908)
   * Fix redirect when using lowercase repo name (#18775) (#18902)
@@ -3323,7 +3462,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Fixed issue merged/closed wording (#17973)
   * Return nicer error for ForcePrivate (#17971)
   * Fix overflow in commit graph (#17947)
-  * Prevent services/mailer/mailer_test.go tests from deleteing data directory (#17941)
+  * Prevent services/mailer/mailer_test.go tests from deleting data directory (#17941)
   * Use disable_form_autofill on Codebase and Gitbucket (#17936)
   * Fix a panic in NotifyCreateIssueComment (caused by string truncation) (#17928)
   * Fix markdown URL parsing (#17924)
@@ -3362,7 +3501,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
   * Fixed emoji alias not parsed in links (#16221)
   * Calculate label URL on API  (#16186)
 * TRANSLATION
-  * Fix mispelling of starred as stared (#17465)
+  * Fix misspelling of starred as stared (#17465)
   * Re-separate the color translation strings (#17390)
   * Enable Malayalam, Greek, Persian, Hungarian & Indonesian by default (#16998)
 * BUILD
@@ -3371,5219 +3510,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
 * MISC
   * Update JS dependencies (#17611)
 
-## [1.15.11](https://github.com/go-gitea/gitea/releases/tag/v1.15.11) - 2022-01-29
+## Archived releases
 
-* SECURITY
-  * Only view milestones from current repo (#18414) (#18418)
-* BUGFIXES
-  * Fix broken when no commits and default branch is not master (#18422) (#18424)
-  * Fix commit's time (#18375) (#18409)
-  * Fix restore without topic failure (#18387) (#18401)
-  * Fix mermaid import in 1.15 (it uses ESModule now) (#18382)
-  * Update to go/text 0.3.7 (#18336)
-* MISC
-  * Upgrade EasyMDE to 2.16.1 (#18278) (#18279)
-
-## [1.15.10](https://github.com/go-gitea/gitea/releases/tag/v1.15.10) - 2022-01-14
-
-* BUGFIXES
-  * Fix inconsistent PR comment counts (#18260) (#18261)
-  * Fix release link broken (#18252) (#18253)
-  * Fix update user from site administration page bug (#18250) (#18251)
-  * Set HeadCommit when creating tags (#18116) (#18173)
-  * Use correct translation key for error messages due to max repo limits (#18135 & #18153) (#18152)
-  * Fix purple color in suggested label colors (#18241) (#18242)
-* SECURITY
-  * Bump mermaid from 8.10.1 to 8.13.8 (#18198) (#18206)
-
-## [1.15.9](https://github.com/go-gitea/gitea/releases/tag/v1.15.9) - 2021-12-30
-
-* BUGFIXES
-  * Fix wrong redirect on org labels (#18128) (#18134)
-  * Fix: unstable sort skips/duplicates issues across pages (#18094) (#18095)
-  * Revert "Fix delete u2f keys bug (#18042)" (#18107)
-  * Migrating wiki don't require token, so we should move it out of the require form (#17645) (#18104)
-  * Prevent NPE if gitea uploader fails to open url (#18080) (#18101)
-  * Reset locale on login (#17734) (#18100)
-  * Correctly handle failed migrations (#17575) (#18099)
-  * Instead of using routerCtx just escape the url before routing (#18086) (#18098)
-  * Quote references to the user table in consistency checks (#18072) (#18073)
-  * Add NotFound handler (#18062) (#18067)
-  * Ensure that git repository is closed before transfer (#18049) (#18057)
-  * Use common sessioner for API and web routes (#18114)
-* TRANSLATION
-  * Fix code search result hint on zh-CN (#18053)
-
-## [1.15.8](https://github.com/go-gitea/gitea/releases/tag/v1.15.8) - 2021-12-20
-
-* BUGFIXES
-  * Move POST /{username}/action/{action} to simply POST /{username} (#18045) (#18046)
-  * Fix delete u2f keys bug (#18040) (#18042)
-  * Reset Session ID on login (#18018) (#18041)
-  * Prevent off-by-one error on comments on newly appended lines (#18029) (#18035)
-  * Stop printing 03d after escaped characters in logs (#18030) (#18034)
-  * Reset locale on login (#18023) (#18025)
-  * Fix reset password email template (#17025) (#18022)
-  * Fix outType on gitea dump (#18000) (#18016)
-  * Ensure complexity, minlength and isPwned are checked on password setting (#18005) (#18015)
-  * Fix rename notification bug (#18011)
-  * Prevent double decoding of % in url params  (#17997) (#18001)
-  * Prevent hang in git cat-file if the repository is not a valid repository (Partial #17991) (#17992)
-  * Prevent deadlock in create issue (#17970) (#17982)
-* TESTING
-  * Use non-expiring key. (#17984) (#17985)
-
-## [1.15.7](https://github.com/go-gitea/gitea/releases/tag/v1.15.7) - 2021-12-01
-
-* ENHANCEMENTS
-  * Only allow webhook to send requests to allowed hosts (#17482) (#17510)
-  * Fix login redirection links (#17451) (#17473)
-* BUGFIXES
-  * Fix database inconsistent when admin change user email (#17549) (#17840)
-  * Use correct user on releases (#17806) (#17818)
-  * Fix commit count in tag view (#17698) (#17790)
-  * Fix close issue but time watcher still running (#17643) (#17761)
-  * Fix Migrate Description (#17692) (#17727)
-  * Fix bug when project board get open issue number (#17703) (#17726)
-  * Return 400 but not 500 when request archive with wrong format (#17691) (#17700)
-  * Fix bug when read mysql database max lifetime (#17682) (#17690)
-  * Fix database deadlock when update issue labels (#17649) (#17665)
-  * Fix bug on detect issue/comment writer (#17592)
-  * Remove appSubUrl from pasted images (#17572) (#17588)
-  * Make `ParsePatch` more robust (#17573) (#17580)
-  * Fix stats upon searching issues (#17566) (#17578)
-  * Escape issue titles in comments list (#17555) (#17556)
-  * Fix zero created time bug on commit api (#17546) (#17547)
-  * Fix database keyword quote problem on migration v161 (#17522) (#17523)
-  * Fix email with + when active (#17518) (#17520)
-  * Stop double encoding blame commit messages (#17498) (#17500)
-  * Quote the table name in CountOrphanedObjects (#17487) (#17488)
-  * Run Migrate in Install rather than just SyncTables (#17475) (#17486)
-* BUILD
-  * Fix golangci-lint warnings (#17598 et al) (#17668)
-* MISC
-  * Preserve color when inverting emojis (#17797) (#17799)
-
-## [1.15.6](https://github.com/go-gitea/gitea/releases/tag/v1.15.6) - 2021-10-28
-
-* BUGFIXES
-  * Prevent panic in serv.go with Deploy Keys (#17434) (#17435)
-  * Fix CSV render error (#17406) (#17431)
-  * Read expected buffer size (#17409) (#17430)
-  * Ensure that restricted users can access repos for which they are members (#17460) (#17464)
-  * Make commit-statuses popup show correctly (#17447) (#17466)
-* TESTING
-  * Add integration tests for private.NoServCommand and private.ServCommand (#17456) (#17463)
-
-## [1.15.5](https://github.com/go-gitea/gitea/releases/tag/v1.15.5) - 2021-10-21
-
-* SECURITY
-  * Upgrade Bluemonday to v1.0.16 (#17372) (#17374)
-  * Ensure correct SSH permissions check for private and restricted users (#17370) (#17373)
-* BUGFIXES
-  * Prevent NPE in CSV diff rendering when column removed (#17018) (#17377)
-  * Offer rsa-sha2-512 and rsa-sha2-256 algorithms in internal SSH (#17281) (#17376)
-  * Don't panic if we fail to parse U2FRegistration data (#17304) (#17371)
-  * Ensure popup text is aligned left (backport for 1.15) (#17343)
-  * Ensure that git daemon export ok is created for mirrors (#17243) (#17306)
-  * Disable core.protectNTFS (#17300) (#17302)
-  * Use pointer for wrappedConn methods (#17295) (#17296)
-  * AutoRegistration is supposed to be working with disabled registration (backport) (#17292)
-  * Handle duplicate keys on GPG key ring (#17242) (#17284)
-  * Fix SVG side by side comparison link (#17375) (#17391)
-
-## [1.15.4](https://github.com/go-gitea/gitea/releases/tag/v1.15.4) - 2021-10-08
-
-* BUGFIXES
-  * Raw file API: don't try to interpret 40char filenames as commit SHA (#17185) (#17272)
-  * Don't allow merged PRs to be reopened (#17192) (#17271)
-  * Fix incorrect repository count on organization tab of dashboard (#17256) (#17266)
-  * Fix unwanted team review request deletion (#17257) (#17264)
-  * Fix broken Activities link in team dashboard (#17255) (#17258)
-  * API pull's head/base have correct permission(#17214) (#17245)
-  * Fix strange behavior of DownloadPullDiffOrPatch in incorrect index (#17223) (#17227)
-  * Upgrade xorm to v1.2.5 (#17177) (#17188)
-  * Fix missing repo link in issue/pull assigned emails (#17183) (#17184)
-  * Fix bug of get context user (#17169) (#17172)
-  * Nicely handle missing user in collaborations (#17049) (#17166)
-  * Add Horizontal scrollbar to inner menu on Chrome (#17086) (#17164)
-  * Fix wrong i18n keys (#17150) (#17153)
-  * Fix Archive Creation: correct transaction ending (#17151)
-  * Prevent panic in Org mode HighlightCodeBlock (#17140) (#17141)
-  * Create doctor command to fix repo_units broken by dumps from 1.14.3-1.14.6 (#17136) (#17137)
-* ENHANCEMENT
-  * Check user instead of organization when creating a repo from a template via API (#16346) (#17195)
-* TRANSLATION
-  * v1.15 fix Sprintf format 'verbs' in locale files (#17187)
-
-## [1.15.3](https://github.com/go-gitea/gitea/releases/tag/v1.15.3) - 2021-09-19
-
-* ENHANCEMENTS
-  * Add fluid to ui container class to remove margin (#16396) (#16976)
-  * Add caller to cat-file batch calls (#17082) (#17089)
-* BUGFIXES
-  * Render full plain readme. (#17083) (#17090)
-  * Upgrade xorm to v1.2.4 (#17059)
-  * Fix bug of migrate comments which only fetch one page (#17055) (#17058)
-  * Do not show issue context popup on external issues (#17050) (#17054)
-  * Decrement Fork Num when converting from Fork (#17035) (#17046)
-  * Correctly rollback in ForkRepository (#17034) (#17045)
-  * Fix missing close in WalkGitLog (#17008) (#17009)
-  * Add prefix to SVG id/class attributes (#16997) (#17000)
-  * Fix bug of migrated repository not index (#16991) (#16996)
-  * Skip AllowedUserVisibilityModes validation on update user if it is an organisation (#16988) (#16990)
-  * Fix storage Iterate bug and Add storage doctor to delete garbage attachments (#16971) (#16977)
-  * Fix issue with issue default mail template (#16956) (#16975)
-  * Ensure that rebase conflicts are handled in updates (#16952) (#16960)
-  * Prevent panic on diff generation (#16950) (#16951)
-
-## [1.15.2](https://github.com/go-gitea/gitea/releases/tag/v1.15.2) - 2021-09-03
-
-* BUGFIXES
-  * Add unique constraint back into issue_index (#16938)
-  * Close storage objects before cleaning (#16934) (#16942)
-
-## [1.15.1](https://github.com/go-gitea/gitea/releases/tag/v1.15.1) - 2021-09-02
-
-* BUGFIXES
-  * Allow BASIC authentication access to /:owner/:repo/releases/download/* (#16916) (#16923)
-  * Prevent leave changes dialogs due to autofill fields (#16912) (#16920)
-  * Ignore review comment when ref commit is missed (#16905) (#16919)
-  * Fix wrong attachment removal (#16915) (#16917)
-  * Gitlab Migrator: dont ignore reactions of last request (#16903) (#16913)
-  * Correctly return the number of Repositories for Organizations (#16807) (#16911)
-  * Test if LFS object is accessible (#16865) (#16904)
-  * Fix git.Blob.DataAsync(): close pipe since we return a NopCloser (#16899) (#16900)
-  * Fix dump and restore respository (#16698) (#16898)
-  * Repare and Improve GetDiffRangeWithWhitespaceBehavior (#16894) (#16895)
-  * Fix wiki raw commit diff/patch view (#16891) (#16892)
-  * Ensure wiki repos are all closed (#16886) (#16888)
-  * List limited and private orgs if authenticated on API (#16866) (#16879)
-  * Simplify split diff view generation and remove JS dependency (#16775) (#16863)
-  * Ensure that the default visibility is set on the user create page (#16845) (#16862)
-  * In Render tolerate not being passed a context (#16842) (#16858)
-  * Upgrade xorm to v1.2.2 (#16663) & Add test to ensure that dumping of login sources remains correct (#16847) (#16848)
-  * Report the correct number of pushes on the feeds (#16811) (#16822)
-  * Add primary_key to issue_index (#16813) (#16820)
-  * Prevent NPE on empty commit (#16812) (#16819)
-  * Fix branch pagination error (#16805) (#16816)
-  * Add missing return to handleSettingRemoteAddrError (#16794) (#16795)
-  * Remove spurious / from issues.opened_by (#16793)
-  * Ensure that template compilation panics are sent to the logs (#16788) (#16792)
-  * Update caddyserver/certmagic (#16789) (#16790)
-
-## [1.15.0](https://github.com/go-gitea/gitea/releases/tag/v1.15.0) - 2021-08-21
-
-* BREAKING
-  * Make app.ini permissions more restrictive (#16266)
-  * Refactor Webhook + Add X-Hub-Signature (#16176)
-  * Add asymmetric JWT signing (#16010)
-  * Clean-up the settings hierarchy for issue_indexer queue (#16001)
-  * Change default queue settings to be low go-routines (#15964)
-  * Improve assets handler middleware (#15961)
-  * Rename StaticUrlPrefix to AssetUrlPrefix (#15779)
-  * Use a generic markup class to display externally rendered files and diffs (#15735)
-  * Add frontend testing, require node 12 (#15315)
-  * Move (custom) assets into subpath `/assets` (#15219)
-  * Use level config in log section when sub log section not set level (#15176)
-  * Links in markdown should be absolute to the repository not the server (#15088)
-  * Upgrade to the latest version of golang-jwt (#16590) (#16606)
-  * Set minimum supported version of go to 1.16 (#16710)
-* SECURITY
-  * Encrypt LDAP bind password in db with SECRET_KEY (#15547)
-  * Remove random password in Dockerfiles (#15362)
-  * Upgrade to the latest version of golang-jwt and increase minimum go to 1.15 (#16590) (#16606)
-  * Correctly create of git-daemon-export-ok files (#16508) (#16514)
-  * Don't show private user's repo in explore view (#16550) (#16554)
-  * Update node tar dependency to 6.1.6 (#16622) (#16623)
-* FEATURES
-  * Update Go-Git to take advantage of LargeObjectThreshold (#16316)
-  * Support custom mime type mapping for text files (#16304)
-  * Link to previous blames in file blame page (#16259)
-  * Add LRU mem cache implementation (#16226)
-  * Localize Email Templates (#16200)
-  * Make command in authorized keys a template (#16003)
-  * Add possibility to make branch in branch page (#15960)
-  * Add email headers (#15939)
-  * Make tasklist checkboxes clickable (#15791)
-  * Add selecting tags on the compare page (#15723)
-  * Add cron job to delete old actions from database (#15688)
-  * On open repository open common cat file batch and batch-check (#15667)
-  * Add tag protection (#15629)
-  * Add push to remote mirror repository (#15157)
-  * Add Image Diff for SVG files (#14867)
-  * Add dashboard milestone search and repo milestone search by name. (#14866)
-  * Add LFS Migration and Mirror (#14726)
-  * Improve notifications for WIP draft PR's (#14663)
-  * Disable Stars config option (#14653)
-  * GPG Key Ownership verification with Signed Token (#14054)
-  * OAuth2 auto-register (#5123)
-* API
-  * Return updated repository when changing repository using API (#16420)
-  * Let branch/tag name be a valid ref to get CI status (#16400)
-  * Add endpoint to get commits of PR (#16300)
-  * Allow COMMENT reviews to not specify a body (#16229)
-  * Add subject-type filter to list notification API endpoints (#16177)
-  * ListReleases add filter for draft and pre-releases (#16175)
-  * ListIssues add more filters (#16174)
-  * Issue Search Add filter for MilestoneNames (#16173)
-  * GET / SET User Settings (#16169)
-  * Expose repo.GetReviewers() & repo.GetAssignees() (#16168)
-  * User expose counters (#16167)
-  * Add repoGetTag (#16166)
-  * Add repoCreateTag (#16165)
-  * Creating a repo from a template repo via API (#15958)
-  * Add Active and ProhibitLogin to API (#15689)
-  * Add Location, Website and Description to API (#15675)
-  * Expose resolver via API (#15167)
-  * Swagger AccessToken fixes (#16574) (#16597)
-  * Set AllowedHeaders on API CORS handler (#16524) (#16618)
-* ENHANCEMENTS
-  * Support HTTP/2 in Let's Encrypt (#16371)
-  * Introduce NotifySubjectType (#16320)
-  * Add forge emojies (#16296)
-  * Implemented head_commit for webhooks (#16282)
-  * Upgrade Gliderlabs SSH to 0.3.3 and add FailedConnectionCallback (#16278)
-  * Add previous/next buttons to review comments (#16273)
-  * Review comments: break-word for long file names (#16272)
-  * Add configuration to restrict allowed user visibility modes (#16271)
-  * Add scroll-margin-top to account for sticky header (#16269)
-  * Add --quiet and --verbose to gitea web to control initial logging (#16260)
-  * Use gitea logging module for git module (#16243)
-  * Add tests for all webhooks (#16214)
-  * Add button to delete undeleted repositories from failed migrations (#16197)
-  * Speed up git diff highlight generation (#16180)
-  * Add OpenID claims "profile" and "email". (#16141)
-  * Reintroduce squash merge default comment as a config setting (#16134)
-  * Add sanitizer rules per renderer (#16110)
-  * Improve performance of dashboard list orgs (#16099)
-  * Refactor assert statements in tests (#16089)
-  * Add sso.Group, context.Auth, context.APIAuth to allow auth special routes (#16086)
-  * Remove unnecessary goroutine (#16080)
-  * Add attachments for PR reviews (#16075)
-  * Make the github migration less rate limit waiting to get comment per page from repository but not per issue (#16070)
-  * Add Visible modes function from Organisation to Users too (#16069)
-  * Add checkbox to delete pull branch after successful merge (#16049)
-  * Make commit info cancelable (#16032)
-  * Make modules/context.Context a context.Context (#16031)
-  * Unified custom config creation (#16012)
-  * Make sshd_config more flexible regarding connections (#16009)
-  * Append to existing trailers in generated squash commit message (#15980)
-  * Always store primary email address into email_address table and also the state (#15956)
-  * Load issue/PR context popup data only when needed (#15955)
-  * Remove remaining fontawesome usage in templates (#15952)
-  * Remove fomantic accordion module (#15951)
-  * Small refactoring of modules/private (#15947)
-  * Double the avatar size factor (#15941)
-  * Add curl to rootless docker image (#15908)
-  * Replace clipboard.js with async clipboard api (#15899)
-  * Allow custom highlight mapping beyond file extensions (#15808)
-  * Add trace logging to SSO methods (#15803)
-  * Refactor routers directory (#15800)
-  * Allow only internal registration (#15795)
-  * Add a new internal hook to save ssh log (#15787)
-  * Respect default merge message syntax when parsing item references (#15772)
-  * OAuth2 login: Set account link to "login" as default behavior (#15768)
-  * Use single shared random string generation function (#15741)
-  * Hold the event source when there are no listeners (#15725)
-  * Code comments improvements (#15722)
-  * Provide OIDC compliant user info endpoint (#15721)
-  * Fix webkit calendar icon color on arc-green (#15713)
-  * Improve Light Chroma style (#15699)
-  * Only use boost workers for leveldb shadow queues (#15696)
-  * Add compare tag dropdown to releases page (#15695)
-  * Add caret styling CSS (#15651)
-  * Remove x-ua-compatible meta tag (#15640)
-  * Refactor of link creation (#15619)
-  * Add a new table issue_index to store the max issue index so that issue could be deleted with no duplicated index (#15599)
-  * Rewrite of the LFS server (#15523)
-  * Display more repository type on admin repository management (#15440)
-  * Remove usage of some JS globals (#15378)
-  * SHA in merged commit comment should be rendered ui sha (#15376)
-  * Add well-known config for OIDC (#15355)
-  * Use route rather than use thus reducing the number of stack frames (#15301)
-  * Code Formats, Nits & Unused Func/Var deletions (#15286)
-  * Let package git depend on setting but not opposite (#15241)
-  * Fixed sanitize errors (#15240)
-  * response simple text message for not html request when 404 (#15229)
-  * Remove file-loader dependency (#15196)
-  * Refactor renders (#15175)
-  * Add mimetype mapping settings (#15133)
-  * Add Status Updates whilst Gitea migrations are occurring (#15076)
-  * Reload locales in initialisation if needed by utilizing i18n.Reset (#15073)
-  * Counterwork seemingly unclickable repo button labels (#15064)
-  * Add DefaultMergeStyle option to repository (#14789)
-  * Added support for gopher URLs. (#14749)
-  * Rework repository archive (#14723)
-  * Add links to toggle WIP status (#14677)
-  * Add Tabular Diff for CSV files (#14661)
-  * Use milestone deadline when sorting issues (#14551)
-* BUGFIXES
-  * Fix invalid params and typo of email templates (#16394)
-  * Fix activation of primary email addresses (#16385)
-  * Fix calculation for finalPage in repo-search component (#16382)
-  * Specify user in rootless container numerically (#16361)
-  * Detect encoding changes while parsing diff (#16330)
-  * Fix U2F error reasons always hidden (#16327)
-  * Prevent zombie processes (#16314)
-  * Escape reference to `user` table in models.SearchEmails (#16313)
-  * Fix default push instructions on empty repos (#16302)
-  * Fix modified files list in webhooks when there is a space (#16288)
-  * Fix webhook commits wrong hash on HEAD reset (#16283)
-  * Fuzzer finds an NPE due to incorrect URLPrefix (#16249)
-  * Don't WARN log UserNotExist errors on ExternalUserLogin failure (#16238)
-  * Do not show No match found for tribute (#16231)
-  * Fix "Copy Link" for pull requests (#16230)
-  * Fix diff expansion is missing final line in a file (#16222)
-  * Fix private repo permission problem (#16142)
-  * Fix not able to update local created non-urlencoded wiki pages (#16139)
-  * More efficiently parse shas for shaPostProcessor (#16101)
-  * Fix `doctor --run check-db-consistency --fix` with label fix (#16094)
-  * Prevent webhook action buttons from shifting (#16087)
-  * Change default TMPDIR path in rootless containers (#16077)
-  * Fix typo and add TODO notice (#16064)
-  * Use git log name-status in get last commit (#16059)
-  * Fix 500 Error with branch and tag sharing the same name (#16040)
-  * Fix get tag when migration (#16014)
-  * Add custom emoji support (#16004)
-  * Use filepath.ToSlash and Join in indexer defaults and queues (#15971)
-  * Add permission check for ``GenerateRepository`` (#15946)
-  * Ensure settings for Service and Mailer are read on the install page (#15943)
-  * Fix layout of milestone view (#15927)
-  * Unregister non-matching serviceworkers (#15834)
-  * Multiple Queue improvements: LevelDB Wait on empty, shutdown empty shadow level queue, reduce goroutines etc (#15693)
-  * Attachment support repository route (#15580)
-  * Fix missing icons and colorpicker when mounted on suburl (#15501)
-  * Create a session on ReverseProxy and ensure that ReverseProxy users cannot change username (#15304)
-  * Prevent double-login for Git HTTP and LFS and simplify login (#15303)
-  * Resolve Object { type: "error", data: undefined } in stopwatch.js (#15278)
-  * Fix heatmap activity (#15252)
-  * Remove vendored copy of fomantic-dropdown (#15193)
-  * Update repository size on cron gc task (#15177)
-  * Add NeedPostProcess for Parser interface to improve performance of csv parser and some external parser (#15153)
-  * Add code block highlight to orgmode back (#14222)
-  * Remove User.GetOrganizations() (#14032)
-  * Restore Accessibility for Dropdown (#16576) (#16617)
-  * Pass down SignedUserName down to AccessLogger context (#16605) (#16616)
-  * Fix table alignment in markdown (#16596) (#16602)
-  * Fix 500 on first wiki page (#16586) (#16598)
-  * Lock goth/gothic and Re-attempt OAuth2 registration on login if registration failed at startup (#16564) (#16570)
-  * Upgrade levelqueue to v0.4.0 (#16560) (#16561)
-  * Handle too long PR titles correctly (#16517) (#16549)
-  * Fix data race in bleve indexer (#16474) (#16509)
-  * Restore CORS on git smart http protocol (#16496) (#16506)
-  * Fix race in log (#16490) (#16505)
-  * Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498)
-  * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480)
-  * Update notification table with only latest data (#16445) (#16469)
-  * Fix crash following ldap authentication update (#16447) (#16448)
-  * Fix direct creation of external users on admin page (partial #16612) (#16613)
-  * Prevent 500 on draft releases without tag (#16634) (#16636)
-  * Restore creation of git-daemon-export-ok files (#16508) (#16514)
-  * Fix data race in bleve indexer (#16474) (#16509)
-  * Restore CORS on git smart http protocol (#16496) (#16506)
-  * Fix race in log (#16490) (#16505)
-  * Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498)
-  * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480)
-  * Update notification table with only latest data (#16445) (#16469)
-  * Fix crash following ldap authentication update (#16447) (#16448)
-  * Restore compatibility with SQLServer 2008 R2 in migrations (#16638)
-  * Fix direct creation of external users on admin page (#16613)
-  * Fix go-git implementation of GetNote when passed a non-existent commit (#16658) (#16659)
-  * Fix NPE in fuzzer (#16680) (#16682)
-  * Set issue_index when finishing migration (#16685) (#16687)
-  * Skip patch download when no patch file exists (#16356) (#16681)
-  * Ensure empty lines are copiable and final new line too (#16678) (#16692)
-  * Fix wrong user in OpenID response (#16736) (#16741)
-  * Do not use thin scrollbars on Firefox (#16738) (#16745)
-  * Recreate Tables should Recreate indexes on MySQL (#16718) (#16739)
-  * Keep attachments on tasklist update (#16750) (#16757)
-* TESTING
-  * Bump `postgres` and `mysql` versions (#15710)
-  * Add tests for clone from wiki (#15513)
-  * Fix Benchmark tests, remove a broken one & add two new  (#15250)
-  * Create Proper Migration tests (#15116)
-* TRANSLATION
-  * Use a special name for update default branch on repository setting (#15893)
-  * Fix mirror_lfs source string in en-US locale (#15369)
-* BUILD
-  * Upgrade xorm to v1.1.1 (#16339)
-  * Disable legal comments in esbuild (#15929)
-  * Switch to Node 16 to build fronted  (#15804)
-  * Use esbuild to minify CSS (#15756)
-  * Use binary version of revive linter (#15739)
-  * Fix: npx webpack make: *** [Makefile:699: public/js/index.js] Error -… (#15465)
-  * Stop packaging node_modules in release tarballs (#15273)
-  * Introduce esbuild on webpack (#14578)
-* DOCS
-  * Update queue workers documentation (#15999)
-  * Comment out app.example.ini (#15807)
-  * Improve logo customization docs (#15754)
-  * Add some response status on api docs (#15399)
-  * Rework Token API comments (#15162)
-  * Add better errors for disabled account recovery (#15117)
-* MISC
-  * Remove utf8 option from installation page (#16126)
-  * Use Wants= over Requires= in systemd file (#15897)
-
-## [1.14.7](https://github.com/go-gitea/gitea/releases/tag/v1.14.7) - 2021-09-02
-
-* BUGFIXES
-  * Add missing gitRepo close at GetDiffRangeWithWhitespaceBehavior (Partial #16894) (#16896)
-  * Fix wiki raw commit diff/patch view (#16891) (#16893)
-  * Ensure wiki repos are all closed (#16886) (#16889)
-  * Upgrade xorm to v1.2.2 (#16663) & Add test to ensure that dumping of login sources remains correct (#16847) (#16849)
-  * Recreate Tables should Recreate indexes on MySQL (#16718) (#16740)
-
-## [1.14.6](https://github.com/go-gitea/gitea/releases/tag/v1.14.6) - 2021-08-04
-
-* SECURITY
-  * Bump github.com/markbates/goth from v1.67.1 to v1.68.0 (#16538) (#16540)
-  * Switch to maintained JWT lib (#16532) (#16535)
-  * Upgrade to latest version of golang-jwt (as forked for 1.14) (#16590) (#16607)
-* BUGFIXES
-  * Add basic edit ldap auth test & actually fix #16252 (#16465) (#16495)
-  * Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16481)
-
-## [1.14.5](https://github.com/go-gitea/gitea/releases/tag/v1.14.5) - 2021-07-16
-
-* SECURITY
-  * Hide mirror passwords on repo settings page (#16022) (#16355)
-  * Update bluemonday to v1.0.15 (#16379) (#16380)
-* BUGFIXES
-  * Retry rename on lock induced failures (#16435) (#16439)
-  * Validate issue index before querying DB (#16406) (#16410)
-  * Fix crash following ldap authentication update (#16447) (#16449)
-* ENHANCEMENTS
-  * Redirect on bad CSRF instead of presenting bad page (#14937) (#16378)
-
-## [1.14.4](https://github.com/go-gitea/gitea/releases/tag/v1.14.4) - 2021-07-06
-
-* BUGFIXES
-  * Fix relative links in postprocessed images (#16334) (#16340)
-  * Fix list_options GetStartEnd (#16303) (#16305)
-  * Fix API to use author for commits instead of committer (#16276) (#16277)
-  * Handle misencoding of login_source cfg in mssql (#16268) (#16275)
-  * Fixed issues not updated by commits (#16254) (#16261)
-  * Improve efficiency in FindRenderizableReferenceNumeric and getReference (#16251) (#16255)
-  * Use html.Parse rather than html.ParseFragment (#16223) (#16225)
-  * Fix milestone counters on new issue (#16183) (#16224)
-  * reqOrgMembership calls need to be preceded by reqToken (#16198) (#16219)
-
-## [1.14.3](https://github.com/go-gitea/gitea/releases/tag/v1.14.3) - 2021-06-18
-
-* SECURITY
-  * Encrypt migration credentials at rest (#15895) (#16187)
-  * Only check access tokens if they are likely to be tokens (#16164) (#16171)
-  * Add missing SameSite settings for the i_like_gitea cookie (#16037) (#16039)
-  * Fix setting of SameSite on cookies (#15989) (#15991)
-* API
-  * Repository object only count releases as releases (#16184) (#16190)
-  * EditOrg respect RepoAdminChangeTeamAccess option (#16184) (#16190)
-  * Fix overly strict edit pr permissions (#15900) (#16081)
-* BUGFIXES
-  * Run processors on whole of text (#16155) (#16185)
-  * Class `issue-keyword` is being incorrectly stripped off spans (#16163) (#16172)
-  * Fix language switch for install page (#16043) (#16128)
-  * Fix bug on getIssueIDsByRepoID (#16119) (#16124)
-  * Set self-adjusting deadline for connection writing (#16068) (#16123)
-  * Fix http path bug (#16117) (#16120)
-  * Fix data URI scramble (#16098) (#16118)
-  * Merge all deleteBranch as one function and also fix bug when delete branch don't close related PRs (#16067) (#16097)
-  * git migration: don't prompt interactively for clone credentials (#15902) (#16082)
-  * Fix case change in ownernames (#16045) (#16050)
-  * Don't manipulate input params in email notification (#16011) (#16033)
-  * Remove branch URL before IssueRefURL (#15968) (#15970)
-  * Fix layout of milestone view (#15927) (#15940)
-  * GitHub Migration, migrate draft releases too (#15884) (#15888)
-  * Close the gitrepo when deleting the repository (#15876) (#15887)
-  * Upgrade xorm to v1.1.0 (#15869) (#15885)
-  * Fix blame row height alignment (#15863) (#15883)
-  * Fix error message when saving generated LOCAL_ROOT_URL config (#15880) (#15882)
-  * Backport Fix LFS commit finder not working (#15856) (#15874)
-  * Stop calling WriteHeader in Write (#15862) (#15873)
-  * Add timeout to writing to responses (#15831) (#15872)
-  * Return go-get info on subdirs (#15642) (#15871)
-  * Restore PAM user autocreation functionality (#15825) (#15867)
-  * Fix truncate utf8 string (#15828) (#15854)
-  * Fix bound address/port for caddy's certmagic library (#15758) (#15848)
-  * Upgrade unrolled/render to v1.1.1 (#15845) (#15846)
-  * Queue manager FlushAll can loop rapidly - add delay (#15733) (#15840)
-  * Tagger can be empty, as can Commit and Author - tolerate this (#15835) (#15839)
-  * Set autocomplete off on branches selector (#15809) (#15833)
-  * Add missing error to Doctor log (#15813) (#15824)
-  * Move restore repo to internal router and invoke from command to avoid open the same db file or queues files (#15790) (#15816)
-* ENHANCEMENTS
-  * Removable media support to snap package (#16136) (#16138)
-  * Move sans-serif fallback font higher than emoji fonts (#15855) (#15892)
-* DOCKER
-  * Only write config in environment-to-ini if there are changes (#15861) (#15868)
-  * Only offer hostcertificates if they exist (#15849) (#15853)
-
-## [1.14.2](https://github.com/go-gitea/gitea/releases/tag/v1.14.2) - 2021-05-09
-
-* API
-  * Make change repo settings work on empty repos (#15778) (#15789)
-  * Add pull "merged" notification subject status to API (#15344) (#15654)
-* BUGFIXES
-  * Ensure that ctx.Written is checked after issues(...) calls (#15797) (#15798)
-  * Use pulls in commit graph unless pulls are disabled (#15734 & #15740 & #15774) (#15775)
-  * Set GIT_DIR correctly if it is not set (#15751) (#15769)
-  * Fix bug where repositories appear unadopted (#15757) (#15767)
-  * Not show `ref-in-new-issue` pop when issue was disabled (#15761) (#15765)
-  * Drop back to use IsAnInteractiveSession for SVC (#15749) (#15762)
-  * Fix setting version table in dump (#15753) (#15759)
-  * Fix close button change on delete in simplemde area (#15737) (#15747)
-  * Defer closing the gitrepo until the end of the wrapped context functions (#15653) (#15746)
-  * Fix some ui bug about draft release (#15137) (#15745)
-  * Only log Error on getLastCommitStatus error to let pull list still be visible (#15716) (#15715)
-  * Move tooltip down to allow selection of Remove File on error (#15672) (#15714)
-  * Fix setting redis db path (#15698) (#15708)
-  * Fix DB session cleanup (#15697) (#15700)
-  * Fixed several activation bugs (#15473) (#15685)
-  * Delete references if repository gets deleted (#15681) (#15684)
-  * Fix orphaned objects deletion bug (#15657) (#15683)
-  * Delete protected branch if repository gets removed (#15658) (#15676)
-  * Remove spurious set name from eventsource.sharedworker.js (#15643) (#15652)
-  * Not update updated uinx for `git gc` (#15637) (#15641)
-  * Fix commit graph author link (#15627) (#15630)
-  * Fix webhook timeout bug (#15613) (#15621)
-  * Resolve panic on failed interface conversion in migration v156 (#15604) (#15610)
-  * Fix missing storage init (#15589) (#15598)
-  * If the default branch is not present do not report error on stats indexing (#15546 & #15583) (#15594)
-  * Fix lfs management find (#15537) (#15578)
-  * Fix NPE on view commit with notes (#15561) (#15573)
-  * Fix bug on commit graph (#15517) (#15530)
-  * Send size to /avatars if requested (#15459) (#15528)
-  * Prevent migration 156 failure if tag commit missing (#15519) (#15527)
-* ENHANCEMENTS
-  * Display conflict-free merge messages for pull requests (#15773) (#15796)
-  * Exponential Backoff for ByteFIFO (#15724) (#15793)
-  * Issue list alignment tweaks (#15483) (#15766)
-  * Implement delete release attachments and update release attachments' name (#14130) (#15666)
-  * Add placeholder text to deploy key textarea (#15575) (#15576)
-  * Project board improvements (#15429) (#15560)
-  * Repo branch page: label size, PR ref, new PR button alignment (#15363) (#15365)
-* MISC
-  * Fix webkit calendar icon color on arc-green (#15713) (#15728)
-  * Performance improvement for last commit cache and show-ref (#15455) (#15701)
-  * Bump unrolled/render to v1.1.0 (#15581) (#15608)
-  * Add ETag header (#15370) (#15552)
-
-## [1.14.1](https://github.com/go-gitea/gitea/releases/tag/v1.14.1) - 2021-04-15
-
-* BUGFIXES
-  * Fix bug clone wiki (#15499) (#15502)
-  * Github Migration ignore rate limit, if not enabled (#15490) (#15495)
-  * Use subdir for URL (#15446) (#15493)
-  * Query the DB for the hash before inserting in to email_hash (#15457) (#15491)
-  * Ensure review dismissal only dismisses the correct review (#15477) (#15489)
-  * Use index of the supported tags to choose user lang (#15452) (#15488)
-  * Fix wrong file link in code search page (#15466) (#15486)
-  * Quick template fix for built-in SSH server in admin config (#15464) (#15481)
-  * Prevent superfluous response.WriteHeader (#15456) (#15476)
-  * Fix ambiguous argument error on tags (#15432) (#15474)
-  * Add created_unix instead of expiry to migration (#15458) (#15463)
-  * Fix repository search (#15428) (#15442)
-  * Prevent NPE on avatar direct rendering if federated avatars disabled (#15434) (#15439)
-  * Fix wiki clone urls (#15430) (#15431)
-  * Fix dingtalk icon url at webhook (#15417) (#15426)
-  * Standardise icon on projects PR page (#15387) (#15408)
-* ENHANCEMENTS
-  * Add option to skip LFS/attachment files for `dump` (#15407) (#15492)
-  * Clone panel fixes (#15436)
-  * Use semantic dropdown for code search query type (#15276) (#15364)
-* BUILD
-  * Build go-git variants for windows (#15482) (#15487)
-  * Lock down build-images dependencies (Partial #15479) (#15480)
-* MISC
-  * Performance improvement for list pull requests (#15447) (#15500)
-  * Fix potential copy lfs records failure when fork a repository (#15441) (#15485)
-
-## [1.14.0](https://github.com/go-gitea/gitea/releases/tag/v1.14.0) - 2021-04-11
-
-* SECURITY
-  * Respect approved email domain list for externally validated user registration (#15014)
-  * Add reverse proxy configuration support for remote IP address detection (#14959)
-  * Ensure validation occurs on clone addresses too (#14994)
-  * Fix several render issues highlighted during fuzzing (#14986)
-* BREAKING
-  * Fix double 'push tag' action feed (#15078) (#15083)
-  * Remove possible resource leak (#15067) (#15082)
-  * Handle unauthorized user events gracefully (#15071) (#15074)
-  * Restore Access.log following migration to Chi framework (Stops access logging of /api/internal routes) (#14475)
-  * Migrate from Macaron to Chi framework (#14293)
-  * Deprecate building for mips (#14174)
-  * Consolidate Logos and update README header (#14136)
-  * Inline manifest.json (#14038)
-  * Store repository data in data path if not previously set (#13991)
-  * Rename "gitea" png to "logo" (#13974)
-  * Standardise logging of failed authentication attempts in internal SSH (#13962)
-  * Add markdown support in organization description (#13549)
-  * Improve users management through the CLI (#6001) (#10492)
-* FEATURES
-  * Create a new issue with reference to lines of code from file view (#14863)
-  * Repository transfer has to be confirmed, if user can not create repo for new owner (#14792)
-  * Allow blocking some email domains from registering an account (#14667)
-  * Create a new issue based on reference to an issue comment (#14366)
-  * Add support to migrate from gogs (#14342)
-  * Add pager to the branches page (#14202)
-  * Minimal OpenID Connect implementation (#14139)
-  * Display current stopwatch in navbar (#14122)
-  * Display SVG files as images instead of text (#14101)
-  * Disable SSH key deletion of externally managed Keys (#13985)
-  * Add support for ed25519_sk and ecdsa_sk SSH keys (#13462)
-  * Add support for Mastodon OAuth2 provider (#13293)
-  * Add gitea sendmail command (#13079)
-  * Create DB session provider(based on xorm) (#13031)
-  * Add dismiss review feature (#12674)
-  * Make manual merge autodetection optional and add manual merge as merge method (#12543)
-  * Dump github/gitlab/gitea repository data to a local directory and restore to gitea (#12244)
-  * Create Rootless Docker image (#10154)
-* API
-  * Speedup issue search (#15179) (#15192)
-  * Get pull, return head branch sha, even if deleted (#14931)
-  * Export LFS & TimeTracking function status (#14753)
-  * Show Gitea version in swagger (#14654)
-  * Fix PATCH /repos/{owner}/{repo} panic (#14637)
-  * Add Restricted Field to User (#14630)
-  * Add support for ref parameter to get raw file API (#14602)
-  * Add affected files of commits to commit struct (#14579)
-  * Fix CJK fonts again and misc. font issues (#14575)
-  * Add delete release by tag & delete tag (#14563) & (#13358)
-  * Add pagination to ListBranches (#14524)
-  * Add signoff option in commit form (#14516)
-  * GetRelease by tag only return release (#14397)
-  * Add MirrorInterval to the API (#14163)
-  * Make BasicAuth Prefix case insensitive (#14106)
-  * Add user filter to issueTrackedTimes, enable usage for issue managers (#14081)
-  * Add ref to create/edit issue options & deprecated assignee (#13992)
-  * Add Ref to Issue (#13946)
-  * Expose default theme in meta and API (#13809)
-  * Send error message when CSRF token is missing (#13676)
-  * List, Check, Add & delete endpoints for repository teams (#13630)
-  * Admin EditUser: Make FullName, Email, Website & Location optional (#13562)
-  * Add more filters to issues search (#13514)
-  * Add review request api (#11355)
-* BUGFIXES
-  * Fix delete nonexist oauth application 500 and prevent deadlock (#15384) (#15396)
-  * Always set the merge base used to merge the commit (#15352) (#15385)
-  * Upgrade to bluemonday 1.0.7 (#15379) (#15380)
-  * Turn RepoRef and RepoAssignment back into func(*Context) (#15372) (#15377)
-  * Move FCGI req.URL.Path fix-up to the FCGI listener (#15292) (#15361)
-  * Show diff on rename with diff changes (#15338) (#15339)
-  * Fix handling of logout event (#15323) (#15337)
-  * Fix CanCreateRepo check (#15311) (#15321)
-  * Fix xorm log stack level (#15285) (#15316)
-  * Fix bug in Wrap (#15302) (#15309)
-  * Drop the event source if we are unauthorized (#15275) (#15280)
-  * Backport Fix graph pagination (#15225)  (#15249)
-  * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15200)
-  * should run RetrieveRepoMetas() for empty pr (#15187) (#15190)
-  * Move setting to enable closing issue via commit in non default branch to repo settings (#14965)
-  * Show correct issues for team dashboard (#14952)
-  * Ensure that new pull request button works on forked forks owned by owner of the root and reduce ambiguity (#14932)
-  * Only allow issue labels from owner repository or organization (#14928)
-  * Fix alignment of People and Teams right arrow on org homepage (#14924)
-  * Fix overdue marking of closed issues and milestones (#14923)
-  * Prevent panic when empty MilestoneID in repo/issue/list (#14911)
-  * Fix migration context data (#14910)
-  * Handle URLs with trailing slash (#14852)
-  * Add CORS config on to /login/oauth/access_token endpoint (#14850)
-  * Make searching issues by keyword case insensitive on DB (#14848)
-  * Prevent use of double sub-path and incorrect asset path in manifest (#14827)
-  * Fix link account ui (#14763)
-  * Fix preview status switch button on wiki editor (#14742)
-  * Fix github download on migration (#14703)
-  * Fix svg spacing (#14638)
-  * Prevent adding nil label to .AddedLabels or .RemovedLabels (#14623)
-  * Truncated organizations name (#14615)
-  * Exclude the current dump file from the dump (#14606)
-  * Use OldRef instead of CommitSHA for DeleteBranch comments (#14604)
-  * Ensure memcache caching works when TTL greater than 30 days (#14592)
-  * Remove NULs byte arrays passed to PostProcess (#14587)
-  * Restore detection of branches are equal on compare page (#14586)
-  * Fix incorrect key name so registerManualConfirm works (#14455)
-  * Fix close/reopen with comment (#14436)
-  * Allow passcode invalid error to appear (#14371)
-  * Escape branch names in compare url (#14364)
-  * Label and milestone webhooks on issue/pull creation (#14363)
-  * Handle NotifyCreateRef as create branch in feeds (#14245)
-  * Prevent clipping input text in Chrome + Segoe UI Font (#14179)
-  * Fix UI on edit auth source page (#14137)
-  * Fix git.parseTagData (#14105)
-  * Refactor get tag to remove unnecessary steps (#14058)
-  * Fix integrations test error with space in CURDIR path (#14056)
-  * Dropdown triangle fixes (#14028)
-  * Fix label of --id in admin delete user (#14005)
-  * Cause NotifyMigrateRepository to emit a repo create webhook (#14004)
-  * Update HEAD to match defaultBranch in template generation (#13948)
-  * Fix action avatar loading (#13909)
-  * Fix issue participants (#13893)
-  * Fix avatar template error (#13833)
-  * Fix review request notification email links when external issue tracker is enabled (#13723)
-  * Fix blame line alignment (#13542)
-  * Include OriginalAuthor in Reaction constraint (#13505)
-  * Comments on review should have the same sha (#13448)
-  * Fix whitespace rendering in diff (#13415)
-  * Fixed git args duplication (#13411)
-  * Fix bug on release publisherid migrations (#13410)
-  * Fix --port setting (#13288)
-  * Keep database transactions not too big (#13254)
-  * Git version check, ignore pre-releases constraints (#13234)
-  * Handle and propagate errors when checking if paths are Dirs, Files or Exist (#13186)
-  * Update Mirror IsEmpty status on synchronize (#13185)
-  * Use GO variable in go-check target (#13146) (#13147)
-* ENHANCEMENTS
-  * UI style improvements
-  * Dropzone styling improvements (#15291) (#15374)
-  * Add size to Save function (#15264) (#15270)
-  * Monaco improvements (#15333) (#15345)
-  * Support .mailmap in code activity stats (#15009)
-  * Sort release attachments by name (#15008)
-  * Add ui.explore settings to control view of explore pages (#14094)
-  * Make internal SSH server host key path configurable (#14918)
-  * Hide resync all ssh principals when using internal ssh server (#14904)
-  * Add SameSite setting for cookies (#14900)
-  * Move Bleve and Elastic code indexers to use a common cat-file --batch (#14781)
-  * Add environment-to-ini to docker image (#14762)
-  * Add preview support for wiki editor when disable simpleMDE (#14757)
-  * Add easyMDE(simpleMDE) support for release content editor (#14744)
-  * Organization removal confirmation using name not password (#14738)
-  * Make branch names in PR description clickable (#14716)
-  * Add Password Algorithm option to install page (#14701)
-  * Add fullTextSearch to dropdowns by default (#14694)
-  * Fix truncated organization names (#14655)
-  * Whitespace in commits (#14650)
-  * Sort / move project boards (#14634)
-  * Make fileheader sticky in diffs (#14616)
-  * Add helper descriptions on new repo page (#14591)
-  * Move the stopwatches to the eventsource stream (#14588)
-  * Add Content-Length header to HEAD requests (#14542)
-  * Add Image Diff options in Diff view (#14450)
-  * Improve Description in new/ edit Project template (#14429)
-  * Allow ssh-keygen on Windows to detect ssh key type (#14413)
-  * Display error if twofaSecret cannot be retrieved (#14372)
-  * Sort issue search results by revelance (#14353)
-  * Implement ghost comment mitigation (#14349)
-  * Upgrade blevesearch dependency to v2.0.1 (#14346)
-  * Add edit, delete and reaction support to code review comments on issue page (#14339)
-  * Merge default and system webhooks under one menu (#14244)
-  * Add option for administrator to reset user 2FA (#14243)
-  * Add option to change username to the admin panel (#14229)
-  * Check for 'main' as potential default branch name (#14193)
-  * Project: show referenced PRs in issue cards (#14183)
-  * Use caddy's certmagic library for extensible/robust ACME handling (#14177)
-  * CLI support for OAuth sources custom icons (#14166)
-  * Custom icons for OAuth sources (#14161)
-  * Team dashboards (#14159)
-  * KanBan: be able to set default board (#14147)
-  * Disable Fomantic's custom scrollbars (#14109)
-  * Add UI to delete tracked times (#14100)
-  * Rework heatmap permissions (#14080)
-  * Issue and pull request filters on organization dashboard (#14072)
-  * Fix webhook list styling (#14001)
-  * Show dropdown with all statuses for commit (#13977)
-  * Show status check for merged PRs (#13975)
-  * Diff stat improvements (#13954)
-  * Report permissions denied in internal SSH (#13953)
-  * Markdown task list improvements (#13952)
-  * Heatmap days clickable (#13935)
-  * chore: use octicon-mirror for feeds display (#13928)
-  * Move diff split code into own template file (#13919)
-  * Markdown: Enable wrapping in code blocks and a color tweak (#13894)
-  * Do not reload page after adding comments in Pull Request reviews (#13877)
-  * Add pull request manually merge instruction (#13840)
-  * add thumbnail preview section to issue attachments (#13826)
-  * Move Repo APIFormat to convert package (#13787)
-  * Move notification APIFormat (#13783)
-  * Swap swagger-ui with swagger-ui-dist (#13777)
-  * User Settings: Ignore empty language codes & validate (#13755)
-  * Improve migrate page and add card CSS (#13751)
-  * Add block on official review requests branch protection (#13705)
-  * Add review requested filter on pull request overview (#13701)
-  * Use chronological commit order in default squash message (#13696)
-  * Clickable links in pull request (and issue) titles (#13695)
-  * Support shortened commit SHAs in URLs (#13686)
-  * Use native git variants by default with go-git variants as build tag (#13673)
-  * Don't render dropdown when only 1 merge style is available (#13670)
-  * Move webhook type from int to string (#13664)
-  * Direct avatar rendering (#13649)
-  * Verify password for local-account activation (#13631)
-  * Prevent clone protocol button flash on page load (#13626)
-  * Remove fetch request from heatmap (#13623)
-  * Refactor combine label comments with tests (#13619)
-  * Move metrics from macaron to chi (#13601)
-  * Issue and Pulls lists rework (#13594)
-  * HTTP cache rework and enable caching for storage assets (#13569)
-  * Use mount but not register for chi routes (#13555)
-  * Use monaco for the git hook editor (#13552)
-  * Make heatmap colors more distinct (#13533)
-  * Lazy-load issue reviewers and assignees avatars (#13526)
-  * Change search and filter icons to SVG (#13473)
-  * Create tag on ui (#13467)
-  * updateSize when create a repo with init commit (#13441)
-  * Added title and action buttons to Project view page (#13437)
-  * Override fomantic monospace fonts and set size (#13435)
-  * Rework focused comment styling (#13434)
-  * Tags cleanup (#13428)
-  * Various style tweaks (#13418)
-  * Refactor push update (#13381)
-  * Comment box tweaks and SVG dropdown triangles (#13376)
-  * Various style fixes (#13372)
-  * Change repo home page icons to SVG (#13364)
-  * Use CSS Vars for primary color (#13361)
-  * Refactor image paste code (#13354)
-  * Switch from SimpleMDE to EasyMDE (#13333)
-  * Group Label Changed Comments in timeline (#13304)
-  * Make the logger an interface (#13294)
-  * Fix PR/Issue titles on mobile (#13292)
-  * Rearrange the order of the merged by etc. in locale (#13284)
-  * Replace footer and modal icons with SVG (#13245)
-  * Issues overview should not show issues from archived repos (#13220)
-  * Show stale label for stale code comment which is marked as resolved (#13213)
-  * Use CSS Variables for fonts, remove postcss-loader (#13204)
-  * Add mentionable teams to tributeValues and change team mention rules to gh's style (#13198)
-  * Move install pages out of main macaron routes (#13195)
-  * Update outdated label to use Fomantic UI style (#13181)
-  * Added option to disable webhooks (#13176)
-  * Change order of possible-owner organizations to alphabetical (#13160)
-  * Log IP on SSH authentication failure for Built-in SSH server (#13150)
-  * Added option to disable migrations (#13114)
-  * New "Add Mirror" Button in the Organization view (#13105)
-  * Manually approve new registration (#13083)
-  * Cron job to cleanup hook_task table (#13080)
-  * Use the headline comment of pull-request as the squash commit's message (#13071)
-  * Clarify the suffices and prefixes of setting.AppSubURL and setting.AppURL (#12999)
-  * Slightly simplify the queue settings code to help reduce the risk of problems (#12976)
-  * Add precise search type for Elastic Search (#12869)
-  * Move APIFormat functions into convert package (#12856)
-  * Multiple GitGraph improvements: Exclude PR heads, Add branch/PR links, Show only certain branches, (#12766)
-  * Add TrN for repository limit (#12492)
-  * Refactor doctor (#12264)
-  * Add the tag list page to the release page (#12096)
-  * Redirect on changed user and org name (#11649)
-  * load U2F js only on pages which need it (#11585)
-  * Make archival asynchronous (#11296)
-  * Introduce go chi web framework as frontend of macaron, so that we can move routes from macaron to chi step by step (#7420)
-  * Improve vfsgen to not unzip bindata files but send to browser directly (#7109)
-  * Enhance release list (#6025)
-* DOCS
-  * Swagger show models by default (#14880)
-  * Add missing repo.projects unit into swagger (#14876)
-  * Update docs and comments to remove macaron (#14491)
-  * Issue template addition: Are you using Gitea behind CloudFlare? (#14098)
-  * Generate man pages (#13901)
-  * Reformat/fine-tune docs (#13897)
-  * Added Table of Contents to long documentation pages (#13890)
-  * Add docs command (#13429)
-  * Update external-renderers.en-us.md (#13165)
-* MISC
-  * Add builds for apple M1 (darwin arm64) (#14951)
-  * Migrate to use jsoniter instead of encoding/json (#14841)
-  * Reduce make verbosity (#13803)
-  * Add git command error directory on log (#13194)
-
-## [1.13.7](https://github.com/go-gitea/gitea/releases/tag/v1.13.7) - 2021-04-07
-
-* SECURITY
-  * Update to bluemonday-1.0.6 (#15294) (#15298)
-  * Clusterfuzz found another way (#15160) (#15169)
-* API
-  * Fix wrong user returned in API (#15139) (#15150)
-* BUGFIXES
-  * Add 'fonts' into 'KnownPublicEntries' (#15188) (#15317)
-  * Speed up `enry.IsVendor` (#15213) (#15246)
-  * Response 404 for diff/patch of a commit that not exist (#15221) (#15238)
-  * Prevent NPE in CommentMustAsDiff if no hunk header (#15199) (#15201)
-* MISC
-  * Add size to Save function (#15264) (#15271)
-
-## [1.13.6](https://github.com/go-gitea/gitea/releases/tag/v1.13.6) - 2021-03-23
-
-* SECURITY
-  * Fix bug on avatar middleware (#15124) (#15125)
-  * Fix another clusterfuzz identified issue (#15096) (#15114)
-* API
-  * Fix nil exeption for get pull reviews API #15104 (#15106)
-* BUGFIXES
-  * Fix markdown rendering in milestone content (#15056) (#15092)
-
-## [1.13.5](https://github.com/go-gitea/gitea/releases/tag/v1.13.5) - 2021-03-21
-
-* SECURITY
-  * Update to goldmark 1.3.3 (#15059) (#15061)
-  * Another clusterfuzz spotted issue (#15032) (#15034)
-* API
-  * Fix set milestone on PR creation (#14981) (#15001)
-  * Prevent panic when editing forked repos by API (#14960) (#14963)
-* BUGFIXES
-  * Fix bug when upload on web (#15042) (#15055)
-  * Delete Labels & IssueLabels on Repo Delete too (#15039) (#15051)
-  * Fix postgres ID sequences broken by recreate-table (#15015) (#15029)
-  * Fix several render issues (#14986) (#15013)
-  * Make sure sibling images get a link too (#14979) (#14995)
-  * Fix Anchor jumping with escaped query components (#14969) (#14977)
-  * Fix release mail html template (#14976)
-  * Fix excluding more than two labels on issues list (#14962) (#14973)
-  * Don't mark each comment poster as OP (#14971) (#14972)
-  * Add "captcha" to list of reserved usernames (#14930)
-  * Re-enable import local paths after reversion from #13610 (#14925) (#14927)
-
-## [1.13.4](https://github.com/go-gitea/gitea/releases/tag/v1.13.4) - 2021-03-07
-
-* SECURITY
-  * Fix issue popups (#14898) (#14899)
-* BUGFIXES
-  * Fix race in LFS ContentStore.Put(...) (#14895) (#14913)
-  * Fix a couple of issues with a feeds (#14897) (#14903)
-  * When transfering repository and database transaction failed, rollback the renames (#14864) (#14902)
-  * Fix race in local storage (#14888) (#14901)
-  * Fix 500 on pull view page if user is not loged in (#14885) (#14886)
-* DOCS
-  * Fix how lfs data path is set (#14855) (#14884)
-
-## [1.13.3](https://github.com/go-gitea/gitea/releases/tag/v1.13.3) - 2021-03-04
-
-* BREAKING
-  * Turn default hash password algorithm back to pbkdf2 from argon2 until we find a better one (#14673) (#14675)
-* BUGFIXES
-  * Fix paging of file commit logs (#14831) (#14879)
-  * Print useful error if SQLite is used in settings but not supported (#14476) (#14874)
-  * Fix display since time round (#14226) (#14873)
-  * When Deleting Repository only explicitly close PRs whose base is not this repository (#14823) (#14842)
-  * Set HCaptchaSiteKey on Link Account pages (#14834) (#14839)
-  * Fix a couple of CommentAsPatch issues.  (#14804) (#14820)
-  * Disable broken OAuth2 providers at startup (#14802) (#14811)
-  * Repo Transfer permission checks (#14792) (#14794)
-  * Fix double alert in oauth2 application edit view (#14764) (#14768)
-  * Fix broken spans in diffs (#14678) (#14683)
-  * Prevent race in PersistableChannelUniqueQueue.Has (#14651) (#14676)
-  * HasPreviousCommit causes recursive load of commits unnecessarily (#14598) (#14649)
-  * Do not assume all 40 char strings are SHA1s (#14624) (#14648)
-  * Allow org labels to be set with issue templates (#14593) (#14647)
-  * Accept multiple SSH keys in single LDAP SSHPublicKey attribute (#13989) (#14607)
-  * Fix bug about ListOptions and stars/watchers pagnation (#14556) (#14573)
-  * Fix GPG key deletion during account deletion (#14561) (#14569)
-
-## [1.13.2](https://github.com/go-gitea/gitea/releases/tag/v1.13.2) - 2021-01-31
-
-* SECURITY
-  * Prevent panic on fuzzer provided string (#14405) (#14409)
-  * Add secure/httpOnly attributes to the lang cookie (#14279) (#14280)
-* API
-  * If release publisher is deleted use ghost user (#14375)
-* BUGFIXES
-  * Internal ssh server respect Ciphers, MACs and KeyExchanges settings (#14523) (#14530)
-  * Set the name Mapper in migrations (#14526) (#14529)
-  * Fix wiki preview (#14515)
-  * Update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 (#14497)
-  * ChangeUserName: rename user files back on DB issue (#14447)
-  * Fix lfs preview bug (#14428) (#14433)
-  * Ensure timeout error is shown on u2f timeout (#14417) (#14431)
-  * Fix Deadlock & Delete affected reactions on comment deletion (#14392) (#14425)
-  * Use path not filepath in routers/editor (#14390) (#14396)
-  * Check if label template exist first (#14384) (#14389)
-  * Fix migration v141 (#14387) (#14388)
-  * Use Request.URL.RequestURI() for fcgi (#14347)
-  * Use ServerError provided by Context (#14333) (#14345)
-  * Fix edit-label form init (#14337)
-  * Fix mailIssueCommentBatch for pull request (#14252) (#14296)
-  * Render links for commit hashes followed by comma (#14224) (#14227)
-  * Send notifications for mentions in pulls, issues, (code-)comments (#14218) (#14221)
-  * Fix avatar bugs (#14217) (#14220)
-  * Ensure that schema search path is set with every connection on postgres (#14131) (#14216)
-  * Fix dashboard issues labels filter bug (#14210) (#14214)
-  * When visit /favicon.ico but the static file is not exist return 404 but not continue to handle the route (#14211) (#14213)
-  * Fix branch selector on new issue page (#14194) (#14207)
-  * Check for notExist on profile repository page (#14197) (#14203)
-
-## [1.13.1](https://github.com/go-gitea/gitea/releases/tag/v1.13.1) - 2020-12-29
-
-* SECURITY
-  * Hide private participation in Orgs (#13994) (#14031)
-  * Fix escaping issue in diff (#14153) (#14154)
-* BUGFIXES
-  * Fix bug of link query order on markdown render (#14156) (#14171)
-  * Drop long repo topics during migration (#14152) (#14155)
-  * Ensure that search term and page are not lost on adoption page-turn (#14133) (#14143)
-  * Fix storage config implementation (#14091) (#14095)
-  * Fix panic in BasicAuthDecode (#14046) (#14048)
-  * Always wait for the cmd to finish (#14006) (#14039)
-  * Don't use simpleMDE editor on mobile devices for 1.13 (#14029)
-  * Fix incorrect review comment diffs (#14002) (#14011)
-  * Trim the branch prefix from action.GetBranch (#13981) (#13986)
-  * Ensure template renderer is available before storage handler (#13164) (#13982)
-  * Whenever the password is updated ensure that the hash algorithm is too (#13966) (#13967)
-  * Enforce setting HEAD in wiki to master (#13950) (#13961)
-  * Fix feishu webhook caused by API changed (#13938)
-  * Fix Quote Reply button on review diff (#13830) (#13898)
-  * Fix Pull Merge when tag with same name as base branch exist (#13882) (#13896)
-  * Fix mermaid chart size (#13865)
-  * Fix branch/tag notifications in mirror sync (#13855) (#13862)
-  * Fix crash in short link processor (#13839) (#13841)
-  * Update font stack to bootstrap's latest (#13834) (#13837)
-  * Make sure email recipients can see issue (#13820) (#13827)
-  * Reply button is not removed when deleting a code review comment (#13824)
-  * When reinitialising DBConfig reset the database use flags (#13796) (#13811)
-* ENHANCEMENTS
-  * Add emoji in label to project boards (#13978) (#14021)
-  * Send webhook when tag is removed via Web UI (#14015) (#14019)
-  * Use Process Manager to create own Context (#13792) (#13793)
-* API
-  * GetCombinedCommitStatusByRef always return json & swagger doc fixes (#14047)
-  * Return original URL of Repositories (#13885) (#13886)
-
-## [1.13.0](https://github.com/go-gitea/gitea/releases/tag/v1.13.0) - 2020-12-01
-
-* SECURITY
-  * Add Allow-/Block-List for Migrate & Mirrors (#13610) (#13776)
-  * Prevent git operations for inactive users (#13527) (#13536)
-  * Disallow urlencoded new lines in git protocol paths if there is a port (#13521) (#13524)
-  * Mitigate Security vulnerability in the git hook feature (#13058)
-  * Disable DSA ssh keys by default (#13056)
-  * Set TLS minimum version to 1.2 (#12689)
-  * Use argon as default password hash algorithm (#12688)
-* BREAKING
-  * Set RUN_MODE prod by default (#13765) (#13767)
-  * Don't replace underscores in auto-generated IDs in goldmark (#12805)
-  * Add Primary Key to Topic and RepoTopic tables (#12639)
-  * Disable password complexity check default (#12557)
-  * Change PIDFile default from /var/run/gitea.pid to /run/gitea.pid (#12500)
-  * Add extension Support to Attachments (allow all types for releases) (#12465)
-  * Remove IE11 Support (#11470)
-* FEATURES
-  * Adopt repositories (#12920)
-  * Check passwords against HaveIBeenPwned (#12716)
-  * Gitea 2 Gitea migration (#12657)
-  * Support storing Avatars in minio  (#12516)
-  * Allow addition of gpg keyring with multiple keys (#12487)
-  * Add email notify for new release (#12463)
-  * Add Access-Control-Expose-Headers (#12446)
-  * UserProfile Page: Render Description (#12415)
-  * Add command to recreate tables (#12407)
-  * Add mermaid JS renderer (#12334)
-  * Add ssh certificate support (#12281)
-  * Add spent time to referenced issue in commit message (#12220)
-  * Initial support for push options (#12169)
-  * Provide option to unlink a fork (#11858)
-  * Show exact tag for commit on diff view (#11846)
-  * Pause, Resume, Release&Reopen, Add and Remove Logging from command line (#11777)
-  * Issue templates directory (#11450)
-  * Add a storage layer for attachments (#11387)
-  * Add hide activity option (#11353)
-  * Add push commits history comment on PR time-line (#11167)
-  * Support elastic search for code search (#10273)
-  * Kanban board (#8346)
-* API
-  * If User is Admin, show 500 error message on PROD mode too (#13115)
-  * Add Timestamp to Tag list API (#13026)
-  * Return sample message for login error in api context (#12994)
-  * Add IsTemplate option in create repo ui and api (#12942)
-  * GetReleaseByID return 404 if not found (#12933)
-  * Get release by tags endpoint (#12932)
-  * NotificationSubject show Issue/Pull State (#12901)
-  * Expose its limitation settings (#12714)
-  * Add Created & Updated to Milestone (#12662)
-  * Milestone endpoints accept names too (#12649)
-  * Expose Attachment Settings in the API (#12514)
-  * Add Issue and Repo info to StopWatch (#12458)
-  * Add cron running API (#12421)
-  * Add Update Pull HeadBranch Function (#12419)
-  * Add TOTP header to Swagger Documentation (#12402)
-  * Delete Token accept names too (#12366)
-  * Add name filter for GetMilestoneList (#12336)
-  * Fixed count of filtered issues when api request. (#12275)
-  * Do not override API issue pagination with UI settings (#12068)
-  * Expose useful General Repo settings settings (#11758)
-  * Return error when trying to create Mirrors but Mirrors are globally disabled (#11757)
-  * Provide diff and patch API endpoints (#11751)
-  * Allow to create closed milestones (#11745)
-  * Add language Statistics endpoint (#11737)
-  * Add Endpoint to get GetGeneralUI Settings (#11735) & (#11854)
-  * Issue/Pull expose IsLocked Property on API (#11708)
-  * Add endpoint for Branch Creation (#11607)
-  * Add pagination headers on endpoints that support total count from database (#11145)
-* BUGFIXES
-  * Fix bogus http requests on diffs (#13760) (#13761)
-  * Show 'owner' tag for real owner (#13689) (#13743)
-  * Validate email before inserting/updating (#13475) (#13666)
-  * Fix issue/pull request list assignee filter (#13647) (#13651)
-  * Gitlab migration support for subdirectories (#13563) (#13591)
-  * Fix logic for preferred license setting (#13550) (#13557)
-  * Add missed sync branch/tag webhook (#13538) (#13556)
-  * Migration won't fail on non-migrated reactions (#13507)
-  * Fix Italian language file parsing error (#13156)
-  * Show outdated comments in pull request (#13148) (#13162)
-  * Fix parsing of pre-release git version (#13169) (#13172)
-  * Fix diff skipping lines (#13154) (#13155)
-  * When handling errors in storageHandler check underlying error (#13178) (#13193)
-  * Fix size and clickable area on file table back link (#13205) (#13207)
-  * Add better error checking for inline html diff code (#13251)
-  * Fix initial commit page & binary munching problem (#13249) (#13258)
-  * Fix migrations from remote Gitea instances when configuration not set (#13229) (#13273)
-  * Store task errors following migrations and display them (#13246) (#13287)
-  * Fix bug isEnd detection on getIssues/getPullRequests (#13299) (#13301)
-  * When the git ref is unable to be found return broken pr (#13218) (#13303)
-  * Ensure topics added using the API are added to the repository (#13285) (#13302)
-  * Fix avatar autogeneration (#13233) (#13282)
-  * Add migrated pulls to pull request task queue (#13331) (#13334)
-  * Issue comment reactions should also check pull type on API (#13349) (#13350)
-  * Fix links to repositories in /user/setting/repos (#13360) (#13362)
-  * Remove obsolete change of email on profile page (#13341) (#13347)
-  * Fix scrolling to resolved comment anchors (#13343) (#13371)
-  * Storage configuration support `[storage]` (#13314) (#13379)
-  * When creating line diffs do not split within an html entity (#13357) (#13375) (#13425) (#13427)
-  * Fix reactions on code comments (#13390) (#13401)
-  * Add missing full names when DEFAULT_SHOW_FULL_NAME is enabled (#13424)
-  * Replies to outdated code comments should also be outdated (#13217) (#13433)
-  * Fix panic bug in handling multiple references in commit (#13486) (#13487)
-  * Prevent panic on git blame by limiting lines to 4096 bytes at most (#13470) (#13491)
-  * Show original author's reviews on pull summary box (#13127)
-  * Update golangci-lint to version 1.31.0 (#13102)
-  * Fix line break for MS teams webhook (#13081)
-  * Fix Issue & Pull Request comment headers on mobile (#13039)
-  * Avoid setting the CONN_STR in queues unless it is meant to be set (#13025)
-  * Remove code-view class from diff view (#13011)
-  * Fix the color of PR comment hyperlinks. (#13009)
-  * (Re)Load issue labels when changing them (#13007)
-  * Fix Media links in org files not liked to media files (#12997)
-  * Always return a list from GetCommitsFromIDs (#12981)
-  * Only set the user password if the password field would have been shown (#12980)
-  * Fix admin/config page (#12979)
-  * Changed width of commit signature avatar (#12961)
-  * Completely quote AppPath and CustomConf paths (#12955)
-  * Fix handling of migration errors (#12928)
-  * Fix anonymous GL migration (#12862)
-  * Fix git open close bug (#12834)
-  * Fix markdown meta parsing (#12817)
-  * Add default storage configurations (#12813)
-  * Show PR settings on empty repos (#12808)
-  * Disable watch and star if not signed in (#12807)
-  * Whilst changing the character set to utf8mb4 we should set ROW_FORMAT=dynamic too (#12804)
-  * Set opengraph attributes on org pages (#12803)
-  * Return error when creating gitlabdownloader failed (#12790)
-  * Add migration for password algorithm change (#12784)
-  * Compare SSH_DOMAIN when parsing submodule URLs (#12753)
-  * Fix editor.commit_empty_file_text locale string (#12744)
-  * Fix wrong poster message for code comment on Pull view (#11721)
-  * Escape failed highlighted files (#12685)
-  * Ensure that all migration requests are cancellable (#12669)
-  * Ensure RepoPath is lowercased in gitea serv (#12668)
-  * Do not disable commit changes button on repost (#12644)
-  * Dark theme for line numbers in blame view (#12632)
-  * Fix message when deleting last owner from an organization (#12628)
-  * Use shellquote to unpack arguments to gitea serv (#12624)
-  * Fix signing.wont_sign.%!s() if Require Signing commits but not signed in. (#12581)
-  * Set utf8mb4 as the default charset on MySQL if CHARSET is unset (#12563)
-  * Set context for running CreateArchive to that of the request (#12555)
-  * Prevent redirect back to /user/events (#12462)
-  * Re-attempt to delete temporary upload if the file is locked by another process (#12447)
-  * Mirror System Notice reports are too frequent (#12438)
-  * Do not show arrows on comment diffs on pull comment pages (#12434)
-  * Fix milestone links (#12405)
-  * Increase size of the language column in language_stat (#12396)
-  * Use transaction in V102 migration (#12395)
-  * Only use --exclude on name-rev with git >= 2.13 (#12347)
-  * Add action feed for new release (#12324)
-  * Set NoAutoTime when updating is_archived (#12266)
-  * Support Force-update in Mirror and improve Tracing in mirror (#12242)
-  * Avoid sending "0 new commits" webhooks (#12212)
-  * Fix U2F button icon (#12167)
-  * models/repo_sign.go: break out of loops (#12159)
-  * Ensure that git commit tree continues properly over the page (#12142)
-  * Rewrite GitGraph.js (#12137)
-  * Fix repo API listing stability (#12057)
-  * Add team support for review request (#12039)
-  * Fix 500 error on repos with no tags (#11870)
-  * Fix nil pointer in default issue mail template (#11862)
-  * Fix commit search in all branches (#11849)
-  * Don't consider tag refs as valid for branch name (#11847)
-  * Don't add same line code comment box twice (#11837)
-  * Fix visibility of forked public repos from private orgs (#11717)
-  * Fix chardet test and add ordering option (#11621)
-  * Fix number of files, total additions, and deletions on Diff pages (#11614)
-  * Properly handle and return empty string for dangling commits in GetBranchName (#11587)
-  * Include query in sign in redirect (#11579)
-  * Fix Enter not working in SimpleMDE (#11564)
-  * Fix bug about can't skip commits base on base branch (#11555)
-* ENHANCEMENTS
-  * Only Return JSON for responses (#13511) (#13565)
-  * Use existing analyzer module for language detection for highlighting (#13522) (#13551)
-  * Return the full rejection message and errors in flash errors (#13221) (#13237)
-  * Remove PAM from auth dropdown when unavailable (#13276) (#13281)
-  * Add HostCertificate to sshd_config in Docker image (#13143)
-  * Save TimeStamps for Star, Label, Follow, Watch and Collaboration to Database (#13124)
-  * Improve error feedback for duplicate deploy keys (#13112)
-  * Set appropriate `autocomplete` attributes on password fields (#13078)
-  * Adding visual cue for "Limited" & "Private" organizations. (#13040)
-  * Fix Pull Request merge buttons on mobile (#13035)
-  * Gitea serv, hooks, manager and the like should always display Fatals (#13032)
-  * CSS tweaks to warning/error segments and misc fixes (#13024)
-  * Fix formatting of branches ahead-behind on narrow windows (#12989)
-  * Add config option to make create-on-push repositories public by default (#12936)
-  * Disable migration items when mirror is selected (#12918)
-  * Add the checkbox quick button to the comment tool bar also (#12885)
-  * Support GH enterprise (#12863)
-  * Simplify CheckUnitUser logic (#12854)
-  * Fix background of signed-commits on arc-green of timeline commits (#12837)
-  * Move git update-server-info to hooks (#12826)
-  * Add ui style for "Open a blank issue" button (#12824)
-  * Use a simple format for the big number on ui (#12822)
-  * Make SVG size argument optional (#12814)
-  * Add placeholder text for bio profile text form (#12792)
-  * Set language via AJAX (#12785)
-  * Show git-pull-request icon for closed pull request (#12742)
-  * Migrate version parsing library to hashicorp/go-version (#12719)
-  * Only use async pre-empt hack if go < 1.15 (#12718)
-  * Inform user about meaning of an hourglass on reviews (#12713)
-  * Add a migrate service type switch page (#12697)
-  * Migrations: Gitlab Add Reactions Support for Issues & MergeRequests (#12695)
-  * Remove duplicate logic in initListSubmits (#12660)
-  * Set avatar image dimensions (#12654)
-  * Rename models.ProtectedBranchRepoID/PRID to models.EnvRepoID/PRID and ensure EnvPusherEmail is set (#12646)
-  * Set setting.AppURL as GITEA_ROOT_URL environment variable during pushes (#12752)
-  * Add postgres schema to the search_path on database connection (#12634)
-  * Git migration UX improvements (#12619)
-  * Add link to home page on swagger ui (#12601)
-  * hCaptcha Support (#12594)
-  * OpenGraph: use repo avatar if exist (#12586)
-  * Reaction picker display improvements (#12576)
-  * Fix emoji replacements, make emoji images consistent (#12567)
-  * Increase clickable area on files table links (#12553)
-  * Set z-index for sticky diff box lower (#12537)
-  * Report error if API merge is not allowed (#12528)
-  * LFS support to be stored on minio (#12518)
-  * Show 2FA info on Admin Pannel: Users List (#12515)
-  * Milestone Issue/Pull List: Add octicons type (#12499)
-  * Make dashboard newsfeed list length a configurable item (#12469)
-  * Add placeholder text for send testing email button in admin/config (#12452)
-  * Add SVG favicon (#12437)
-  * In issue comments, put issue participants also in completion list when hitting @ (#12433)
-  * Collapse Swagger UI tags by default (#12428)
-  * Detect full references to issues and pulls in commit messages (#12399)
-  * Allow common redis and leveldb connections (#12385)
-  * Don't use legacy method to send Matrix Webhook (#12348)
-  * Remove padding/border-radius on image diffs (#12346)
-  * Render the git graph on the server (#12333)
-  * Fix clone panel in wiki position not always align right (#12326)
-  * Rework 'make generate-images' (#12316)
-  * Refactor webhook payload convertion (#12310)
-  * Move jquery-minicolors to npm/webpack (#12305)
-  * Support use nvarchar for all varchar columns when using mssql (#12269)
-  * Update Octicons to v10 (#12240)
-  * Disable search box autofocus (#12229)
-  * Replace code fold icons with octicons (#12222)
-  * Ensure syntax highlighting is the same inside diffs (#12205)
-  * Auto-init repo on license, .gitignore select (#12202)
-  * Default to showing closed Issues/PR list when there are only closed issues/PRs (#12200)
-  * Enable cloning via Git Wire Protocol v2 over HTTP (#12170)
-  * Direct SVG rendering (#12157)
-  * Improve arc-green code colors (#12111)
-  * Allow admin to merge pr with protected file changes (#12078)
-  * Show description on individual milestone view (#12055)
-  * Update the wiki repository remote origin while update the mirror repository's Clone From URL (#12053)
-  * Server-side syntax highlighting for all code (#12047)
-  * Use Fomantic's fluid padded for blame full width (#12023)
-  * Use custom SVGs for commit signing lock icon (#12017)
-  * Make tabs smaller (#12003)
-  * Fix sticky diff stats container (#12002)
-  * Move fomantic and jQuery to main webpack bundle (#11997)
-  * Use enry language type to detect special languages (#11974)
-  * Use only first line of commit when creating referenced comment (#11960)
-  * Rename custom/conf/app.ini.sample to custom/conf/app.example.ini for better syntax light on editor (#11926)
-  * Fix double divider on issue sidebar (#11919)
-  * Shorten markdown heading anchors links (#11903)
-  * Add org avatar on top of internal repo icon (#11895)
-  * Use label to describe repository type (#11891)
-  * Make repository size unclickable on repo summary bar (#11887)
-  * Rework blame template and styling (#11885)
-  * Fix icon alignment for show/hide outdated link on resolved conversation (#11881)
-  * Vertically align review icons on repository sidebar (#11880)
-  * Better align items using flex within review request box (#11879)
-  * Only write to global gitconfig if necessary (#11876)
-  * Disable all typographic replacements in markdown renderer (#11871)
-  * Improve label edit buttons labels (#11841)
-  * Use crispEdges rendering for octicon-internal-repo (#11801)
-  * Show update branch item in merge box when it's necessary (#11761)
-  * Add compare link to releases (#11752)
-  * Allow site admin to disable mirrors (#11740)
-  * Export monaco editor on window.codeEditors (#11739)
-  * Add configurable Trust Models (#11712)
-  * Show full GPG commit status on PR commit history (#11702)
-  * Fix align issues and decrease avatar size on PR timeline (#11689)
-  * Replace jquery-datetimepicker with native date input (#11684)
-  * Change Style of Tags on Comments (#11668)
-  * Fix missing styling for shabox on PR commit history (#11625)
-  * Apply padding to approval icons on PR list (#11622)
-  * Fix message wrapping on PR commit list (#11616)
-  * Right-align status icon on pull request commit history (#11594)
-  * Add missing padding for multi-commit list on PR view (#11593)
-  * Do not show avatar for "{{user}} added X commits" (#11591)
-  * Fix styling and padding for commit list on PR view (#11588)
-  * Style code review comment for arc-green (#11572)
-  * Use default commit message for wiki edits (#11550)
-  * Add internal-repo octicon for public repos of private org (#11529)
-  * Fix dropzone color on arc-green (#11514)
-  * Insert ui divider directly in templates instead of from inside heatmap vue component (#11508)
-  * Move tributejs to npm/webpack (#11497)
-  * Fix text-transform on wiki revisions page (#11486)
-  * Do not show lock icon on repo list for public repos in private org (#11445)
-  * Include LFS when calculating repo size (#11060)
-  * Add check for LDAP group membership (#10869)
-  * When starting new stopwatch stop previous if it is still running (#10533)
-  * Add queue for code indexer (#10332)
-  * Move all push update operations to a queue (#10133)
-  * Cache last commit when pushing for big repository (#10109)
-  * Change/remove a branch of an open issue (#9080)
-  * Sortable Tables Header By Click (#7980)
-* TESTING
-  * Use community codecov drone plugin (#12468)
-  * Add more tests for diff highlighting (#12467)
-  * Don't put integration test data outside of test folder (#11746)
-  * Add debug option to hooks (#11624)
-  * Log slow tests (#11487)
-* TRANSLATION
-  * Translate two small lables on commit statuse list (#12821)
-  * Make issues.force_push_codes message shorter (#11575)
-* BUILD
-  * Bump min required golang to 1.13 (#12717)
-  * Add 'make watch' (#12636)
-  * Extract Swagger CSS to its own file (#12616)
-  * Update eslint config (#12609)
-  * Avoid unnecessary system-ui expansion (#12522)
-  * Make the default PID file compile-time settable (#12485)
-  * Add 'watch-backend' (#12330)
-  * Detect version of sed in Makefile (#12319)
-  * Update gitea-vet to v0.2.1 (#12282)
-  * Add logic to build stable and edge builds for gitea snap (#12052)
-  * Fix missing CGO_EXTRA_FLAGS build arg for docker (#11782)
-  * Alpine 3.12 (#11720)
-  * Enable stylelint's shorthand-property-no-redundant-values (#11436)
-* DOCS
-  * Change default log configuration (#13088)
-  * Add automatic JS license generation (#11810)
-  * Remove page size limit comment from swagger (#11806)
-  * Narrow down Edge version in browser support docs (#11640)
-
-## [1.12.5](https://github.com/go-gitea/gitea/releases/tag/v1.12.5) - 2020-10-01
-
-* BUGFIXES
-  * Allow U2F with default settings for gitea in subpath (#12990) (#13001)
-  * Prevent empty div when editing comment (#12404) (#12991)
-  * On mirror update also update address in DB (#12964) (#12967)
-  * Allow extended config on cron settings (#12939) (#12943)
-  * Open transaction when adding Avatar email-hash pairs to the DB (#12577) (#12940)
-  * Fix internal server error from ListUserOrgs API (#12910) (#12915)
-  * Update only the repository columns that need updating (#12900) (#12912)
-  * Fix panic when adding long comment (#12892) (#12894)
-  * Add size limit for content of comment on action ui (#12881) (#12890)
-  * Convert User expose ID each time (#12855) (#12883)
-  * Support slashes in release tags (#12864) (#12882)
-  * Add missing information to CreateRepo API endpoint (#12848) (#12867)
-  * On Migration respect old DefaultBranch (#12843) (#12858)
-  * Fix notifications page links (#12838) (#12853)
-  * Stop cloning unnecessarily on PR update (#12839) (#12852)
-  * Escape more things that are passed through str2html (#12622) (#12850)
-  * Remove double escape on labels addition in comments (#12809) (#12810)
-  * Fix "only mail on mention" bug (#12775) (#12789)
-  * Fix yet another bug with diff file names (#12771) (#12776)
-  * RepoInit Respect AlternateDefaultBranch (#12746) (#12751)
-  * Fix Avatar Resize (resize algo NearestNeighbor -> Bilinear) (#12745) (#12750)
-* ENHANCEMENTS
-  * gitea dump: include version & Check InstallLock (#12760) (#12762)
-
-## [1.12.4](https://github.com/go-gitea/gitea/releases/tag/v1.12.4) - 2020-09-02
-
-* SECURITY
-  * Escape provider name in oauth2 provider redirect (#12648) (#12650)
-  * Escape Email on password reset page (#12610) (#12612)
-  * When reading expired sessions - expire them (#12686) (#12690)
-* ENHANCEMENTS
-  * StaticRootPath configurable at compile time (#12371) (#12652)
-* BUGFIXES
-  * Fix to show an issue that is related to a deleted issue (#12651) (#12692)
-  * Expire time acknowledged for cache (#12605) (#12611)
-  * Fix diff path unquoting (#12554) (#12575)
-  * Improve HTML escaping helper (#12562)
-  * models: break out of loop (#12386) (#12561)
-  * Default empty merger list to those with write permissions (#12535) (#12560)
-  * Skip SSPI authentication attempts for /api/internal (#12556) (#12559)
-  * Prevent NPE on commenting on lines with invalidated comments (#12549) (#12550)
-  * Remove hardcoded ES indexername (#12521) (#12526)
-  * Fix bug preventing transfer to private organization (#12497) (#12501)
-  * Keys should not verify revoked email addresses (#12486) (#12495)
-  * Do not add prefix on http/https submodule links (#12477) (#12479)
-  * Fix ignored login on compare (#12476) (#12478)
-  * Fix incorrect error logging in Stats indexer and OAuth2 (#12387) (#12422)
-  * Upgrade google/go-github to v32.1.0 (#12361) (#12390)
-  * Render emoji's of Commit message on feed-page (#12373)
-  * Fix handling of diff on unrelated branches when Git 2.28 used (#12370)
-
-## [1.12.3](https://github.com/go-gitea/gitea/releases/tag/v1.12.3) - 2020-07-28
-
-* BUGFIXES
-  * Don't change creation date when updating Release (#12343) (#12351)
-  * Show 404 page when release not found (#12328) (#12332)
-  * Fix emoji detection in certain cases (#12320) (#12327)
-  * Reduce emoji size (#12317) (#12327)
-  * Fix double-indirection bug in logging IDs (#12294) (#12308)
-  * Link to pull list page on sidebar when view pr (#12256) (#12263)
-  * Extend Notifications API and return pinned notifications by default (#12164) (#12232)
-
-## [1.12.2](https://github.com/go-gitea/gitea/releases/tag/v1.12.2) - 2020-07-11
-
-* BUGFIXES
-  * When deleting repository decrese user repository count in cache (#11954) (#12188)
-  * Return full commit message instead of summary in commits API (#12186) (#12187)
-  * Properly set HEAD when a repo is created with a default branch that is not named 'master' (#12135) (#12182)
-  * Ensure GPG Subkeys are verified (#12155) (#12168)
-  * Fix failing to cache last commit with key being to long (#12151) (#12161)
-  * Multiple small admin dashboard fixes (#12153) (#12156)
-  * Remove spurious logging of " Delete all repository archives" at startup (#12139) (#12148)
-  * Fix repository setup instructions when default branch is not named 'master' (#12122) (#12147)
-  * Move EventSource to SharedWorker (#12095) (#12130)
-  * Fix ui bug in wiki commit page (#12089) (#12125)
-  * Fix gitgraph branch continues after merge (#12044) (#12105)
-  * Set the base url when migrating from Gitlab using access token or username without password (#11852) (#12104)
-  * Ensure BlameReaders close at end of request (#12102) (#12103)
-  * Fix panic when adding review comment (#12058)
-* ENHANCEMENTS
-  * Disable dropzone's timeout for file uploads (#12024) (#12032)
-
-## [1.12.1](https://github.com/go-gitea/gitea/releases/tag/v1.12.1) - 2020-06-21
-
-* BUGFIXES
-  * Handle multiple merges in gitgraph.js (#11996) (#12000)
-  * Add serviceworker.js to KnownPublicEntries (#11992) (#11994)
-  * For language detection do not try to analyze big files by content (#11971) (#11975)
-* ENHANCEMENTS
-  * Fix scrollable header on dropdowns (#11893) (#11965)
-
-## [1.11.8](https://github.com/go-gitea/gitea/releases/tag/v1.11.8) - 2020-06-21
-
-* BUGFIXES
-  * Really fix __webpack_public_path__ for 1.11 (#11961)
-
-## [1.12.0](https://github.com/go-gitea/gitea/releases/tag/v1.12.0) - 2020-06-17
-
-* BREAKING
-  * When using API CreateRelease set created_unix to the tag commit time (#11218)
-  * Enable ENABLE_HARD_LINE_BREAK by default for rendering markdown (#11162)
-  * Fix sanitizer config - multiple rules (#11133)
-  * Remove check on username when using AccessToken authentication for the API (#11015)
-  * Return 404 from Contents API when items don't exist (#10323)
-  * Notification API should always return a JSON object with the current count of notifications (#10059)
-  * Remove migration support from versions earlier than 1.6.0 (#10026)
-* SECURITY
-  * Use -1 to disable key algorithm type in ssh.minimum_key_sizes (#11635) (#11662)
-* FEATURES
-  * Improve config logging when WrappedQueue times out (#11174)
-  * Add branch delete to API (#11112)
-  * Use markdown frontmatter to provide Table of contents, language and frontmatter rendering (#11047)
-  * Add a way to mark Conversation (code comment) resolved (#11037)
-  * Handle yaml frontmatter in markdown (#11016)
-  * Cache PullRequest Divergence (#10914)
-  * Make `gitea admin auth list` formatting configurable (#10844)
-  * Add Matrix webhook (#10831)
-  * Add Organization Wide Labels (#10814)
-  * Allow to set protected file patterns for files that can not be changed under no conditions (#10806)
-  * Option to set default branch at repository creation (#10803)
-  * Add request review from specific reviewers feature in pull request (#10756)
-  * Add NextCloud oauth (#10562)
-  * System-wide webhooks (#10546)
-  * Relax sanitization as per https://github.com/jch/html-pipeline (#10527)
-  * Use media links for img in post-process (#10515)
-  * Add API endpoints to manage OAuth2 Application (list/create/delete) (#10437)
-  * Render READMEs in docs/ .gitea or .github from root (#10361)
-  * Add feishu webhook support (#10229)
-  * Cache last commit to accelerate the repository directory page visit (#10069)
-  * Implement basic app.ini and path checks to doctor cmd (#10064)
-  * Make WorkerPools and Queues flushable (#10001)
-  * Implement "embedded" command to extract static resources (#9982)
-  * Add API endpoint for repo transfer (#9947)
-  * Make archive prefixing configurable with a global setting (#9943)
-  * Add Unique Queue infrastructure and move TestPullRequests to this (#9856)
-  * Issue/PR Context Popups (#9822)
-  * Add "Update Branch" button to Pull Requests (#9784)
-  * Add require signed commit for protected branch (#9708)
-  * Mark PR reviews as stale at push and allow to dismiss stale approvals (#9532)
-  * Add API notification endpoints (#9488)
-  * Issue search support elasticsearch (#9428)
-  * Add API branch protection endpoint (#9311)
-  * Add a new command doctor to check if some wrong configurations on gitea instance (#9095)
-  * Add support for migrating from Gitlab (#9084)
-  * Add support for database schema in PostgreSQL (#8819)
-  * Add setting to set default and global disabled repository units. (#8788)
-  * Language statistics bar for repositories (#8037)
-  * Restricted users (#6274)
-* BUGFIXES
-  * Fix commenting on non-utf8 encoded files (#11916) (#11950)
-  * Use google/uuid to instead satori/go.uuid (#11943) (#11946)
-  * Align show/hide outdated button on code review block (#11932) (#11944)
-  * Update to go-git v5.1.0 (#11936) (#11941)
-  * Use ID or Where to instead directly use Get when load object from database (#11925) (#11934)
-  * Update CommitsAhead CommitsBehind on Pull BaseBranch Change too (#11912) (#11915)
-  * Invalidate comments when file is shortened (#11882) (#11884)
-  * Rework api/user/repos for pagination (#11827) (#11877)
-  * Handle more pathological branch and tag names (#11843) (#11863)
-  * Add doctor check to set IsArchived false if it is null (partial #11853) (#11859)
-  * Prevent panic on empty HOST for mysql (#11850) (#11856)
-  * Use DEFAULT_PAGING_NUM instead of MAX_RESPONSE_ITEMS in ListOptions (#11831) (#11836)
-  * Fix reply octicon (#11821) (#11822)
-  * Honor DEFAULT_PAGING_NUM for API (#11805) (#11813)
-  * Ensure rejected push to refs/pull/index/head fails nicely (#11724) (#11809)
-  * In File Create/Update API return 404 if Branch does not exist (#11791) (#11795)
-  * Fix doer of rename repo (#11789) (#11794)
-  * Initialize SimpleMDE when making a code comment (#11749) (#11785)
-  * Fix timezone on issue deadline (#11697) (#11784)
-  * Fix to allow comment poster to edit or delete his own comments (#11671) (#11774)
-  * Show full 500 error in API when Gitea in dev mode (#11641) (#11753)
-  * Add missing templates for Matrix system webhooks (#11729) (#11748)
-  * Fix verification of subkeys of default gpg key (#11713) (#11747)
-  * Fix styling for commiter on diff view (#11715) (#11744)
-  * Properly truncate system notices (#11714) (#11742)
-  * Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718)
-  * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11682)
-  * Doctor check & fix db consistency (#11111) (#11676)
-  * Exclude generated files from language statistics (#11653) (#11670)
-  * Return json on 500 error from API (#11574) (#11659)
-  * When must change password only show Signout (#11600) (#11637)
-  * Backport various styling fixes (#11619)
-  * Fix wrong milestone in webhook message (#11596) (#11611)
-  * Fix serviceworker output file and misc improvements (#11562) (#11610)
-  * When initialising repositories ensure that the user doing the creation is the initializer (#11601) (#11608)
-  * Prevent empty query parameter being set on dashboard (#11561) (#11604)
-  * Fix images in wiki edit preview (#11546) (#11602)
-  * Prevent (caught) panic on login (#11590) (#11597)
-  * Prevent transferring repos to invisible orgs (#11517) (#11549)
-  * Move serviceworker to workbox and fix SSE interference (#11538) (#11547)
-  * API PullReviewComment HTMLPullURL should return the HTMLURL (#11501) (#11533)
-  * Fix repo-list private and total count bugs (#11500) (#11532)
-  * Fix form action template substitutions on admin pages (backport #11519) (#11531)
-  * Fix a bug where the reaction emoji doesn't disappear. (#11489) (#11530)
-  * TrimSpace when reading InternalToken from a file (#11502) (#11524)
-  * Fix selected line color in arc-green (#11492) (#11520)
-  * Make localstorage read ssh or https correctly (#11483) (#11490)
-  * Check branch protection on IsUserAllowedToUpdate (#11448)
-  * Fix margin on attached segment headers when they are separated by other element (#11425)
-  * Fix webhook template when validation errors occur (#11421)
-  * Fix NPE in template due to missing signing key on commit page (#11392)
-  * Restore active background to Register button on Register page (#11390)
-  * Fix hook failure due to relative LFS_CONTENT_PATH (#11362)
-  * Correctly set the organization num repos (#11339)
-  * Prevent 500 with badly formed task list (#11328)
-  * Allow compare page to look up base, head, own-fork, forkbase-of-head (#11327)
-  * Handle panics that percolate up to the graceful module (#11291)
-  * Don't allow registration via the web form, when AllowOnlyExternalRegistration is True (#11248)
-  * Patch fomantic-ui to workaround build issue (#11244)
-  * Prevent panic during wrappedConn close at hammertime (#11219)
-  * On logout force redirect to start page (#11202)
-  * Fix creation of Organization repos by Users with max created personal repos (#11183)
-  * Add option to increase provided OAuth2 token maximum size (#11180)
-  * Log the indexer path on failure (#11172)
-  * Ensure that relative paths in edit preview work (#11143)
-  * Make API EditIssue and EditPullRequest issue notifications (#11123)
-  * Send 404 immediately for known public requests (#11117)
-  * Remove nil inserts in models (#11096)
-  * Add GetReviews() to RetryDownloader (#11093)
-  * Remove nonexistent serviceworker entries (#11091)
-  * Simplify and fix GetApprovalCounts (#11086)
-  * Fix wiki revision template and simplify some tmpl conditions (#11080)
-  * Make branch parameter optional for /api/v1/repos/{owner}/{repo}/contents/{filepath} (#11067)
-  * Align review-item svg octicons (#11065)
-  * Automatically remove Watches, Assignments, etc if user loses access due to being removed as collaborator or from a team (#10997)
-  * Users should not be able to prohibit their own login (#10970)
-  * Fix scrollbar issues in dropdowns (#10897)
-  * Change the order of issues.closed_by to list opening user first (#10876)
-  * Allow site admin to check /api/v1/orgs endpoints (#10867)
-  * Avoid logging []byte in queue failures - convert to string first (#10865)
-  * Use ErrKeyUnableToVerify if fail to calc fingerprint in ssh-keygen (#10863)
-  * Fix assignees double load bug (#10856)
-  * Handle push rejection in branch and upload (#10854)
-  * In authorized_keys use double-quote for windows compatibility (#10841)
-  * Fix milestone template (#10824)
-  * log.Fatal on failure to listen to SSH port (#10795)
-  * Fix forked repo has no icon and language stat. (#10791)
-  * Fix tag/release deletion (#10663)
-  * Fix webhook migration (#10641)
-  * Migration for deleting orphaned dependencies (#10617)
-  * Add migration to fix the old broken merge-bases (#10604)
-  * Update templates for Go 1.14 (#10596)
-  * Remove unnecessary parentheses in wiki/view template (#10583)
-  * Change default value of DefaultCommandExecutionTimeout to match docs (#10581)
-  * Handle panic in indexer initialisation better (#10534)
-  * Set correct content_type value for Gogs/Gitea webhooks (#9504) (#10456)
-  * Fixed wrong AppSubUrl in multiple templates (#10447)
-  * Fix profile page CSS (#10406)
-  * Inject SVG sprite via ajax (#10320)
-  * Fix migration information update bug when linked github account (#10310)
-  * Allow admin to check org membership by API for other users (#10201)
-  * Fix topics dropdown (#10167)
-  * Ensure DeleteUser is not allowed to Delete Orgs and visa versa (#10134)
-  * Fix IsErrPullClosed (#10093)
-  * Accept punctuation after simple+cross repository issue references (#10091)
-  * On merge of already closed PR redirect back to the pulls page (#10010)
-  * Fix crowdin update script (#9969)
-  * Fix pull view when head repository or head branch missed and close related pull requests when delete head repository or head branch (#9927)
-  * Add option to prevent LDAP from deactivating everything on empty search (#9879)
-  * Fix admin handling at merge of PR (#9749)
-  * err_admin_name_pattern_not_allowed String Clarification (#9731)
-  * Fix wrong original git service type on a migrated repository (#9693)
-  * Fix ref links in issue overviews for tags (#8742)
-* ENHANCEMENTS
-  * Fix search form button overlap (#11840) (#11864)
-  * Make tabular menu styling consistent for arc-green (#11570) (#11798)
-  * Add option to API to update PullRequest base branch (#11666) (#11796)
-  * Increase maximum SQLite variables count to 32766 (#11696) (#11783)
-  * Update emoji dataset with skin tone variants (#11678) (#11763)
-  * Add logging to long migrations (#11647) (#11691)
-  * Change language statistics to save size instead of percentage (#11681) (#11690)
-  * Allow different HardBreaks settings for documents and comments (#11515) (#11599)
-  * Fix alignment for commits on dashboard (#11595) (#11680)
-  * Default MSSQL port 0 to allow automatic detection by default (#11642) (#11673)
-  * Handle expected errors in AddGPGkey API  (#11644) (#11661)
-  * Close EventSource before unloading the page (#11539) (#11557)
-  * Ensure emoji render with regular font-weight (#11541) (#11545)
-  * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11542)
-  * Tweak reaction buttons (#11516)
-  * Use more toned colors for selected line (#11493) (#11511)
-  * Increase width for authors on commit view (#11441)
-  * Hide archived repos by default in repo-list (#11440)
-  * Better styling for code review comment textarea (#11428)
-  * Support view individual commit for wiki pages (#11415)
-  * Fix yellow background on active elements in code review (#11414)
-  * Better styling for code review comment form (#11413)
-  * Change install description on homepage (#11395)
-  * Ensure search action button is coalesced to adjacent input (#11385)
-  * Switch code editor to Monaco (#11366)
-  * Add paging and archive/private repository filtering to dashboard list (#11321)
-  * Changed image of openid-connect logo for better look on arc-green theme (#11312)
-  * Load Repo Topics on blame view too (#11307)
-  * Change the style in admin notice content view from `

` to `

` (#11301)
-  * Allow log.xxx.default to set logging settings for the default logger only (#11292)
-  * Automatically attempt auto recovery of broken disk queues (Update lunny/levelqueue to 0.3.0) (#11285)
-  * Make sendmail a Process and have default timeout (#11256)
-  * Check value of skip-repository flag in dump command (#11254)
-  * Fix submit review form (#11252)
-  * Allow unauthenticated users to compare (#11240)
-  * Add EventSource support (#11235)
-  * Refactor Milestone related (#11225)
-  * Add pull review API endpoints (#11224)
-  * Add a 'this' to issue close/reopened messages (#11204)
-  * When migrating from Gitlab map Approvals to approving Reviews (#11147)
-  * Improve representation of attachments in issues (#11141)
-  * Protect default branch against deletion (#11115)
-  * Add X-Total-Count on /repos/{owner]/{repo}/pulls API endpoint (#11113)
-  * Fix status label on branches list vertical alignment (#11109)
-  * Add single release page and latest redirect (#11102)
-  * Add missing commit states to PR checks template (#11085)
-  * Change icon on title for merged PR to git-merge (#11064)
-  * Add MergePull comment type instead of close for merge PR (#11058)
-  * Upgrade jQuery to 3.5.0, remove jQuery-Migrate, fix deprecations (#11055)
-  * Consolidate author name across timeline (#11053)
-  * Refactor UpdateOAuth2Application (#11034)
-  * Support unicode emojis and remove emojify.js (#11032)
-  * Add git hook "warning" to admin panel (#11030)
-  * Add flash notify for email preference setting success (#11027)
-  * Remove package code.gitea.io/gitea/modules/git import out of models (#11025)
-  * Match arc-green code tag color to code blocks (#11023)
-  * Move syntax highlighting to web worker (#11017)
-  * Prevent merge of outdated PRs on protected branches (#11012)
-  * Add Get/Update for api/v1/user/applications/oauth2 (#11008)
-  * Upgrade to most recent bluemonday (#11007)
-  * Tweak code tags in markdown (#11000)
-  * Reject duplicate AccessToken names (#10994)
-  * Fix Ctrl-Enter shortcut for issues (#10986)
-  * Provide `OwnerName` field for README template (#10981)
-  * Prettify Timeline (#10972)
-  * Add issue subscription check to API (#10967)
-  * Use AJAX for notifications table (#10961)
-  * Adjust label padding (#10957)
-  * Avoiding directory execution on hook (#10954) (#10955)
-  * Migrate ActivityHeatmap to Vue SFC (#10953)
-  * Change merge strategy: do not check write access if user in merge white list (#10951)
-  * Enable GO111MODULE=on globally in Makefile (#10939)
-  * API endpoint to get single commit via SHA and Ref (#10915)
-  * Add accordion to release list and hide non-latest (#10910)
-  * Split dashboard elements into separate template files (#10885)
-  * Add more message on sidebar menus (#10872)
-  * Set MySQL rowtype to dynamic for new tables (#10833)
-  * Completely fix task-list checkbox styling (#10798)
-  * Hide gear icon for user who can't use them on sidebar (#10750)
-  * Refactor Cron and merge dashboard tasks (#10745)
-  * Change review status icons on pr view style to github style (#10737)
-  * Make pagination optional for API list notification endpoints (#10714)
-  * Fix tab indentation in code view (#10671)
-  * Fix task-list checkbox styling (#10668)
-  * Multiple LFS improvements (#10667)
-  * Make PR message on pushes configurable (#10664)
-  * Move dropzone.js to npm/webpack (#10645)
-  * Ensure Update button is enabled even when CI has failed (#10640)
-  * Add restricted user filter to LDAP authentication (#10600)
-  * Add Yandex OAuth2 provider (#8335) (#10564)
-  * Make avatar lookup occur at image request (#10540)
-  * Prevent accidential selection of language stats bar (#10537)
-  * Add fluid-icon (#10491)
-  * Inform participants on UI too (#10473)
-  * Build with go 1.14 (and raise minimum go version to 1.12) (#10467)
-  * Add max-file-size to LFS (#10463)
-  * Enable paggination for ListRepoTags API (#10454)
-  * Update JS dependencies (#10450)
-  * Show the username as a fallback on feeds if full name is blank (#10438)
-  * Various dark theme fixes (#10416)
-  * Display pull request head branch even the branch deleted or repository deleted (#10413)
-  * Prevent Firefox from using apple-touch-icon (#10402)
-  * Fix input[type=file] on dark theme (#10382)
-  * Improve mobile review-box sizing (#10297)
-  * Notification: queue ui.go notification-service (#10281)
-  * Add detected file language to code search (#10256)
-  * Index code and stats only for non-empty repositories (#10251)
-  * Add Approval Counts to pulls list (#10238)
-  * Limit label list height on edit issue page (#10216)
-  * Improve 404 error message (#10214)
-  * Tweak locale to respect singular conflicting file message in PR list (#10177)
-  * Fix commit view (#10169)
-  * Reorganize frontend files and tooling (#10168)
-  * Allow emoji on popup label (#10166)
-  * ListIssues add filter for milestones API (#10148)
-  * Show if a PR has conflicting files on the PR lists (#10130)
-  * Fix inconsistent label color format in API (#10129)
-  * Show download count info in release list (#10124)
-  * Add Octicon SVG spritemap (#10107)
-  * Update aria-fixed semantic-dropdown to fomantic master (#10096)
-  * Fix apple-touch-icon, regenerate images (#10065)(#10006)
-  * Style blockquote for default issue mail template (#10024)
-  * More expansions in template repositories (#10021)
-  * Allow list collaborators for users with Read access to repo (#9995)
-  * Add explicit dimensions to navbar avatar (#9986)
-  * Remove loadCSS and preload woff2 icon fonts (#9976)
-  * Fix commit view JS features, reimplement folding (#9968)
-  * Fix review avatar image (#9962)
-  * Improve notification pager (#9821)
-  * Move jquery and jquery-migrate to npm/webpack (#9813)
-  * Change font to Roboto to support more charsets (#9803)
-  * Move mailer to use a queue (#9789)
-  * Issue search on my related repositories (#9758)
-  * Add "before" query to ListIssueComments and ListRepoIssueComments API (#9685)
-  * Move tracked time api convert to convert package (#9665)
-  * Improve PR info in default merge message (#9635)
-  * Granular webhook events (#9626)
-  * Add Reviewed-on in commit message (#9623)
-  * Add top author stats to activity page (#9615)
-  * Allow repo admin to merge PR regardless of review status (#9611)
-  * Migrate reactions when migrating repository from github (#9599)
-  * API orgEditTeam make Fields optional (#9556)
-  * Move create/fork repository from models to modules/repository (#9489)
-  * Migrate reviews when migrating repository from github (#9463)
-  * Times API add filters (#9373)
-  * Move push commits from models to modules/repository (#9370)
-  * Add API endpoint to check notifications [Extend #9488] (#9595)
-  * Add GET /orgs API endpoint (#9560)
-  * API add/generalize pagination (#9452)
-  * Make create org repo API call same as github (#9186)
-* BUILD
-  * Turn off go modules for xgo and gxz (#10963)
-  * Add gitea-vet (#10948)
-  * Rename scripts to build and add revive command as a new build tool command (#10942)
-  * Add 'make lint', restructure 'compliance' pipeline (#10861)
-  * Move JS build dependencies to 'dependencies' (#10763)
-  * Use whitelist to find go files, run find only once (#10594)
-  * Move vue and vue-calendar-heatmap to npm/webpack (#10188)
-  * Move jquery.are-you-sure to npm/webpack (#10063)
-  * Move highlight.js to npm/webpack (#10011)
-  * Generate Bindata if TAGS="bindata" and not up-to-date (#10004)
-  * Move CSS build to webpack (#9983)
-  * Move fomantic target, update 'make help' (#9945)
-  * Add css extraction and minification to webpack (#9944)
-  * Misc webpack tweaks (#9924)
-  * Make node_modules a order-only prerequisite (#9923)
-  * Update documentation for the go module era (#9751)
-  * Move swagger-ui to webpack/npm and update it to 3.24.3 (#9714)
-  * Use npm to manage fomantic and only build needed components (#9561)
-* MISC
-  * Add gnupg to Dockerfile (#11365)
-  * Update snapcraft.yaml for core18 and latest features (#11300)
-  * Update JS dependencies, min Node.js version 10.13 (#11246)
-  * Change default charset for MySQL on install to utf8mb4 (#10989)
-  * Return issue subscription status from API subscribe (#10966)
-  * Fix queue log param (#10733)
-  * Add warning when using relative path to app.ini (#10104)
-
-## [1.11.7](https://github.com/go-gitea/gitea/releases/tag/v1.11.7) - 2020-06-18
-
-* BUGFIXES
-  * Use ID or Where to instead directly use Get when load object from database (#11925) (#11935)
-  * Fix __webpack_public_path__ for 1.11 (#11907)
-  * Fix verification of subkeys of default gpg key (#11713) (#11902)
-  * Remove unnecessary parentheses in wiki/view template (#11781)
-  * Doctor fix xorm.Count nil on sqlite error (#11741)
-
-## [1.11.6](https://github.com/go-gitea/gitea/releases/tag/v1.11.6) - 2020-05-30
-
-* SECURITY
-  * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11683)
-  * Use session for retrieving org teams (#11438) (#11439)
-* BUGFIXES
-  * Return json on 500 error from API (#11574) (#11660)
-  * Fix wrong milestone in webhook message (#11596) (#11612)
-  * Prevent (caught) panic on login (#11590) (#11598)
-  * Fix commit page js error (#11527)
-  * Use media links for img in post-process (#10515) (#11504)
-  * Ensure public repositories in private organizations are visible and fix admin organizations list (#11465) (#11475)
-  * Set correct Content-Type value for Gogs/Gitea webhooks (#9504) (#10456) (#11461)
-  * Allow all members of private orgs to see public repos (#11442) (#11459)
-  * Whenever the ctx.Session is updated, release it to save it before sending the redirect (#11456) (#11457)
-  * Forcibly clean and destroy the session on logout (#11447) (#11451)
-  * Fix /api/v1/orgs/* endpoints by changing parameter to :org from :orgname (#11381)
-  * Add tracked time fix to doctor (part of #11111) (#11138)
-  * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11544)
-  * Remove unnecessary parentheses in wiki/revision.tmpl to allow 1.11 to build on go1.14  (#11481)
-
-## [1.11.5](https://github.com/go-gitea/gitea/releases/tag/v1.11.5) - 2020-05-09
-
-* BUGFIXES
-  * Prevent timer leaks in Workerpool and others (#11333) (#11340)
-  * Fix tracked time issues (#11349) (#11354)
-  * Add NotifySyncPushCommits to indexer notifier (#11309) (#11338)
-  * Allow X in addition to x in tasks (#10979) (#11335)
-  * When delete tracked time through the API return 404 not 500 (#11319) (#11326)
-  * Prevent duplicate records in organizations list when creating a repository (#11303) (#11325)
-  * Manage port in submodule refurl (#11305) (#11323)
-  * api.Context.NotFound(...) should tolerate nil (#11288) (#11306)
-  * Show pull request selection even when unrelated branches (#11239) (#11283)
-  * Repo: milestone: make /milestone/:id endpoint accessible (#11264) (#11282)
-  * Fix GetContents(): Dont't ignore Executables (#11192) (#11209)
-  * Fix submodule paths when AppSubUrl is not root (#11098) (#11176)
-  * Prevent clones and pushes to disabled wiki (#11131) (#11134)
-  * Remove errant third closing curly-bracket from account.tmpl and send account ID in account.tmpl (#11130)
-  * On Repo Deletion: Delete related TrackedTimes too (#11110) (#11125)
-  * Refresh codemirror on show pull comment tab (#11100) (#11122)
-  * Fix merge dialog on protected branch with missing required statuses (#11074) (#11084)
-  * Load pr Issue Poster on API too (#11033) (#11039)
-  * Fix release counter on API repository info (#10968) (#10996)
-  * Generate Diff and Patch direct from Pull head (#10936) (#10938)
-  * Fix rebase conflict detection in git 2.26 (#10929) (#10930)
-* ENHANCEMENT
-  * Fix 404 and 500 image size in small size screen (#11043) (#11049)
-  * Multiple Gitea Doctor improvements (#10943) (#10990) (#10064) (#9095) (#10991)
-
-## [1.11.4](https://github.com/go-gitea/gitea/releases/tag/v1.11.4) - 2020-04-01
-
-* BUGFIXES
-  * Only update merge_base if not already merged (#10909)
-  * Fix milestones too many SQL variables bug (#10880) (#10904)
-  * Protect against NPEs in notifications list (#10879) (#10883)
-  * Convert plumbing.ErrObjectNotFound to git.ErrNotExist in getCommit (#10862) (#10868)
-  * Convert plumbing.ErrReferenceNotFound to git.ErrNotExist in GetRefCommitID (#10676) (#10797)
-  * Account for empty lines in receive-hook message (#10773) (#10784)
-  * Fix bug on branch API (#10767) (#10775)
-  * Migrate to go-git/go-git v5.0.0 (#10735) (#10753)
-  * Fix hiding of fields in authorization source page (#10734) (#10752)
-  * Prevent default for linkAction (#10742) (#10743)
-
-## [1.11.3](https://github.com/go-gitea/gitea/releases/tag/v1.11.3) - 2020-03-10
-
-* BUGFIXES
-  * Prevent panic in stopwatch (#10670) (#10673)
-  * Fix bug on pull view when required status check no ci result (#10648) (#10651)
-  * Build explicitly with Go 1.13 (#10684)
-
-## [1.11.2](https://github.com/go-gitea/gitea/releases/tag/v1.11.2) - 2020-03-06
-
-* BREAKING
-  * Various fixes in login sources (#10428) (#10429)
-* SECURITY
-  * Ensure only own addresses are updated (#10397) (#10399)
-  * Logout POST action (#10582) (#10585)
-  * Org action fixes and form cleanup (#10512) (#10514)
-  * Change action GETs to POST (#10462) (#10464)
-  * Fix admin notices (#10480) (#10483)
-  * Change admin dashboard to POST (#10465) (#10466)
-  * Update markbates/goth (#10444) (#10445)
-  * Update crypto vendors (#10385) (#10398)
-* BUGFIXES
-  * Allow users with write permissions to modify issue descriptions and comments. (#10623) (#10626)
-  * Handle deleted base branch in PR (#10618) (#10619)
-  * Delete dependencies when deleting a repository (#10608) (#10616)
-  * Ensure executable bit is kept on the web editor (#10607) (#10614)
-  * Update mergebase in pr checker (#10586) (#10605)
-  * Fix release attachments being deleted while upgrading (#10572) (#10573)
-  * Fix redirection path if Slack webhook channel is invalid (#10566)
-  * Fix head.tmpl og:image picture location (#10531) (#10556)
-  * Fix 404 after activating secondary email (#10547) (#10553)
-  * Show Signer in commit lists and add basic trust (#10425 & #10511) (#10524)
-  * Fix potential bugs (#10513) (#10518)
-  * Use \[:space:\] instead of \\s (#10508) (#10509)
-  * Avoid mailing users that have explicitly unwatched an issue (#10475) (#10500)
-  * Handle push rejection message in Merge & Web Editor (#10373) (#10497)
-  * Fix SQLite concurrency problems by using BEGIN IMMEDIATE (#10368) (#10493)
-  * Fix double PR notification from API (#10482) (#10486)
-  * Show the username as a fallback on feeds if full name is blank (#10461)
-  * Trigger webhooks on issue label-change via API too (#10421) (#10439)
-  * Fix git reference type in webhooks (#10427) (#10432)
-  * Prevent panic on merge to PR (#10403) (#10408)
-  * Fix wrong num closed issues on repository when close issue via commit… (#10364) (#10380)
-  * Reading pull attachments should depend on read UnitTypePullRequests (#10346) (#10354)
-  * Set max-width on review-box comment box (#10348) (#10353)
-  * Prevent nil pointer in GetPullRequestCommitStatusState (#10342) (#10344)
-  * Fix protected branch status check settings (#10341) (#10343)
-  * Truncate long commit message header (#10301) (#10319)
-  * Set the initial commit status to Success otherwise it will always be Pending (#10317) (#10318)
-  * Don't manually replace whitespace during render (#10291) (#10315)
-* ENHANCEMENT
-  * Admin page for managing user e-mail activation (#10557) (#10579)
-
-## [1.11.1](https://github.com/go-gitea/gitea/releases/tag/v1.11.1) - 2020-02-15
-
-* BUGFIXES
-  * Repo name added to automatically generated commit message when merging (#9997) (#10285)
-  * Fix Workerpool deadlock (#10283) (#10284)
-  * Divide GetIssueStats query in smaller chunks (#10176) (#10282)
-  * Fix reply on code review (#10257)
-  * Stop hanging issue indexer initialisation from preventing shutdown (#10243) (#10249)
-  * Fix filter label emoji width (#10241) (#10244)
-  * Fix issue sidebar menus having an infinite height (#10239) (#10240)
-  * Fix commit between two commits calculation if there is only last commit (#10225) (#10226)
-  * Only check for conflicts/merging if the PR has not been merged in the interim (#10132) (#10206)
-  * Blacklist manifest.json & milestones user (#10292) (#10293)
-
-## [1.11.0](https://github.com/go-gitea/gitea/releases/tag/v1.11.0) - 2020-02-10
-
-* BREAKING
-  * Fix followers and following tabs in profile (#10202) (#10203)
-  * Make CertFile and KeyFile relative to CustomPath (#9868) (#9874)
-  * Remove unused endpoints (#9538)
-  * Prefix all user-generated IDs in markup (#9477)
-  * Enforce Gitea environment for pushes (#8982)
-  * Hide some user information via API if user have not enough permissions (#8655)
-  * Move startpage/homepage translation to crowdin (#8596)
-* SECURITY
-  * Never allow an empty password to validate (#9682) (#9683)
-  * Prevent redirect to Host (#9678) (#9679)
-  * Swagger hide search field (#9554)
-  * Add "search" to reserved usernames (#9063)
-  * Switch to fomantic-ui (#9374)
-  * Only serve attachments when linked to issue/release and if accessible by user (#9340)
-* FEATURES
-  * Webhooks should only show sender if it makes sense (#9601)
-  * Provide Default messages for merges (#9393)
-  * Add description to labels on create issue (#9392)
-  * Graceful Queues: Issue Indexing and Tasks (#9363)
-  * Default NO_REPLY_ADDRESS to DOMAIN (#9325)
-  * Allow FCGI over unix sockets (#9298)
-  * Graceful: Xorm, RepoIndexer, Cron and Others (#9282)
-  * Add API for Reactions (#9220)
-  * Graceful: Cancel Process on monitor pages & HammerTime (#9213)
-  * Graceful: Allow graceful restart for unix sockets (#9113)
-  * Graceful: Allow graceful restart for fcgi (#9112)
-  * Sign protected branches (#8993)
-  * Add Graceful shutdown for Windows and hooks for shutdown of goroutines (#8964)
-  * Add Gitea icon to Emojis (#8950)
-  * Expand/Collapse Files and Blob Excerpt while Reviewing/Comparing code (#8924)
-  * Allow Custom Reactions (#8886)
-  * Close/reopen issues by keywords in titles and comments (#8866)
-  * Allow incompletely specified Time Formats (#8816)
-  * Prevent upload (overwrite) of lfs locked file (#8769)
-  * Template Repositories (#8768)
-  * Add /milestones endpoint (#8733)
-  * Make repository management section handle lfs locks (#8726)
-  * Respect LFS File Lock on UI (#8719)
-  * Add team option to grant rights for all organization repositories (#8688)
-  * Enabling and disabling the commit button to prevent empty commits (web editor) (#8590)
-  * Add setting to disable BASIC authentication (#8586)
-  * Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528)
-  * Allow Protected Branches to Whitelist Deploy Keys (#8483)
-  * Push to create repo (#8419)
-  * Sign merges, CRUD, Wiki and Repository initialisation with gpg key (#7631)
-  * Add basic repository lfs management (#7199)
-* BUGFIXES
-  * Fix code-expansion arc-green theme bug (#10180) (#10185)
-  * Prevent double wait-group decrement (#10170) (#10175)
-  * Allow emoji on review head comments (#10159) (#10174)
-  * Fix issue/pull link (#10158) (#10173)
-  * Fix push-create SSH bugs (#10145) (#10151)
-  * Prevent DeleteUser API abuse (#10125) (#10128)
-  * Fix issues/pulls dashboard paging error (#10114) (#10115)
-  * Add button to revert SimpleMDE to plain textarea (#10099) (#10102)
-  * Fix branch page pull request title and link error (#10092) (#10097)
-  * Fix PR API: Only try to get HeadBranch if HeadRepo exist (#10029) (#10088)
-  * Update topics repo count when deleting repository (#10051) (#10081)
-  * Show pull icon on pull requests (#10061) (#10062)
-  * Fix milestone API state parameter unhandled (#10049) (#10052)
-  * Move to using a temporary repo for pushing new PRs (#10009) (#10042)
-  * Fix wiki raw view on sub path (#10002) (#10040)
-  * Ensure that feeds are appropriately restricted (#10018) (#10019)
-  * Sanitize credentials in mirror form (#9975) (#9991)
-  * Close related pull requests when deleting head repository or head branch (#9927) (#9974)
-  * Switch to use -f instead of -F for sendmail (#9961) (#9970)
-  * Fix file rename/copy not supported by indexer (#9965) (#9967)
-  * Fix repo indexer not updating upon push (#9957) (#9963)
-  * Don't convert ellipsis in markdown (#9905) (#9937)
-  * Fixed repo link in generated comment for cross repository dependency (#9863) (#9935)
-  * Check if diff actually contains sections when rendering (#9926) (#9933)
-  * Fix wrong hint when status checking is running on pull request view (#9886) (#9928)
-  * Fix RocketChat (#9908) (#9921)
-  * Do not try to recreate ldap user if they are already created (#9900) (#9919)
-  * Create terminated channel in queue_redis (#9910) (#9911)
-  * Prevent empty LDAP search result from deactivating all users (#9879) (#9896)
-  * Fix wrong permissions check when issues/prs shared operations (#9885) (#9889)
-  * Check user != nil before checking values (#9881) (#9883)
-  * Allow hyphen in language name (#9873) (#9880)
-  * Ensure that 2fa is checked on reset-password (#9857) (#9876)
-  * Fix issues/pulls dependencies problems (#9842) (#9864)
-  * Fix markdown anchor links (#9673) (#9840)
-  * Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9837)
-  * Fix download file wrong content-type (#9825) (#9834)
-  * Fix wrong poster identity on a migrated pull request when submit review (#9827) (#9830)
-  * Fix database dump when log directory is missing (#9818) (#9819)
-  * Fix compare (#9808) (#9814)
-  * Fix push-to-create (#9772) (#9797)
-  * Fix missing msteam webhook on organization (#9781) (#9794)
-  * Fix missing unlock in uniquequeue (#9790) (#9791)
-  * Fix add team on collaborator page when same name as organization (#9778)
-  * DeleteRepoFile incorrectly handles Delete to new branch (#9769) (#9775)
-  * Fix milestones page (#9771)
-  * Fix SimpleMDE quote reply (#9757) (#9768)
-  * Fix missing updated time on migrated issues and comments (#9744) (#9764)
-  * Move Errored PRs out of StatusChecking (#9675) (#9726)
-  * Make hook status printing configurable with delay (#9641) (#9725)
-  * ​Fix /repos​/issues​/search (#9698) (#9724)
-  * Silence fomantic error regarding tabs (#9713) (#9718)
-  * Remove unused lock (#9709) (#9710)
-  * Remove q.lock.Unlock() in setInternal to prevent panic (#9705) (#9706)
-  * Load milestone in API PR list (#9671) (#9700)
-  * Don't attempt to close issue if already closed (#9696) (#9699)
-  * Remove google font call (#9668) (#9681)
-  * Eliminate horizontal scroll caused by footer (#9674)
-  * Fix nil reference in repo generation (#9660) (#9666)
-  * Add HTML URL to API Issues (#9654) (#9661)
-  * Add PR review webhook to Telegram (#9653) (#9655)
-  * Use filepath.IsAbs instead of path.IsAbs (#9651) (#9652)
-  * Disable remove button on repository teams when have access to all (#9640)
-  * Clean up old references on branch delete (#9614)
-  * Hide public repos owned by private orgs (#9609)
-  * Fix access issues on milestone and issue overview pages. (#9603)
-  * Fix error logged when repos qs is empty (#9591)
-  * Dont trigger notification twice on issue assignee change (#9582)
-  * Fix mirror pushed commit actions (#9572)
-  * Allow only specific columns to be updated on issue via API (#9189) (#9539)
-  * Fix default avatar for ghost user (#9536)
-  * Fix download of release attachments with same name (#9529)
-  * Resolve deprecated INI conversion (#9525)
-  * Ignore empty avatars during database migration (#9520)
-  * Fix deleted branch isn't removed when push the branch again (#9516)
-  * Fix repository issues pagination bug when there are more than one label filter (#9512)
-  * Fix SetExpr failed (#9506)
-  * Remove obsolete file private/push_update.go (#9503)
-  * When recreating hooks, delete them first so they are recreated with the umask (#9502)
-  * Properly enforce gitea environment for pushes (#9501)
-  * Fix datarace on repo indexer queue (#9490)
-  * Add call to load repo prior to redirect in add/remove dependency code (#9484)
-  * Wrap the code indexer (#9476)
-  * Use Req.URL.RequestURI() to cope with FCGI urls (#9473)
-  * Set default ssh.minimum_key_sizes (#9466)
-  * Fixed issue with paging in /repos/{owner}/{repo}/git/trees/{sha} api (#9459)
-  * Fix wrong notification on merge (#9450)
-  * Issue with Migration rule v111 (#9449)
-  * Trigger webhook when deleting a branch after merging a PR (#9424)
-  * Add migration to sanitize repository original_url (#9423)
-  * Use OriginalURL instead of CloneAddr in migration logging (#9418)
-  * Push update after branch is restored (#9416)
-  * Fix wrong migration (#9381)
-  * Fix show repositories filter (#9234) (#9379)
-  * Fix Slack webhook payload title generation to work with Mattermost (#9378)
-  * Fix double webhook for new PR (#9375)
-  * AuthorizedKeysCommand should not query db directly (#9371)
-  * Fix missed change to GetManager() (#9361)
-  * Fix cache problem on dashboard (#9358)
-  * RepoIndexer: DefaultBranch needs to be prefixed by BranchPrefix (#9356)
-  * Fix protected branch using IssueID (#9348)
-  * Fix nondeterministic behavior (#9341)
-  * Fix PR/issue redirects when having external tracker (#9339)
-  * Remove release attachments which repository has been deleted (#9334)
-  * Fix issue indexer not triggered when migrating a repository (#9332)
-  * Add SyncTags to uploader interface (#9326)
-  * Fix bug that release attachment files not deleted when deleting repository (#9322)
-  * Only sync tags after all migration release batches are completed (#9319)
-  * File Edit: Author/Committer interchanged (#9297)
-  * prebuild CSS/JS before xgo release binaries (#9293)
-  * Log: Ensure FLAGS=none shows no flags (#9287)
-  * Make Diff Detail on Pull Request Changed File UI always on Top (#9280)
-  * Switch CSS minifier to cssnano (#9260)
-  * Fix latest docker image haven't include static files. (#9252)
-  * Don't link wiki revision to commit (#9244)
-  * Change review content column to type text in db (#9229)
-  * Fixed topic regex pattern and added search by topic links after save (#9219)
-  * Add language to user API responce (#9215)
-  * Correct tooltip message blocked by dependencies (#9211)
-  * Add SimpleMDE and Fix Image Paste for Issue/Comment Editor (#9197)
-  * Fix panic when diff (#9187)
-  * Fix #9151 - smtp logger configuration sendTos should be an array (#9154)
-  * Fix max length check and limit in multiple repo forms (#9148)
-  * Always Show Password Field on Link Account Sign-in Page (#9147)
-  * Properly fix displaying virtual session provider in admin panel (#9137)
-  * Fix race condition on indexer (#9136)
-  * Fix team links in HTML rendering (#9127)
-  * Fix race condition in ReplaceSanitizer (#9123)
-  * Fix what information is shown about user in API (#9115)
-  * Fix nil context user for template repositories (#9099)
-  * Hide given credentials for migrated repos. (#9097)
-  * Fix reCAPTCHA API URL (#9083)
-  * Fix password checks on admin create/edit user (#9076)
-  * Update golang.org/x/crypto vendor to use acme v2 (#9056)
-  * Ensure Written is set in GZIP ProxyResponseWriter (#9018)
-  * Fix wrong system notice when repository is empty (#9010)
-  * Fix broken link to branch from issue list (#9003)
-  * Fix bug when pack js (#8992)
-  * New review approvals shouldn't require a message (#8991)
-  * Shadow password correctly for session config (#8984)
-  * Don't send notification on pending reviews (#8943)
-  * Fix Notify Create Ref Error on tag creation (#8936)
-  * Convert EOL to UNIX-style to render MD properly (#8925)
-  * Migrate temp_repo.go to use git.NewCommand  (#8918)
-  * Fix issue with user.fullname (#8902)
-  * Add Close() method to gogitRepository (#8901)
-  * Enable punctuations ending mentions (#8889)
-  * Fix password complexity check on registration (#8887)
-  * Fix require external registration password (#8885)
-  * Fix edit content button on migrated issue content (#8877)
-  * Fix permission checks for close/reopen from commit (#8875)
-  * Fix API Bug (fail on empty assignees) (#8873)
-  * Stop using git count-objects and use raw directory size for repository (#8848)
-  * Fix count for commit graph last page (#8843)
-  * Fix to close opened io resources as soon as not needed (#8839)
-  * Improve notification (#8835)
-  * Fix new user form for non-local users (#8826)
-  * Fix: remove duplicated signed commit icons (#8820)
-  * Fix (open/closed) issue count when label excluded (#8815)
-  * Fix SSH2 conditional in key parsing code (#8806)
-  * Fix 500 when edit hook (#8782)
-  * On windows set core.longpaths true (#8776)
-  * Fix commit expand button to not go to commit link (#8745)
-  * Avoid re-issuing redundant cross-references. (#8734)
-  * Fix milestone close timestamp function (#8728)
-  * Move webhook codes from service to webhook notification (#8712)
-  * Show zero lines on the line counter if the file empty (#8700)
-  * Fix deadline on update issue or PR via API (#8696)
-  * make call createMilestoneComment on newIssue func (#8678)
-  * Send tag create and push webhook when release created on UI (#8671)
-  * Prevent chrome download page as html with alt + click (#8669)
-  * Fix 500 when getting user as unauthenticated user (#8653)
-  * Graceful fixes (#8645)
-  * Add SubURL to redirect path (#8632) (#8634)
-  * Fix extra columns from `label` table (#8633)
-  * Add SubURL to redirect path for transferred/renamed repos (#8632)
-  * Fix bug when migrate from API (#8631)
-  * Allow to merge if file path contains " or \ (#8629)
-  * Prevent removal of non-empty emoji panel following selection of duplicate (#8609)
-  * Ensure default gpg settings not nil and found commits have reference to repo (#8604)
-  * Set webhook Content-Type for application/x-www-form-urlencoded (#8599)
-  * Fix #8582 by handling empty repos (#8587)
-  * Fix of the diff statistics view on pull request's (#8581)
-  * Fix bug on pull requests when transfer head repository (#8564)
-  * Fix template error on account page (#8562)
-  * Allow externalID to be UUID (#8551)
-  * Fix ignored error on editorconfig api (#8550)
-  * Fix user avatar name (#8547)
-  * Ensure that GitRepo is set on Empty repositories (#8539)
-  * Add missed close in ServeBlobLFS (#8527)
-  * Fix migrate mirror 500 bug (#8526)
-  * Fix password complexity regex for special characters (on master) (#8525)
-* ENHANCEMENTS
-  * Explicitly refer to PR in squash-merge commit message in case of external tracker (#9844) (#9855)
-  * Add a /user/login landing page option (#9622)
-  * Some more e-mail notification fixes (#9596)
-  * Add branch protection option to block merge on requested changes. (#9592)
-  * Add footer extra links template (#9576)
-  * Fix for a wrong URL in activity page of repository.  (#9571)
-  * Update default issue template (#9568)
-  * Change markdown rendering from blackfriday to goldmark  (#9533)
-  * Extend file create api with dates (#9464)
-  * Add ActionCommentPull action (#9456)
-  * Response for context on retry database connection (#9444)
-  * Refactor webhooks to reduce code duplication (#9422)
-  * update couchbase deps for new license (#9419)
-  * Add .ignore file for search tools (#9417)
-  * Remove unsued struct (#9405)
-  * Hide not allowed Reactions (#9387)
-  * Remove text from action-only webhooks (#9377)
-  * Move PushToBaseRepo from models to services/pull (#9352)
-  * Site admin could view org's members (#9346)
-  * Sleep longer if request speed is over github limitation (#9335)
-  * Refactor comment (#9330)
-  * Refactor code indexer (#9313)
-  * Remove SavePatch and generate patches on the fly (#9302)
-  * Move some pull request functions from models to services (#9266)
-  * Update JS dependencies (#9255)
-  * Show label list on label set (#9251)
-  * Redirect issue if repo has configured external tracker. (#9247)
-  * Allow kbd tags (#9245)
-  * Remove unused comment actions (#9222)
-  * Fixed errors logging in dump.go (#9218)
-  * Expose release counter to repo API response (#9214)
-  * Make consistent links to repository in the Slack/Mattermost notificiations (#9205)
-  * Expose pull request counter to repo API response (#9202)
-  * Extend TrackedTimes API (#9200)
-  * Extend StopWatch API (#9196)
-  * Move code indexer related code to a new package (#9191)
-  * Docker: ask s6 to stop all service when gitea stop (#9171)
-  * Variable expansion in repository templates (#9163)
-  * Add avatar and issue labels to template repositories (#9149)
-  * Show single review comments in the PR conversation tab (#9143)
-  * Extract createComment (#9125)
-  * Move PushUpdateOptions from models to repofiles (#9124)
-  * Alternate syntax for cross references (#9116)
-  * Add USE_SERVICE_WORKER setting (#9110)
-  * Only show part of members on orgnization dashboard and add paging for orgnization members page (#9092)
-  * Explore page: Add topic param to pagination (#9077) (#9078)
-  * Markdown: Sanitizier Configuration (#9075)
-  * Add password requirement info on error (#9074)
-  * Allow authors to use act keywords in PR content (#9059)
-  * Move modules/gzip to gitea.com/macaron/gzip (#9058)
-  * Branch protection: Possibility to not use whitelist but allow anyone with write access (#9055)
-  * Context menus for comments, add quote reply (#9043)
-  * Update branch API endpoint to show effective branch protection. (#9031)
-  * Move git graph from models to modules/graph (#9027)
-  * Move merge actions to notification (#9024)
-  * Move mirror sync actions to notification (#9022)
-  * Add retry for migration http/https requests (#9019)
-  * Rewrite delivery of issue and comment mails (#9009)
-  * Add review comments to mail notifications (#8996)
-  * Refactor pull request review (#8954)
-  * Githook highlighter (#8932)
-  * Add git hooks and webhooks to template repositories; move to services (#8926)
-  * Only view branch or tag if it match refType requested. (#8899)
-  * Drop Admin attribute based on LDAP when login (continue #1743) (#8849)
-  * Add additional periods to activity page (#8829)
-  * Update go-org to optimize code (#8824)
-  * Move some actions to notification/action (#8779)
-  * Webhook support custom proxy (#8760)
-  * Fix API deadline removal (#8759)
-  * Mark review comment as invalidated when file is deleted (#8751)
-  * Move pull list code to a separate file (#8748)
-  * Move webhook to a standalone package under modules (#8747)
-  * Multi repo select on issue page (#8741)
-  * apply exclude label on milestone issue list (#8739)
-  * Move issue notifications and assignee man (#8713)
-  * Move issue change content from models to service (#8711)
-  * Move issue change status from models to service (#8691)
-  * Move more issue assignee code from models to issue service (#8690)
-  * Create PR on Current Repository by Default (#8670)
-  * Improve Open Graph Protocol (#8637)
-  * Batch hook pre- and post-receive calls (#8602)
-  * Improve webhooks (#8583)
-  * Move transfer repository and rename repository on a service package and start action notification (#8573)
-  * Implement/Fix PR review webhooks (#8570)
-  * Rewrite markdown rendering to blackfriday v2 and rewrite orgmode rendering to go-org (#8560)
-  * Move some repositories' operations to a standalone service package (#8557)
-  * Allow more than 255 characters for tokens in external_login_user table (#8554)
-  * Move issue label operations to issue service package (#8553)
-  * Adjust error reporting from merge failures and use LC_ALL=C for git (#8548)
-  * Mail assignee when issue/pull request is assigned (#8546)
-  * Allow committing / adding empty files using the web ui (#8420) (#8532)
-  * Move sync mirror actions to mirror service package (#8518)
-  * Remove arrows on numeric inputs (#8516)
-  * Support inline rendering of CUSTOM_URL_SCHEMES (#8496)
-  * Recalculate repository access only for specific user (#8481)
-  * Add download button for rull request diff- and patch-file (#8470)
-  * Add single sign-on support via SSPI on Windows (#8463)
-  * Move change issue title from models to issue service package (#8456)
-  * Add included tag on  branch view (#8449)
-  * Make static resouces web browser cache time customized on app.ini (#8442)
-  * Enable Uploading/Removing Attachments When Editing an Issue/Comment (#8426)
-  * Add pagination to commit graph page (#8360)
-  * Use templates for issue e-mail subject and body (#8329)
-  * Move clearlabels from models to issue service (#8326)
-  * Move AddTestPullRequestTask to pull service package from models (#8324)
-  * Team permission to create repository in organization (#8312)
-  * Allows external rendering of other filetypes (#8300)
-  * Add 'Alt + click' feature to exclude labels (#8199)
-  * Configurable close and reopen keywords for PRs (#8120)
-  * Configurable URL for static resources (#7911)
-  * Unifies commit list in repository commit table and wiki revision page (#7907)
-  * Allow cross-repository dependencies on issues (#7901)
-  * Auto-subscribe user to repository when they commit/tag to it (#7657)
-  * Restore Graceful Restarting & Socket Activation (#7274)
-  * wiki - add 'write' 'preview' buttons to wiki edit like in issues (#7241)
-  * Change target branch for pull request (#6488)
-  * Display PR commits and diffs using base repo rather than forked (#3648)
-* TESTING
-  * Add debug option to serv to help debug problems (#9492)
-  * Fix the intermittent TestGPGGit failures (#9360)
-  * Testing: Update postgres sequences (#9304)
-  * Missed defer prepareTestEnv (#9285)
-  * Fix "data race" in testlogger (#9159)
-  * Yet another attempt to fix the intermittent failure of gpg git test (#9146)
-  * integrations: Fix Dropped Test Errors (#9040)
-  * services/mirror: fix dropped test errors (#9007)
-  * Fix intermittent GPG Git test failure (#8968)
-  * Update Github Migration Tests (#8893) (#8938)
-  * Update heatmap fixtures to restore tests (#8615)
-* TRANSLATION
-  * Fix Korean locales (#9761) (#9780)
-  * Fix placeholders in the error message (#9060)
-  * Fix spelling of admin.users.max_repo_creation (#8934)
-  * Improve german translation of homepage (#8549)
-* BUILD
-  * Fix webpack polyfills (#9735) (#9738)
-  * Update gitea.com/macaron to 1.4.0 (#9608)
-  * Upgrade lato fonts to v16. (#9498)
-  * Update alpine to 3.11 (#9440)
-  * Upgrade blevesearch (#9177)
-  * Remove built js/css files from git (#9114)
-  * Move semantic.dropdown.custom.js to webpack (#9064)
-  * Check compiled files during build (#9042)
-  * Enable lazy-loading of gitgraph.js (#9036)
-  * Pack web_src/js/draw.js to public/js/index.js (#8975)
-  * Modernize js and use babel (#8973)
-  * Move index.js to web_src and use webpack to pack them (#8598)
-  * Restrict modules/graceful to non-windows build and shim IsChild (#8537)
-  * Upgrade gopkg.in/editorconfig/editorconfig-core-go.v1 (#8501)
-* DOCS
-  * Swagger info corrections (#9441) (#9558)
-  * Add ALLOW_ONLY_EXTERNAL_REGISTRATION to config cheat sheet (#8986)
-  * Rephrase comment about RuntimeDirectory option in systemd config (#8912)
-  * Explicitly indicate the socket unit to use the service unit "gitea.service" (#8804)
-  * Adjust the must-change-password help (#8755)
-  * Add notice to docs for migrating from more recent versions of Gogs (#8724)
-  * Add explicit info about customization of homepage (#8694)
-  * Change external asciidoctor tool to embedded mode (#8677)
-  * Add Docker fail2ban configuration (#8642)
-  * Correct some outdated statements in the contributing guidelines (#8612)
-  * Basic Design guidelines (describing different parts of the code) (#8601)
-  * Display Gitea logo in Readme (#8592)
-  * Fix building from source docs to ref AppWorkPath (#8567)
-  * Update the provided gitea.service to mention socket activation (#8531)
-  * Doc added how to setup email (#8520)
-* MISC
-  * Backport Locales [2020-01-14] (#9773)
-  * Add translatable Powered by Gitea text in footer (#9600)
-  * Add contrib/environment-to-ini (#9519)
-  * Remove unnecessary loading of settings in update hook (#9496)
-  * Update gitignore list (#9437)
-  * Update license list (#9436)
-  * Fix background reactions in the arc-green theme (#9421)
-  * Update and fix chardet import (#9351)
-  * Ensure LF on checkouts and in editors (#9259)
-  * Fixed topics margin (#9248)
-  * Add comment to exported function WindowsServiceName (make revive) (#9241)
-  * Remove empty lines on issues/pulls page (#9232)
-  * Fix Add Comment Button's "+" Position (#9140)
-  * Add first issue comment hashtag (#9052)
-  * Change some label colors (#9051)
-  * Fix double scroll in branch dropdown (#9048)
-  * Add comment highlight when target from url (#9047)
-  * Update display of reactions to issues and comments (#9038)
-  * Button tooltip formatting under Branches (#9034)
-  * Allow setting default branch via API (#9030)
-  * Update dashboard context for PR reviews (#8995)
-  * Show repository size in repo home page and settings (#8940)
-  * Allow to add and remove all repositories to/from team. (#8867)
-  * Show due date in dashboard issues list (#8860)
-  * Theme arc-green: reverse heatmap colors (#8840)
-  * Project files table style update (#8757)
-  * gitignore debugging file from vscode (#8740)
-  * Add API for Issue set Subscription (#8729)
-  * Make 100% width search bar (#8710)
-  * Update color theme for heatmap (#8709)
-  * Add margin to title_wip_desc (#8705)
-  * Improve visibility of "Pending" indicator (#8685)
-  * Improve accessibility of dropdown menus (#8638)
-  * Make /users/{username}/repos list private repos the current user has access to (#8621)
-  * Prevent .code-view from overriding font on icon fonts (#8614)
-  * Add id references on all issue events to allow internal linking (#8608)
-  * Upgrade xorm to v0.8.0 (#8536)
-  * Upgrade gopkg.in/ini.v1 (#8500)
-  * Update CodeMirror to version 5.49.0 (#8381)
-  * Wiki editor: enable side-by-side button (#7242)
-
-## [1.10.6](https://github.com/go-gitea/gitea/releases/tag/v1.10.6) - 2020-03-10
-
-This is a re-tag version of v1.10.5 and also explicitly built with Go 1.13.
-
-WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should __not__ be used.
-
-## [1.10.5](https://github.com/go-gitea/gitea/releases/tag/v1.10.5) - 2020-03-06
-
-* BUGFIXES
-  * Fix release attachments being deleted while upgrading (#10572) (#10574)
-
-## [1.10.4](https://github.com/go-gitea/gitea/releases/tag/v1.10.4) - 2020-02-16
-
-* FEATURE
-  * Prevent empty LDAP search from deactivating all users (#9879) (#9890)
-* BUGFIXES
-  * Fix reply on code review (#10261) (#10227)
-  * Fix branch page pull request title and link error (#10092) (#10098)
-  * Fix milestone API state parameter unhandled (#10049) (#10053)
-  * Fix wiki raw view on sub path (#10002) (#10041)
-  * Fix RocketChat Webhook (#9908) (#9921) (#9925)
-  * Fix bug about wrong dependencies permissions check and other wrong permissions check (#9884) (Partial backport #9842)
-  * Ensure that 2fa is checked on reset-password (#9857) (#9877)
-
-## [1.10.3](https://github.com/go-gitea/gitea/releases/tag/v1.10.3) - 2020-01-17
-
-* SECURITY
-  * Hide credentials when submitting migration (#9102) (#9704)
-  * Never allow an empty password to validate (#9682) (#9684)
-  * Prevent redirect to Host (#9678) (#9680)
-  * Hide public repos owned by private orgs (#9609) (#9616)
-* BUGFIXES
-  * Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9838)
-  * Fix download file wrong content-type (#9825) (#9835)
-  * Fix wrong identify poster on a migrated pull request when submit review (#9827) (#9831)
-  * Fix dump non-exist log directory (#9818) (#9820)
-  * Fix compare (#9808) (#9815)
-  * Fix missing msteam webhook on organization (#9781) (#9795)
-  * Fix add team on collaborator page when same name as organization (#9783)
-  * Fix cache problem on dashboard (#9358) (#9703)
-  * Send tag create and push webhook when release created on UI (#8671) (#9702)
-  * Branches not at ref commit ID should not be listed as Merged (#9614) (#9639)
-
-## [1.10.2](https://github.com/go-gitea/gitea/releases/tag/v1.10.2) - 2020-01-02
-
-* BUGFIXES
-  * Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
-  * Add ErrReactionAlreadyExist error (#9550) (#9564)
-  * Fix bug when migrate from API (#8631) (#9563)
-  * Use default avatar for ghost user (#9536) (#9537)
-  * Fix repository issues pagination bug when there are more than one label filter (#9512) (#9528)
-  * Fix deleted branch not removed when push the branch again (#9516) (#9524)
-  * Fix missing repository status when migrating repository via API (#9511)
-  * Trigger webhook when deleting a branch after merging a PR (#9510)
-  * Fix paging on /repos/{owner}/{repo}/git/trees/{sha} API endpoint (#9482)
-  * Fix NewCommitStatus (#9434) (#9435)
-  * Use OriginalURL instead of CloneAddr in migration logging (#9418) (#9420)
-  * Fix Slack webhook payload title generation to work with Mattermost (#9404)
-  * DefaultBranch needs to be prefixed by BranchPrefix (#9356) (#9359)
-  * Fix issue indexer not triggered when migrating a repository (#9333)
-  * Fix bug that release attachment files not deleted when deleting repository (#9322) (#9329)
-  * Fix migration releases (#9319) (#9326) (#9328)
-  * Fix File Edit: Author/Committer interchanged (#9297) (#9300)
-
-## [1.10.1](https://github.com/go-gitea/gitea/releases/tag/v1.10.1) - 2019-12-05
-
-* BUGFIXES
-  * Fix max length check and limit in multiple repo forms (#9148) (#9204)
-  * Properly fix displaying virtual session provider in admin panel (#9137) (#9203)
-  * Upgrade levelqueue to 0.1.0 (#9192) (#9199)
-  * Fix panic when diff (#9187) (#9193)
-  * Smtp logger configuration sendTos should be an array (#9154) (#9157)
-  * Always Show Password Field on Link Account Sign-in Page (#9150)
-  * Create PR on Current Repository by Default (#8670) (#9141)
-  * Fix race on indexer (#9136) (#9139)
-  * Fix reCAPTCHA URL (#9119)
-  * Hide migrated credentials (#9098)
-  * Update golang.org/x/crypto vendor to use acme v2 (#9056) (#9085)
-  * Fix password checks on admin create/edit user (#9076) (#9081)
-  * Fix add search as a reserved username (#9063) (#9065)
-  * Fix permission checks for close/reopen from commit (#8875) (#9033)
-  * Ensure Written is set in GZIP ProxyResponseWriter (#9018) (#9025)
-  * Fix broken link to branch from issue list (#9003) (#9021)
-  * Fix wrong system notice when repository is empty (#9020)
-  * Shadow password correctly for session config (#8984) (#9002)
-
-## [1.10.0](https://github.com/go-gitea/gitea/releases/tag/v1.10.0) - 2019-11-13
-
-* BREAKING
-  * Fix deadline on update issue or PR via API (#8698)
-  * Hide some user information via API if user doesn't have enough permission (#8655) (#8657)
-  * Remove legacy handling of drone token (#8191)
-  * Change repo search to use exact match for topic search. (#7941)
-  * Add pagination for admin api get orgs and fix only list public orgs bug (#7742)
-  * Implement the ability to change the ssh port to match what is in the gitea config (#7286)
-* SECURITY
-  * Fix issue with user.fullname (#8903)
-  * Ignore mentions for users with no access (#8395)
-  * Be more strict with git arguments (#7715)
-  * Extract the username and password from the mirror url (#7651)
-  * reserve .well-known username (#7637)
-* FEATURES
-  * Org/Members: display 2FA members states + optimize sql requests (#7621)
-  * SetDefaultBranch on pushing to empty repository (#7610)
-  * Adds side-by-side diff for images (#6784)
-  * API method to list all commits of a repository (#6408)
-  * Password Complexity Checks  (#6230)
-  * Add option to initialize repository with labels (#6061)
-  * Add additional password hash algorithms (#6023)
-* BUGFIXES
-  * Allow to merge if file path contains " or \ (#8629) (#8771)
-  * On windows set core.longpaths true (#8776) (#8786)
-  * Fix 500 when edit hook (#8782) (#8789)
-  * Fix Checkbox at RepoSettings Protected Branch (#8799) (#8801)
-  * Fix SSH2 conditional in key parsing code (#8806) (#8810)
-  * Fix commit expand button to not go to commit link (#8745) (#8825)
-  * Fix new user form for non-local users (#8826) (#8828)
-  * Fix to close opened io resources as soon as not needed (#8839) (#8846)
-  * Fix edit content button on migrated issue content (#8877) (#8884)
-  * Fix require external registration password (#8885) (#8890)
-  * Fix password complexity check on registration (#8887) (#8888)
-  * Update Github Migration Tests (#8896) (#8938) (#8945)
-  * Enable punctuations ending mentions (#8889) (#8894)
-  * Add Close() method to gogitRepository (#8901) (#8956)
-  * Hotfix for review actions and notifications (#8965)
-  * Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618)
-  * Fix milestone close timestamp (#8728) (#8730)
-  * Fix 500 when getting user as unauthenticated user (#8653) (#8663)
-  * Fix 'New Issue Missing Milestone Comment' (#8678) (#8681)
-  * Use AppSubUrl for more redirections (#8647) (#8651)
-  * Add SubURL to redirect path (#8632) (#8634)
-  * Fix template error on account page (#8562) (#8622)
-  * Allow externalID to be UUID (#8551) (#8624)
-  * Prevent removal of non-empty emoji panel following selection of duplicate (#8609) (#8623)
-  * Update heatmap fixtures to restore tests (#8615) (#8616)
-  * Ensure that diff stats can scroll independently of the diff (#8581) (#8621)
-  * Webhook: set Content-Type for application/x-www-form-urlencoded (#8600)
-  * Fix #8582 by handling empty repos (#8587) (#8594)
-  * Fix bug on pull requests when transfer head repository (#8564) (#8569)
-  * Add missed close in ServeBlobLFS (#8527) (#8542)
-  * Ensure that GitRepo is set on Empty repositories (#8539) (#8541)
-  * Fix migrate mirror 500 bug (#8526) (#8530)
-  * Fix password complexity regex for special characters (#8524)
-  * Prevent .code-view from overriding font on icon fonts (#8614) (#8627)
-  * Allow more than 255 characters for tokens in external_login_user table (#8554)
-  * Fix errors in create org UI regarding team access permission (#8506)
-  * Fix bug on FindExternalUsersByProvider (#8504)
-  * Create .ssh dir as necessary (#8486)
-  * IsBranchExist: return false if provided name is empty (#8485)
-  * Making openssh listen on SSH_LISTEN_PORT not SSH_PORT (#8477)
-  * Add check for empty set when dropping indexes during migration (#8471)
-  * LFS files are relative to LFS content path, ensure that when deleting they are made relative to this (#8455)
-  * Ensure Request Body Readers are closed in LFS server (#8454)
-  * Fix template bug on mirror repository setting page (#8438)
-  * Fix migration v96 to keep issue attachments (#8435)
-  * Update strk.kbt.io/projects/go/libravatar to latest (#8429)
-  * Singular form for files that has only one line (#8416)
-  * Check for either escaped or unescaped wiki filenames (#8408)
-  * Allow users with explicit read access to give approvals (#8382)
-  * Fix editor commit to new branch if PR disabled (#8375)
-  * readd .markdown class to all markup renderers (#8357)
-  * Upgrade xorm to v0.7.9 to fix some bugs (#8354)
-  * Fix column name ambiguity in GetUserIssueStats() (#8347)
-  * Change general form binding to gogs form (#8334)
-  * Fix pull request commit status in user dashboard list (#8321)
-  * Fix repo_admin_change_team_access always checked in org settings (#8319)
-  * Update to github.com/lafriks/xormstore@v1.3.0 (#8317)
-  * Show correct commit status in PR list (#8316)
-  * Bugfix for image compare and minor improvements to image compare (#8289)
-  * Update xorm (#8286)
-  * Fix API for edit and delete release attachment (#8285)
-  * Fix nil object access in some conditions when parsing cross references (#8281)
-  * Fix label count (#8267)
-  * Only show teams access for organization repositories on collaboration setting page (#8265)
-  * Test more reserved usernames (#8263)
-  * Rewrite reference processing code in preparation for opening/closing from comment references (#8261)
-  * Fix assets key on release webhook (#8253)
-  * Allow registration when button is hidden (#8237)
-  * Fix release API URL generation (#8234)
-  * Fix milestone num_issues (#8221)
-  * MS Teams webhook misses commit messages (#8209)
-  * Fix data race (#8204)
-  * Fix team user api (#8172)
-  * Fix pull merge 500 error caused by git-fetch breaking behaviors (#8161)
-  * Make show private icon when repo avatar set (#8144)
-  * Add reviewers as participants (#8121)
-  * Fix Go 1.13 private repository go get issue (#8112)
-  * feat: highlight issue references with : (#8101)
-  * Make AllowedUsers configurable in sshd_config (#8094)
-  * Strict name matching for Repository.GetTagID() (#8074)
-  * Avoid ambiguity of branch/directory names for the git-diff-tree command (#8066)
-  * Add change title notification for issues (#8061)
-  * [ssh] fix the config specification in the authorized_keys template (#8031)
-  * Fix reading git notes from nested trees (#8026)
-  * Fixes synchronize tags to releases for repository - makes sure we are only getting tag refs (#7990)
-  * Fix adding default Telegram webhook (#7972)
-  * Run CORS handler first for /api routes (#7967)
-  * Abort synchronization from LDAP source if there is some error. (#7960)
-  * Fix wrong sender when send slack webhook (#7918)
-  * Fix bug when migrating a private repository (#7917)
-  * Evaluate emojis in commit messages in list view (#7906)
-  * Fix upload file type check (#7890)
-  * lfs/lock: round locked_at timestamp to second (#7872)
-  * fix non existent milestone with 500 error instead of 404 (#7867)
-  * gpg/bugfix: Use .ExpiredUnix.IsZero to display green color of forever valid gpg key (#7846)
-  * Fix duplicate call of webhook (#7821)
-  * Enable switching to a different source branch when PR already exists (#7819)
-  * Convert files to utf-8 for indexing (#7814)
-  * Do not fetch all refs in pull-request compare (#7797)
-  * Fix multiple bugs with statuses endpoints at API (#7785)
-  * Restore functionality for early gits (#7775)
-  * Fix Slack webhook fork message (#7774)
-  * Rewrite existing repo units if setting is not included in api body (#7763)
-  * Fix rename failed when rewrite public keys (#7761)
-  * Fix approvals counting (#7757)
-  * Add migration step to remove old repo_indexer_status orphaned records (#7746)
-  * Fix repo_index_status lingering when deleting a repository (#7734)
-  * Remove camel case tokenization from repo indexer (#7733)
-  * Fix milestone completness calculation when migrating (#7725)
-  * Regression: Include "executable" files in the index, as they are not necessarily … (#7718)
-  * Fixes indexed repos keeping outdated indexes when files grow too large (#7712)
-  * Skip non-regular files (e.g. submodules) on repo indexing (#7711)
-  * Fix dropTableColumns sqlite implementation (#7710)
-  * Update gopkg.in/src-d/go-git.v4 to v4.13.1 (#7705)
-  * improve branches list performance and fix protected branch icon when no-login (#7695)
-  * Correct wrong datetime format for git (#7689)
-  * Move add to hook queue for created repo to outside xorm session. (#7675)
-  * sugestion to use range .Branches (#7674)
-  * Fix bug on migrating milestone from github (#7665)
-  * hide delete/restore button on archived repos (#7658)
-  * css: use flex to fix floating paginate (#7656)
-  * Fix syntax highlight initialization (#7617)
-  * Fix panic on push at - Merging pull request causes 500 error (#7615)
-  * Make PKCS8, PEM and SSH2 keys work (#7600)
-  * Fix mistake in arc-green.less split-diff css code. (#7587)
-  * Handle ErrUserProhibitLogin in http git (#7586)
-  * Fix bug create/edit wiki pages when code master branch protected (#7580)
-  * Fixes Malformed URLs in API git/commits response (#7565)
-  * Fix file header overflow in file and blame views (#7562)
-  * Improve SSH key parser to handle newlines in keys (#7522)
-  * Fix empty commits now showing in repo overview (#7521)
-  * Fix repository's pull request count error (#7518)
-  * Fix markdown invoke sequence (#7513)
-  * Remove duplicated webhook trigger (#7511)
-  * Update User.NumRepos atomically in createRepository (#7493)
-  * Fix settings page of repo you aren't admin print error - Settings pages giving UnitType error message (#7482)
-  * Fix redirection after file edit - Handles all redirects for Web UI File CRUD (#7478)
-  * cmd/serv: actually exit after fatal errors (#7458)
-  * Fix an issue with some pages throwing 'not defined' js exceptions (#7450)
-  * fix Dropzone.js integration (#7445)
-  * Fix regex for issues in commit messages (#7444)
-  * Diff: Fix indentation on unhighlighted code (#7435)
-  * Only show "New Pull Request" button if repo allows pulls (#7426)
-  * Upgrade macaron/captcha to fix random error problem (#7407)
-  * create class for inline positioned lists (#7393)
-  * Fetch refs for successful testing for tag (#7388)
-  * add missing template variable on organisation settings (#7385)
-  * fix post parameter - on issue list - unset assignee (#7380)
-  * fix/define autochecked checkboxes on issue list in firefox (#7320)
-  * only return head: null if source branch was deleted (#6705)
-* ENHANCEMENTS
-  * Add nofollow to sign in links (#8509)
-  * vendor: update mvdan.cc/xurls/v2 to v2.1.0 (#8495)
-  * Update milestone issues numbers when save milestone and other code improvements (#8411)
-  * Add extra user information when migrating release (#8331)
-  * Require overall success if no context is given for status check (#8318)
-  * Transaction-aware retry create issue to cope with duplicate keys (#8307)
-  * Change link on issue milestone (#8246)
-  * Alwaywas return local url for users avatar (#8245)
-  * Move some milestone functions to a standalone package (#8213)
-  * Move create issue comment to comments package (#8212)
-  * Disable max height property of comment textarea (#8203)
-  * Add 'Mentioning you' group to /issues page (#8201)
-  * oauth2 with remote Gitea (#8149)
-  * Reference issues from pull requests and other issues (#8137)
-  * Fix webhooks to use proxy from environment (#8116)
-  * Add merged commit id on pull view when it's merged (#8062)
-  * Add teams to repo on collaboration page. (#8045)
-  * Update swagger to 0.20.1  (#8010)
-  * Make link last commit massages in repository home page and commit tables (#8006)
-  * Add API endpoint for accessing repo topics (#7963)
-  * Include description in repository search (#7942)
-  * Use gitea forked macaron (#7933)
-  * Fix pull creation with empty changes (#7920)
-  * Allow token as authorization for accessing attachments (#7909)
-  * Retry create issue to cope with duplicate keys (#7898)
-  * Move git diff codes from models to services/gitdiff (#7889)
-  * migrate gplus to google oauth2 provider (#7885)
-  * Remove unique filter from repo indexer analyzer. (#7878)
-  * Detect delimiter in CSV rendering (#7869)
-  * Import topics during migration (#7851)
-  * Move CreateReview to modules/pull (#7841)
-  * vendor: update pdf.js to v2.1.266 (#7834)
-  * Support SSH_LISTEN_PORT env var in docker app.ini template (#7829)
-  * Add Ability for User to Customize Email Notification Frequency (#7813)
-  * Move database settings from models to setting (#7806)
-  * Display ui time with customize time location (#7792)
-  * Implement webhook branch filter (#7791)
-  * Restrict repository indexing by glob match (#7767)
-  * Api: advanced settings for repository (external wiki, issue tracker etc.) (#7756)
-  * Update migrated repositories' issues/comments/prs poster id if user has a github external user saved (#7751)
-  * deps: Upgrade gopkg.in/editorconfig/editorconfig-core-go.v1 (#7749)
-  * Apply emoji on commit graph page (#7743)
-  * Add a lot of extension to language mappings for syntax highlights (#7741)
-  * Add SQL execution on log and indexes on table repository and comment (#7740)
-  * Set DB connection error level to error (#7724)
-  * Check commit message hashes before making links (#7713)
-  * remove unnecessary fmt on generate bindata (#7706)
-  * Fix specific highlighting (CMakeLists.txt ...) (#7686)
-  * Add file status on API (#7671)
-  * Add support for DEFAULT_ORG_MEMBER_VISIBLE (#7669)
-  * Provide links in commit summaries in commits table/view list (#7659)
-  * Change length of some repository's columns (#7652)
-  * Move commit repo action from models to repofiles package (#7645)
-  * fix wrong email when use gitea as OAuth2 provider (#7640)
-  * [Branch View] add download button (#7604)
-  * Update to xorm@v0.7.4 (#7596)
-  * use 403 instead of 401 for ErrUserProhibitLogin (#7591)
-  * Removed unnecessary conversions (#7557)
-  * Un-lambda base.FileSize (#7556)
-  * Added missing error checks in tests (#7554)
-  * Move create release from models to a standalone package (#7539)
-  * Make default branch name link to default branch (#7519)
-  * Added total count of contributions to heatmap (#7517)
-  * Move mirror to a standalone package from models (#7486)
-  * Move models.PushUpdate to repofiles.PushUpdate (#7485)
-  * Include thread related headers in issue/coment mail (#7484)
-  * Refuse merge until all required status checks success (#7481)
-  * convert all js var to let/const (#7464)
-  * Only create branches for opened pull requestes when migrating from github (#7463)
-  * jQuery 3 (#7425)
-  * Add notification placeholder (#7409)
-  * Search Commits via Commit Hash (#7400)
-  * Move status table to cron package (#7370)
-  * wiki - page revisions list  (#7369)
-  * Display original author and URL information when showing migrated issues/comments (#7352)
-  * Refactor filetype is not allowed errors (#7309)
-  * switch to use gliderlabs/ssh for builtin server (#7250)
-  * Remove settting dependency on modules/session (#7237)
-  * Move all mail related codes from models to services/mailer (#7200)
-  * Support git.PATH entry in app.ini (#6772)
-  * Support setting cookie domain (#6288)
-  * Move migrating repository from frontend to backend (#6200)
-  * Delete releases attachments if release is deleted (#6068)
-* TRANSLATION
-  * Latvian translation for home page (#8468)
-  * Add home template italian translation (#8352)
-  * fix misprint (#7452)
-* BUILD
-  * use go 1.13 (#8088)
-* MISC
-  * add file line count info on UI (#8396)
-  * Make issues page left menu 100% width and add reponame as title attribute (#8359)
-  * [arc-green] white on hover for active menu items (#8344)
-  * Move ref (branch or tag) location on issue list page (#8157)
-  * apply emoji on dashboard issue list labels (#8156)
-  * 1148: Take up the full width when viewing the diff in split view. (#8114)
-  * Display description of 'make this repo private' as help text, not as tooltip (#8097)
-  * Fixes deformed emoji in pull request reviews (#8047)
-  * Add strike to old header on comment (#8046)
-  * Add tooltip for the visibility checkbox in /repo/create (#8025)
-  * Update github.com/lafriks/xormstore and tidy up mod.go (#8020)
-  * keep blame view buttons sequence consistent with normal view when view a file (#8007)
-  * Use "Pull Request" instead of "Merge Request" (#8003)
-  * Move line number to :before attr to hide from search on browser (#8002)
-  * Changed black color to white for (read) number label on issue list page (#8000)
-  * [Branch View] show "New Pull Request" Button only if posible (#7977)
-  * Fix hook problem by only setting the git environment variables if we are passed them (#7854)
-  * Prevent Commit Status and Message From Overflowing On Branch Page (#7800)
-  * Fix global search result CSS, misc CSS tweaks (#7789)
-  * Tweak label border CSS (#7739)
-  * Fix create menu item widths (#7708)
-  * [Branch View] Delete duplicate protection symbol (#7624)
-  * [Branch View] Delete Table Header (#7622)
-  * [Branch View] icons to buttons (#7602)
-  * update js dependencies (#7462)
-  * Add Extra Info to Branches Page (#7461)
-  * Bump lodash from 4.17.11 to 4.17.14 (#7459)
-  * wiki history improvements (#7391)
-  * ui fixes - compare view and archieved repo issues (#7345)
-  * dark theme scrollbars (#7269)
-  * wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243)
-  * Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141)
-
-## [1.9.6](https://github.com/go-gitea/gitea/releases/tag/v1.9.6) - 2019-11-13
-
-* BUGFIXES
-  * Allow to merge if file path contains " or \ (#8629) (#8772)
-  * Fix 500 when edit hook (#8782) (#8790)
-  * Fix issue with user.fullname (#8904)
-  * Update Github Migration Test (#8897) (#8946)
-  * Add Close() method to gogitRepository (#8901) (#8958)
-
-## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
-
-* BREAKING
-  * Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
-* BUGFIXES
-  * Fix milestone close timestamp (#8728) (#8731)
-  * Fix deadline on update issue or PR via API (#8699)
-  * Fix 'New Issue Missing Milestone Comment' (#8678) (#8682)
-  * Fix 500 when getting user as unauthenticated user (#8653) (#8662)
-  * Use AppSubUrl for more redirections (#8647) (#8652)
-  * Add SubURL to redirect path (#8632) (#8634) (#8640)
-  * Fix #8582 by handling empty repos (#8587) (#8593)
-  * Fix bug on pull requests when transfer head repository (#8571)
-  * Add missed close in ServeBlobLFS (#8527) (#8543)
-  * Return false if provided branch name is empty for IsBranchExist (#8485) (#8492)
-  * Create .ssh dir as necessary (#8369) (#8486) (#8489)
-  * Restore functionality for early gits (#7775) (#8476)
-  * Add check for empty set when dropping indexes during migration (#8475)
-  * Ensure Request Body Readers are closed in LFS server (#8454) (#8459)
-  * Ensure that LFS files are relative to the LFS content path (#8455) (#8458)
-* SECURITY
-  * Ignore mentions for users with no access (#8395) (#8484)
-* TESTING
-  * Update heatmap fixtures to restore tests (#8615) (#8617)
-
-## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
-
-* BUGFIXES
-  * Highlight issue references (#8101) (#8404)
-  * Fix bug when migrating a private repository #7917 (#8403)
-  * Change general form binding to gogs form (#8334) (#8402)
-  * Fix editor commit to new branch if PR disabled (#8375) (#8401)
-  * Fix milestone num_issues (#8221) (#8400)
-  * Allow users with explicit read access to give approvals (#8398)
-  * Fix commit status in PR #8316 and PR #8321 (#8339)
-  * Fix API for edit and delete release attachment (#8290)
-  * Fix assets on release webhook (#8283)
-  * Fix release API URL generation (#8239)
-  * Allow registration when button is hidden (#8238)
-  * MS Teams webhook misses commit messages (backport v1.9) (#8225)
-  * Fix data race (#8206)
-  * Fix pull merge 500 error caused by git-fetch breaking behaviors (#8194)
-  * Fix the SSH config specification in the authorized_keys template (#8193)
-  * Fix reading git notes from nested trees (#8189)
-  * Fix team user api (#8172) (#8188)
-  * Add reviewers as participants (#8124)
-* BUILD
-  * Use vendored go-swagger (#8087) (#8165)
-  * Fix version-validation for GO 1.13 (go-macaron/cors) (#8389)
-* MISC
-  * Make show private icon when repo avatar set (#8144) (#8175)
-
-## [1.9.3](https://github.com/go-gitea/gitea/releases/tag/v1.9.3) - 2019-09-06
-
-* BUGFIXES
-  * Fix go get from a private repository with Go 1.13 (#8100)
-  * Strict name matching for Repository.GetTagID() (#8082)
-  * Avoid ambiguity of branch/directory names for the git-diff-tree command (#8070)
-  * Add change title notification for issues (#8064)
-  * Run CORS handler first for /api routes (#7967) (#8053)
-  * Evaluate emojis in commit messages in list view (#8044)
-  * Fix failed to synchronize tags to releases for repository (#7990) (#7994)
-  * Fix adding default Telegram webhook (#7972) (#7992)
-  * Abort synchronization from LDAP source if there is some error (#7965)
-  * Fix deformed emoji in commit message (#8071)
-* ENHANCEMENTS
-  * Keep blame view buttons sequence consistent with normal view when viewing a file (#8007) (#8009)
-
-## [1.9.2](https://github.com/go-gitea/gitea/releases/tag/v1.9.2) - 2019-08-22
-
-* BUGFIXES
-  * Fix wrong sender when send slack webhook (#7918) (#7924)
-  * Upload support text/plain; charset=utf8 (#7899)
-  * Lfs/lock: round locked_at timestamp to second (#7872) (#7875)
-  * Fix non existent milestone with 500 error (#7867) (#7873)
-* SECURITY
-  * Fix No PGP signature on 1.9.1 tag (#7874)
-  * Release built with go 1.12.9 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!msg/golang-announce/oeMaeUnkvVE/a49yvTLqAAAJ
-* ENHANCEMENTS
-  * Fix pull creation with empty changes (#7920) (#7926)
-* BUILD
-  * Drone/docker: prepare multi-arch release + provide arm64 image (#7571) (#7884)
-
-## [1.9.1](https://github.com/go-gitea/gitea/releases/tag/v1.9.1) - 2019-08-14
-
-* BREAKING
-  * Add pagination for admin api get orgs and fix only list public orgs bug (#7742) (#7752)
-* SECURITY
-  * Be more strict with git arguments (#7715) (#7762)
-  * Release built with go 1.12.8 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!topic/golang-nuts/fCQWxqxP8aA
-* BUGFIXES
-  * Fix local runs of ssh-requiring integration tests (#7855) (#7857)
-  * Fix hook problem (#7856) (#7754)
-  * Use .ExpiredUnix.IsZero to display green color of forever valid gpg key (#7850) (#7846)
-  * Do not fetch all refs (#7797) (#7837)
-  * Fix duplicate call of webhook (#7824) (#7821)
-  * Enable switching to a different source branch when PR already exists (#7823)
-  * Rewrite existing repo units if setting is not included in api body (#7811)
-  * Prevent Commit Status and Message From Overflowing On Branch Page (#7800) (#7808)
-  * API: fix multiple bugs with statuses endpoints (Backport #7785) (#7807)
-  * Fix Slack webhook fork message (1.9 release backport) (#7783)
-  * Fix approvals counting (#7757) (#7777)
-  * Fix rename failed when rewrite public keys (#7761) (#7769)
-  * Fix dropTableColumns sqlite implementation (#7710) (#7765)
-  * Fix repo_index_status lingering when deleting a repository (#7738)
-  * Fix milestone completness calculation when migrating (#7725) (#7732)
-  * Fixes indexed repos keeping outdated indexes when files grow too large (#7731)
-  * Skip non-regular files (e.g. submodules) on repo indexing (#7717)
-  * Improve branches list performance and fix protected branch icon when no-login (#7695) (#7704)
-  * Correct wrong datetime format for git (#7689) (#7690)
-
-## [1.9.0](https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - 2019-07-30
-
-* BREAKING
-  * Better logging (#6038) (#6095)
-* SECURITY
-  * Shadow the password on cache and session config on admin panel (#7300)
-  * Fix markdown invoke sequence (#7513) (#7560)
-  * Reserve .well-known username (#7638)
-  * Do not leak secrets via timing side channel (#7364)
-  * Ensure that decryption of cookie actually suceeds (#7363)
-* FEATURES
-  * Content API for Creating, Updating, Deleting Files (#6314)
-  * Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
-  * Add command to convert mysql database from utf8 to utf8mb4 (#7144)
-  * Fixes #2738 - Adds the /git/tags API endpoint (#7138)
-  * Compare branches, commits and tags with each other (#6991)
-  * Show Pull Request button or status of latest PR in branch list (#6990)
-  * Repository avatars (#6986)
-  * Show git-notes (#6984)
-  * Add commit statuses reports on pull request view (#6845)
-  * Number of commits ahead/behind in branch overview (#6695)
-  * Add CLI commands to manage LDAP authentication source (#6681)
-  * Add support for MS Teams webhooks (#6632)
-  * OAuth2 Grant UI (#6625)
-  * Add SUBJECT_PREFIX mailer config option (#6605)
-  * Include custom configuration file in dump (#6516)
-  * Add API for manipulating Git hooks (#6436)
-  * Improve migrations to support migrating milestones/labels/issues/comments/pullrequests (#6290)
-  * Add option to blame files (#5721)
-  * Implement Default Webhooks (#4299)
-  * Telegram webhook (#4227)
-* BUGFIXES
-  * Send webhook after commit when creating issue with assignees (#7681) (#7684)
-  * Upgrade macaron/captcha to fix random error problem (#7407) (#7683)
-  * Move add to hook queue for created repo to outside xorm session. (#7682) (#7675)
-  * Show protection symbol if needed on default branch (#7660) (#7668)
-  * Hide delete/restore button on archived repos (#7660)
-  * Fix bug on migrating milestone from github (#7665) (#7666)
-  * Use flex to fix floating paginate (#7656) (#7662)
-  * Change length of some repository's columns (#7652) (#7655)
-  * Fix wrong email when use gitea as OAuth2 provider (#7640) (#7647)
-  * Fix syntax highlight initialization (#7617) (#7626)
-  * Fix bug create/edit wiki pages when code master branch protected (#7580) (#7623)
-  * Fix panic on push at #7611 (#7615) (#7618)
-  * Handle ErrUserProhibitLogin in http git (#7586, #7591) (#7590)
-  * Fix color of split-diff view in dark theme (#7587) (#7589)
-  * Fix file header overflow in file and blame views (#7562) (#7579)
-  * Malformed URLs in API git/commits response (#7565) (#7567)
-  * Fix empty commits now showing in repo overview (#7521) (#7563)
-  * Fix repository's pull request count error (#7518) (#7524)
-  * Remove duplicated webhook trigger (#7511) (#7516)
-  * Handles all redirects for Web UI File CRUD (#7478) (#7507)
-  * Fix regex for issues in commit messages (#7444) (#7466)
-  * cmd/serv: actually exit after fatal errors (#7458) (#7460)
-  * Fix an issue with some pages throwing 'not defined' js exceptions #7450 (#7453)
-  * Fix Dropzone.js integration (#7445) (#7448)
-  * Create class for inline positioned lists (#7439) (#7393)
-  * Diff: Fix indentation on unhighlighted code (#7435) (#7443)
-  * jQuery 3 (#7442) (#7425)
-  * Only show "New Pull Request" button if repo allows pulls (#7426) (#7432)
-  * Fix vendor references (#7394) (#7396)
-  * Only return head: null if source branch was deleted (#6705) (#7376)
-  * Add missing template variable on organisation settings (#7386) (#7385)
-  * Fix post parameter on issue list which had unset assignee (#7380) (#7383)
-  * Fix migration tests due to issue 7 being resolved (#7375) (#7381)
-  * Correctly adjust mirror url (#6593)
-  * Handle early git version's lack of get-url (#7065)
-  * Fix icon position in issue view (#7354)
-  * Cut timeline length with last element on issue view (#7355)
-  * Fix mirror repository webhooks (#7366)
-  * Fix api route for hooks (#7346)
-  * Fix bug conflict between SyncReleasesWithTags and InsertReleases (#7337)
-  * Fix pull view ui merge section (#7335)
-  * Fix 7303 - remove unnessesary buttons on archived repos (#7326)
-  * Fix topic bar to allow prefixes (#7325)
-  * Fixes #7152 - Allow create/update/delete message to be empty, use default message (#7324)
-  * Fixes #7238 - Annotated tag commit ID incorrect (#7321)
-  * Dark theme fixes (#7319)
-  * Gitea own dark codemirror theme (#7317)
-  * Fixes #7292 - API File Contents bug (#7301)
-  * Fix API link header (#7298)
-  * Fix extra newlines when copying from diff in Firefox (#7288)
-  * Make diff line-marker non-selectable (#7279)
-  * Fix Submodule dection in subdir (#7275)
-  * Fix error log when loading issues caused by a xorm bug (#7271)
-  * Add .fa icon margin like .octicon (#7258)
-  * Fix hljs unintenionally highlighting commit links (#7244)
-  * Only check and config git on web subcommand but not others (#7236)
-  * Fix migration panic when Head.User is not exist (#7226)
-  * Only warn on errors in deleting LFS orphaned files during repo deletion (#7213)
-  * Fix duplicated file on pull request conflicted files (#7211)
-  * Allow colon between fixing word and issue (#7207)
-  * Fix overflow issues in repo (#7190)
-  * API error cleanup (#7186)
-  * Add error for fork already existing (#7185)
-  * Fixes diff on merged pull requests (#7171)
-  * If milestone id is zero don't get it from database (#7169)
-  * Fix pusher name via ssh push (#7167)
-  * Fix database lock when use random repository fallback image (#7166)
-  * Various fixes for issue mail notifications (#7165)
-  * Allow archived repos to be (un)starred and (un)watched (#7163)
-  * Fix GCArgs load from ini (#7156)
-  * Detect noreply email address as user (#7133)
-  * Avoid arbitrary format strings upon calling fail() function (#7112)
-  * Validate External Tracker URL Format (#7089)
-  * Repository avatar fallback configuration (#7087)
-  * Fix #732: Add LFS objects to base repository on merging  (#7082)
-  * Install page - Handle invalid administrator username better (#7060)
-  * Workaround for posting single comments in split diff view (#7052)
-  * Fix possbile mysql invalid connnection error (#7051)
-  * Fix charset was not saved after installation finished (#7048)
-  * Handle insecure and ports in go get (#7041)
-  * Avoid bad database state after failed migration (#7040)
-  * Fix wrong init dependency on markup extensions (#7038)
-  * Fix default for allowing new organization creation for new users (#7017)
-  * Fix content download and /verify LFS handler expecting wrong content-type (#7015)
-  * Fix missing repo description when migrating (#7000)
-  * Fix LFS Locks over SSH (#6999)
-  * Do not attempt to return blob on submodule (#6996)
-  * Fix U2F for Chrome >= 74 (#6980)
-  * Fix index produces problem when issues/pulls deleted (#6973)
-  * Allow collaborators to view repo owned by private org (#6965)
-  * Stop running hooks on pr merge (#6963)
-  * Run hooks on merge/edit and cope with protected branches (#6961)
-  * Webhook Logs show proper HTTP Method, and allow change HTTP method in form (#6953)
-  * Stop colorizing log files by default (#6949)
-  * Rotate serv.log, http.log and hook logs and stop stacktracing in these (#6935)
-  * Fix plain text overflow line wrap (#6915)
-  * Fix input size for dependency select (#6913)
-  * Change drone token name to let users know to use oauth2 (#6912)
-  * Fix syntax highlight in blame view #6895 (#6909)
-  * Use AppURL for Oauth user link (#6894)
-  * Fixes #6881 - API users search fix (#6882)
-  * Fix 404 when send pull request some situation  (#6871)
-  * Enforce osusergo build tag for releases (#6862)
-  * Fix 500 when reviewer is deleted with integration tests (#6856)
-  * Fix v85.go (#6851)
-  * Make dropTableColumns drop columns on sqlite and constraints on all (#6849)
-  * Fix double-generation of scratch token (#6832) (#6833)
-  * When mirroring we should set the remote to mirror (#6824)
-  * Fix the v78 migration "Drop is_bare" on MSSQL #6707 (#6823)
-  * Change verbose flag in dump command to avoid colliding with global version flag (#6822)
-  * Fix #6813: Allow git.GetTree to take both commit and tree names (#6816)
-  * Remove `seen` map from `getLastCommitForPaths` (#6807)
-  * Show scrollbar only when needed (#6802)
-  * Restore IsWindows variable assignment (#6722) (#6790)
-  * Service worker js is a missing comma (#6788)
-  * Fix team edit API panic (#6780)
-  * Set user search base field optional in LDAP (simple auth) edit page (#6779)
-  * Ignore already existing public keys after ldap sync (#6766)
-  * Fix pulls broken when fork repository deleted (#6754)
-  * Fix missing return (#6751)
-  * Fix new team 500 (#6749)
-  * OAuth2 token can be used in basic auth (#6747)
-  * Fix org visibility bug when git cloning (#6743)
-  * Fix bug when sort repos on org home page login with non-admin (#6741)
-  * Stricter domain name pattern in email regex (#6739)
-  * Fix admin template error (#6737)
-  * Drop is_bare IDX only when it exists for MySQL and MariaDB (#6736)
-  * UI: Detect and restore encoding and BOM in content  (#6727)
-  * Load issue attributes when editing an issue with API (#6723)
-  * Fix team members API (#6714)
-  * Unfortunately MemProvider Init does not actually Init properly (#6692)
-  * Fix partial reversion of #6657 caused by #6314 (#6685)
-  * Prevent creating empty sessions (#6677)
-  * Fixes #6659 - Swagger schemes selection default to page's protocol (#6660)
-  * Update highlight.js to 9.15.6 (#6658)
-  * Properly escape on the redirect from the web editor (#6657)
-  * Fix #6655 - Don't EscapePound .Link as it is already escaped (#6656)
-  * Use ctx.metas for SHA hash links (#6645)
-  * Fix wrong GPG expire date (#6643)
-  * upgrade version of lib/pq to v1.1.0 (#6640)
-  * Fix forking an empty repository (#6637)
-  * Fix issuer of OTP URI should be URI-encoded. (#6634)
-  * Return a UserList from /api/v1/admin/users (#6629)
-  * Add json tags for oauth2 form (#6627)
-  * Remove extra slash from twitter card (#6619)
-  * remove bash requirement in makefile (#6617)
-  * Fix Open Graph og:image link (#6612)
-  * Fix cross-compile builds (#6609)
-  * Change commit summary to full message in API (#6591)
-  * Fix bug user search API pagesize didn't obey ExplorePagingNum (#6579)
-  * Prevent server 500 on compare branches with no common history (#6555)
-  * Properly escape release attachment URL (#6512)
-  * Delete local branch when repo branch is deleted (#6497)
-  * Fix bug when user login and want to resend register confirmation email (#6482)
-  * Fix upload attachments (#6481)
-  * Avoid multi-clicks in oauth2 login (#6467)
-  * Hacky fix for alignment of the create-organization dialog (#6455)
-  * Change order that PostProcess Processors are run (#6445)
-  * Clean up ref name rules (#6437)
-  * Fix Hook & HookList in Swagger (#6432)
-  * Fixed unitTypeCode not being used in accessLevelUnit (#6419)
-  * Display correct error for invalid mirror interval (#6414)
-  * Don't Unescape redirect_to cookie value (#6399)
-  * Fix dump table name error and add some test for dump database (#6394)
-  * Fix migrations 82 to ignore unsynced tags between database and git data and missing is_archived on repository table (#6387)
-  * Make sure units of a team are returned (#6379)
-  * Fix bug manifest.json will not request with cookie so that session will created every request (#6372)
-  * Disable benchmarking during tag events on DroneIO (#6365)
-  * Comments list performance optimization (#5305)
-* ENHANCEMENTS
-  * Update Drone docker generation to standard format (#7480) (#7496) (#7504)
-  * Add API Endpoint for Repo Edit (#7006)
-  * Add state param to milestone listing API (#7131)
-  * Make captcha and password optional for external accounts (#6606)
-  * Detect migrating batch size (#7353)
-  * Fix 7255 - wrap long texts on user profile info (#7333)
-  * Use commit graph files for listing pages (#7314)
-  * Add git command line commitgraph support global default true when git version >= 2.18 (#7313)
-  * Add LFS_START_SERVER option to control git-lfs support (#7281)
-  * Dark theme markdown fixes (#7260)
-  * Update go-git to v4.12.0 (#7249)
-  * Show lfs config on admin panel (#7220)
-  * Disable same user check for internal SSH (#7215)
-  * Add LastLogin to the User API (#7196)
-  * Add missing description of label on API (#7159)
-  * Use go method to calculate ssh key fingerprint (#7128)
-  * Enable Rust highlighting (#7125)
-  * Refactor submodule URL parsing (#7100)
-  * Change issue mail title. (#7064)
-  * Use batch insert on migrating repository to make the process faster (#7050)
-  * Improve github downloader on migrations (#7049)
-  * When git version >= 2.18, git command could run with git wire protocol version 2 param if enabled (#7047)
-  * Fix Erlang and Elixir highlight mappings (#7044)
-  * API Org Visibility (#7028)
-  * Improve handling of non-square avatars (#7025)
-  * Bugfix: Align comment label and actions to the right (#7024)
-  * Change UpdateRepoIndex api to include watchers (#7012)
-  * Move serv hook functionality & drop GitLogger (#6993)
-  * Add support of utf8mb4 for mysql (#6992)
-  * Make webhook http connections resuable (#6976)
-  * Move xorm logger bridge from log to models so that log module could be a standalone package (#6944)
-  * Refactor models.NewRepoContext to extract git related codes to modules/git (#6941)
-  * Remove macaron dependent on models (#6940)
-  * Add less linter via npx (#6936)
-  * Remove macaron dependent on modules/log (#6933)
-  * Remove macaron dependent on models/mail.go (#6931)
-  * Clean less files (#6921)
-  * Fix code overflow (#6914)
-  * Style orgs list in user profile (#6911)
-  * Improve description of branch protection (fix #6886) (#6906)
-  * Move sdk structs to modules/structs (#6905)
-  * update sdk to latest (#6903)
-  * Escape the commit message on issues update and title in telegram hook (#6901)
-  * SearchRepositoryByName improvements and unification (#6897)
-  * Change the color of issues/pulls list, merged is purple and closed is red (#6874)
-  * Refactor table width to have more info shown in file list (#6867)
-  * Monitor all git commands; move blame to git package and replace git as a variable (#6864)
-  * Fix config ui error about cache ttl (#6861)
-  * Improve localization of git activity stats (#6848)
-  * Generate access token in admin cli (#6847)
-  * Update github.com/urfave/cli to version 1.2.0 (#6838)
-  * Rename LFS_JWT_SECRET cli option to include OAUTH2 as well (#6826)
-  * internal/ssh: ignore env command totally (#6825)
-  * Allow Recaptcha service url to be configured (#6820)
-  * update github.com/mcuadros/go-version to v0.0.0-20190308113854-92cdf37c5b75 (#6815)
-  * Use modules/git for git commands (#6775)
-  * Add GET requests to webhook (#6771)
-  * Move PushUpdate dependency from models to repofiles (#6763)
-  * Tweak tab text and icon colors (#6760)
-  * Ignore non-standard refs in git push (#6758)
-  * Disable web preview for telegram webhook (#6719)
-  * Show full name if DEFAULT_SHOW_FULL_NAME setting enabled (#6710)
-  * Reorder file actions (#6706)
-  * README WordPress the code is overflowing #6679 (#6696)
-  * Improve issue reference on commit (#6694)
-  * Handle redirects for git clone commands (#6688)
-  * Fix one performance/correctness regression in #6478 found on Rails repository. (#6686)
-  * API OTP Context (#6674)
-  * Remove local clones & make hooks run on merge/edit/upload (#6672)
-  * Bump github.com/stretchr/testify from 1.2.2 to 1.3.0 (#6663)
-  * Bump gopkg.in/src-d/go-git.v4 from 4.8.0 to 4.10.0 (#6662)
-  * Fix dropdown icon padding (#6651)
-  * Add more title attributes on shortened names (#6647)
-  * Update UI for topics labels on projects (#6639)
-  * Trace Logging on Permission Denied & ColorFormat (#6618)
-  * Add .gpg url (match github behaviour) (#6610)
-  * Support for custom GITEA_CUSTOM env var in docker(#6608)
-  * Show "delete branch" button on closed pull requests (#6570) (#6601)
-  * Add option to disable refresh token invalidation (#6584)
-  * Fix new repo dropdown alignment (#6583)
-  * Fix mail notification when close/reopen issue (#6581)
-  * Pre-calculate the absolute path of git (#6575)
-  * Minor CSS cleanup for the navbar (#6553)
-  * Render SHA1 links as code blocks (#6546)
-  * Add username flag in create-user command (#6534)
-  * Unifies pagination template usage (#6531) (#6533)
-  * Fixes pagination width on mobile view (#5711) (#6532)
-  * Improve SHA1 link detection (#6526)
-  * Fixes #6446 - Sort team members and team's repositories (#6525)
-  * Use stricter boundaries for auto-link detection (#6522)
-  * Use regular line-height on frontpage entries (#6518)
-  * Fixes #6514 - New Pull Request on files and pulls pages the same (#6515)
-  * Make distinction between DisplayName and Username in email templates (#6495)
-  * Add X-Auto-Response-Suppress header to outgoing messages (#6492)
-  * Cleaned permission checks for API -> site admin can now do anything (#6483)
-  * Support search operators for commits search (#6479)
-  * Improve listing performance by using go-git (#6478)
-  * Fix repo sub_menu font color in arc-green (#6477)
-  * Show last commit status in pull request lists (#6465)
-  * Add signatures to webhooks (#6428)
-  * Optimize all images in public/img (#6427)
-  * Add golangci (#6418)
-  * Make "Ghost" not link to 404 page (#6410)
-  * Include more variables on admin/config page (#6378)
-  * Markdown: enable some more extensions (#6362)
-  * Include repo name in page title tag (#6343)
-  * Show locale string on timestamp (#6324)
-  * Handle CORS requests (#6289)
-  * Improve issue autolinks (#6273)
-  * Migration Tweaks (#6260)
-  * Add title attributes to all items in the repo list viewer (#6258)
-  * Issue indexer queue redis support (#6218)
-  * Add bio field for user (#6113)
-  * Make the version within makefile overwriteable (#6080)
-  * Updates to API 404 responses (#6077)
-  * Use Go1.11 module (#5743)
-  * UX + Security current user password reset (#5042)
-  * Refactor: append, build variable and type switch (#4940)
-  * Git statistics in Activity tab (#4724)
-  * Drop the bits argument when generating an ed25519 key (#6504)
-* TESTING
-  * Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
-  * Refactor and improve git test (#7086)
-  * Fix TestSearchRepo by waiting till indexing is done (#7004)
-  * Add mssql migration tests (needs #6823) (#6852)
-  * Add tests for Org API (#6731)
-  * Context.ServerError and NotFound should log from their caller (#6550)
-* TRANSLATION
-  * Add french specific rule for translating plural texts (#6846)
-* BUILD
-  * Update mssql driver to last working version 20180314172330-6a30f4e59a44 (#7306)
-  * Alpine 3.10 (#7256)
-  * Use vfsgen instead of go-bindata (#7080)
-  * remove and disable package-lock (#6969)
-  * add make targets for js and css, add js linter (#6952)
-  * Added tags pull step to drone config to show correct version hashes i… (#6836)
-  * Make CustomPath, CustomConf and AppWorkPath configurable at build (#6631)
-  * chore: update drone format to 1.0 (#6602)
-  * Fix race in integration testlogger (#6556)
-  * Quieter Integration Tests (#6513)
-  * Drop the docker Makefile from the image (#6507)
-  * Add make version on gitea version (#6485)
-  * Fix #6468 - Uses space match and adds newline for all sed flavors (#6473)
-  * Move code.gitea.io/git to code.gitea.io/gitea/modules/git (#6364)
-  * Update npm dependencies and various tweaks (#7344)
-  * Fix updated drone file (#7336)
-  * Add 'npm' and 'npm-update' make targets and lockfile (#7246)
-* DOCS
-  * Add work path CLI option (#6922)
-  * Fix logging documentation (#6904)
-  * Some logging documentation (#6498)
-  * Fix link to Hacking on Gitea on From-Source doc page (#6471)
-  * Fix typos in docs command-line examples (#6466)
-  * Added docker example for backup (#5846)
-
-## [1.8.3](https://github.com/go-gitea/gitea/releases/tag/v1.8.3) - 2019-06-17
-
-* BUGFIXES
-  * Always set userID on LFS authentication (#7224) (Part of #6993)
-  * Fix LFS Locks over SSH (#6999) (#7223)
-  * Fix duplicated file on pull request conflicted files (#7211) (#7214)
-  * Detect noreply email address as user (#7133) (#7195)
-  * Don't get milestone from DB if ID is zero (#7169) (#7174)
-  * Allow archived repos to be (un)starred and (un)watched (#7163) (#7168)
-  * Fix GCArgs load from ini (#7156) (#7157)
-
-## [1.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
-
-* BUGFIXES
-  * Fix possbile mysql invalid connnection error (#7051) (#7071)
-  * Handle invalid administrator username on install page (#7060) (#7063)
-  * Disable arm7 builds (#7037) (#7042)
-  * Fix default for allowing new organization creation for new users (#7017) (#7034)
-  * SearchRepositoryByName improvements and unification (#6897) (#7002)
-  * Fix u2f registrationlist ToRegistrations() method (#6980) (#6982)
-  * Allow collaborators to view repo owned by private org (#6965) (#6968)
-  * Use AppURL for Oauth user link (#6894) (#6925)
-  * Escape the commit message on issues update (#6901) (#6902)
-  * Fix regression for API users search (#6882) (#6885)
-  * Handle early git version's lack of get-url (#7065) (#7076)
-  * Fix wrong init dependency on markup extensions (#7038) (#7074)
-
-## [1.8.1](https://github.com/go-gitea/gitea/releases/tag/v1.8.1) - 2019-05-08
-
-* BUGFIXES
-  * Fix 404 when sending pull requests in some situations (#6871) (#6873)
-  * Enforce osusergo build tag for releases (#6862) (#6869)
-  * Don't post process commit summary in templates (#6842) (#6868)
-  * Fix 500 when reviewer is deleted (#6856) (#6860)
-  * Fix v78 migration for MSSQL (#6823) (#6854)
-  * Added tags pull step to drone config to show correct version hashes (#6836) (#6839)
-  * Fix double-generation of scratch token (#6833) (#6835)
-  * When mirroring we should set the remote to mirror (#6824) (#6834)
-  * Show scrollbar only when needed (#6802) (#6803)
-  * Service worker js is missing a comma (#6788) (#6795)
-  * Set user search base field optional in LDAP (simple auth) edit page (#6779) (#6789)
-  * Fix team edit API panic (#6780) (#6785)
-  * Minor CSS cleanup for the navbar (#6553) (#6781)
-  * Stricter domain name pattern in email regex (#6739) (#6768)
-  * Detect and restore encoding and BOM in content (#6727) (#6765)
-  * Fix org visibility bug when git cloning (#6743) (#6762)
-  * OAuth2 token can be used in basic auth (#6747) (#6761)
-  * Fix missing return (#6751) (#6756)
-  * Fix sorting repos on org home page with non-admin login (#6741) (#6746)
-  * Drop is_bare IDX only when it exists for MySQL and MariaDB (#6736) (#6744)
-  * Fix team members API (#6714) (#6729)
-  * Load issue attributes when editing an issue with API (#6723) (#6725)
-  * Fix config ui error about cache ttl (#6861) (#6865)
-
-## [1.8.0](https://github.com/go-gitea/gitea/releases/tag/v1.8.0) - 2019-04-20
-
-* SECURITY
-  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6594)
-  * Resolve 2FA bypass on API (#6676) (#6674)
-  * Prevent the creation of empty sessions for non-logged in users (#6690) (#6677)
-* BREAKING
-  * Add "ghost" and "notifications" to list of reserved user names. (#6208)
-  * Change sqlite DB path default to data directory (#6198)
-  * Adds MustChangePassword to user create/edit API (#6193)
-  * Disable redirect for i18n (#5910)
-  * Releases API paging (#5831)
-  * Allow Macaron to be set to log through to gitea.log (#5667)
-  * Don't close issues via commits on non-default branch (#5622)
-* FEATURES
-  * Add regenerate secret feature for oauth2 (#6291)
-  * Expose issue stopwatch toggling via API (#5970)
-  * Add other session providers (#5963)
-  * Pull request conflict files detection (#5951)
-  * Integrate OAuth2 Provider (#5378)
-  * Implement "conversation lock" for issue comments (#5073)
-  * Feature: Archive repos (#5009)
-  * Discord Oauth2 support (#4476)
-  * Allow to set organization visibility (public, internal, private) (#1763)
-  * Added URL mapping for Release attachments like on github.com (#1707)
-* ENHANCEMENTS
-  * Add support for client basic auth for exchanging access tokens (#6293)
-  * Add ability to sort issues by due date (#6206) (#6244)
-  * Style tweaks to issue selection (#6196)
-  * Increase Username and Orgname MaxSize 35 -> 40 (#6178)
-  * Coverage profile with multiple packages (#6167)
-  * Split setting.go to multiple files (#6154)
-  * Allow labels to contain emoji (#6063)
-  * Disable git fsck for mirrored repos by default (#6018)
-  * Add default time out for git operations (#6015)
-  * Split setting.go as multiple files (#6014)
-  * Make dashboard navbar and footer full-width (#6013)
-  * Add lang specific font stacks for CJK (#6007)
-  * Fix header menu misalignment (#6002)
-  * Enhance closed PR and Issue status in the list (#6000)
-  * Make navbar full width (#5998)
-  * Add option to close issues via commit on a non master branch (#5992)
-  * Support n as a line highlight prefix (#5987)
-  * Search for org repos (#3031) (#5986)
-  * Minor UI tweaks (#5980)
-  * Use native golang SSH library but ssh-keygen when enable built-in SSH server to remove dependent on that command lines (#5976)
-  * Dashboard tweaks (#5974)
-  * Fixes for repo topic editor (#5971)
-  * Display the branch name in the commit view (#5950)
-  * handle milestone events for issues and PR (#5947)
-  * Add label names as filter in issue search api (#5946)
-  * Repo header tweaks (#5945)
-  * Better support for long repo names (#5932)
-  * Fix wrapping long code lines (#5927)
-  * Change GPG Validation colors and remove inline CSS (#5404) (#5896)
-  * Fix "pulls.blocked_by_approvals" text (#5879)
-  * Rename reject to 'request changes' (#5858)
-  * Move input fields to add members to a team and repos to a team (#5853)
-  * Config option to disable automatic repo watching (#5852)
-  * New Issue ?body= query (#5851)
-  * Add API to list tags (#5850)
-  * Pagination for git tree API (#5838)
-  * Add InternalTokenURI to load InternalToken from an external file (#5812)
-  * Allow markdown files to read from the LFS (#5787)
-  * Add the ability to use multiple labels as filters (#5786)
-  * Adjust log settings when a user is not found. (#5771)
-  * Log IP of failed ssh connection (#5766)
-  * Moved defaults in defaults.go to setting.go (#5764)
-  * Make DB connect more robust (#5738)
-  * Add Default Pull Request Title (#5735)
-  * Refactor repo.isBare to repo.isEmpty #5629 (#5714)
-  * Add flag to skip repository dumping (#5695)
-  * Prioritize "readme.md" (#5691)
-  * Improve "Fork button" for guests by showing a pop up asking them to log in before forking (#5690)
-  * Allow for user specific themes (#5668)
-  * Display branch name in delete branch confirmation modal. (#5654)
-  * New API routes added (#5594)
-  * Refactor notification for indexer (#5111)
-  * Refactor mail notification (#5110)
-  * Show email if the authenticated user owns the profile page being requested for (#4981)
-  * Optimize pulls merging (#4921)
-  * Sort Repositories widget by most recently updated (#3963) (#4599)
-  * Allow markdown table to scroll (#4401)
-  * Automatically clear stopwatch on merging a PR (#4327)
-  * Add the Owner Name to differentiate when merging (#3807)
-  * Add title attributes to all items in the repo list viewer (#6258) (#6650)
-* BUGFIXES
-  * Fix dropdown icon padding (#6651) (#6654)
-  * Fix wrong GPG expire date (#6643) (#6644)
-  * Fix forking an empty repository (#6637) (#6653)
-  * Remove call to EscapePound .Link as it is already escaped (#6656) (#6666)
-  * Properly escape on the redirect from the web editor (#6657) (#6667)
-  * Allow resend of confirmation email when logged in (#6482) (#6486)
-  * Fix mail notification when close/reopen issue (#6581) (#6588)
-  * Change API commit summary to full message (#6591) (#6592)
-  * Add option to disable refresh token invalidation (#6584) (#6587)
-  * Fix bug user search API pagesize didn't obey ExplorePagingNum (#6579) (#6586)
-  * Fix new repo alignment (#6583) (#6585)
-  * Prevent server 500 on compare branches with no common history (#6555) (#6558)
-  * Properly escape release attachment URL (#6512) (#6523)
-  * Hacky fix for alignment of the create-organization dialog (#6455) (#6462)
-  * Disable benchmarking during tag events on DroneIO (#6365) (#6366)
-  * Make sure units of a team are returned (#6379) (#6381)
-  * Don't Unescape redirect_to cookie value (#6399) (#6401)
-  * Fix dump table name error and add some test for dump database (#6394) (#6402)
-  * Fix migration v82 to ignore unsynced tags between database and git data; Add missing is_archived column on repository table (#6387) (#6403)
-  * Display correct error for invalid mirror interval (#6414) (#6429)
-  * Clean up ref name rules (#6437) (#6439)
-  * Fix Hook & HookList in Swagger (#6432) (#6440)
-  * Change order that PostProcess Processors are run (#6445) (#6447)
-  * Clean up various use of escape/unescape functions for URL generation (#6334)
-  * Return 409 when creating repo if it already exists. (#6330)
-  * Add same changes from issues page to milestone->issues page (#6328)
-  * Fix ParsePatch function to work with quoted diff --git strings (#6323)
-  * Fix reported issue in repo description (#6306)
-  * Use url.PathEscape to escape the branchname (#6304)
-  * Add robots.txt as reserved username (#6272)
-  * Replace linkRegex with xurls library (#6261)
-  * Remove visitLinksForShortLinks features (#6257)
-  * Add unit types to repo action URL to correctly show 404 when archived (#6247)
-  * Check organization visibility before everything else (#6234) (#6235)
-  * Prevent double-close of issues (#6233)
-  * Override xorm type mapping for U2F counter (#6232)
-  * Add isAdmin to user API response (#6231)
-  * Update git vendor to fix wrong release commit id and add migrations (#6224)
-  * Fix fork button (#6223)
-  * Fix renames over redirects (#6216)
-  * Fix display dashboard even if require to change password (#6214)
-  * Create a repo redirect when transferring ownership (#6210) (#6211)
-  * Fix issue update race condition (#6194)
-  * Fix bug when migrate repository 500 when repo is existed (#6188)
-  * Fix scrollbar always present on page body (#6177)
-  * Fix bug when set indexer as db and add tests (#6173)
-  * Modify linkRegex to require http|https (#6171)
-  * Fix bug user could change private repository to public when force private enabled. (#6156)
-  * Fix admin list user/org API (#6143)
-  * Make repo creation for API similar to UI (#6142)
-  * Make document body a flexbox (#6139)
-  * Refactor issue indexer, add some testing and fix a bug (#6131)
-  * Load Issue attributes for API call (#6122)
-  * Fix bug when update owner team then visit team's repo return 404 (#6119)
-  * Fix heatmap and repository menu display in Internet Explorer 9+ (#6117)
-  * Show private organization for admin, fix #6111 (#6112)
-  * Fix prohibit login check on authorization (#6106)
-  * Move to ldap.v3 to fix #5928 (#6105)
-  * Remove use MakeAssigneeList in webhooks to fix deadlock (#6102)
-  * Allow display of LFS stored Readme.md on directory page (#6073) (#6099)
-  * Make sure labels are actually returned (#6053)
-  * Fix panic: template: repo/issue/list:210: unexpected "=" in operand (#6041)
-  * After deleting a repo on admin panel, UI should remember the last sort type (#6033)
-  * Default create repository on organisation on its dashboard (#6026)
-  * Swagger: Remove spaces in MergePullRequestOption enum (#6016)
-  * Fix metrics auth token detection (#6006)
-  * Fix repo header issues (#5995)
-  * Fix bug when deleting a linked account will removed all (#5989)
-  * Make organization dropdown scrollable when using mouse wheel (#5988)
-  * Fix empty ssh key importing in ldap (#5984)
-  * Admin config page mailertype setting option update (#5973)
-  * Fix redirect loop during forced password change (#5965)
-  * Show user who created the repository instead of the organisation in action feed (#5948)
-  * Remove all CommitStatus when a repo is deleted (#5940)
-  * Fix ssh deploy and user key constraints (#1357) (#5939)
-  * Fix log output (#5938)
-  * Set PusherName and PusherID to owner on deploy key to fix pushing with deploy keys (#5935)
-  * Fix compare button (#5929)
-  * Fix bug when read public repo lfs file (#5912)
-  * Only allow local login if password is non-empty (#5906)
-  * Recover panic in orgmode.Render if bad orgfile (#4982) (#5903)
-  * Provide better panic handling (#5902)
-  * Respect value of REQUIRE_SIGNIN_VIEW (#5901)
-  * Show a 404 not a 500 if a repo does not exist (#5900)
-  * Ensure repo is loaded in mailer (Completely fix #5891) (#5895)
-  * Ensure issue.Poster is loaded in mailIssueCommentToParticipants (#5891)
-  * Correct footer height if screen-width is to small (fixes #5878) (#5889)
-  * In gitea serv switch off console logger to fix #5866 (#5887)
-  * Don't allow pull requests to be created on an archived repository (#5883)
-  * Support reviews on a deleted file path (#5880)
-  * Fix compare button on upstream repo leading to 404 (#5877)
-  * Fix null pointer on not logged in attempt to Sudo (#5872)
-  * Fix new release creation API to allow empty target (#5870)
-  * Fix an error while adding a dependency via UI. (#5862)
-  * Fix failing migration v67 (#5849)
-  * Fix delete correct temp directory (#5839)
-  * Make sure .git/info is created before generating .git/info/sparse-che… (#5825)
-  * Fix topics saving internal error and disable for archived repos (#5821)
-  * Fix TLS errors when using acme/autocert for local connections (#5820)
-  * When creating new repository fsck option should be enabled (#5817)
-  * Request for public keys only if LDAP attribute is set  (#5816)
-  * Fix serving of raw wiki files other than .md (#5814)
-  * Fix migration 78 error mssql (#5791)
-  * Disallow empty titles (#5785)
-  * Fix the v78 migration script (#5776)
-  * Ensure valid git author names passed in signatures (#5774)
-  * Fix wrong assumption where a user is always said to have unassigned (her)himself (#5769)
-  * Upgrade go-sql-driver/mysql to fix invalid connection error (#5748)
-  * Fixing PostgreSQL dump creation (#5747)
-  * Add proper CORS preflight origin validation (#5740)
-  * Disable auto-migrate in docker container (#5730)
-  * In basic auth check for tokens before call UserSignIn (#5725)
-  * Pooled and buffered gzip implementation (#5722)
-  * Ensure that sessions are passed into queries that could use the database to prevent deadlocks (#5718)
-  * Keep file permissions during database migration (#5707)
-  * Use correct value for "MSpan Structures Obtained" #4742 (#5706)
-  * Refactor editor upload, update and delete to use git plumbing and add LFS support (#5702)
-  * Update xorm to fix issue #5659 and #5651 (#5680)
-  * Fix public will not be reused as public key after deleting as deploy key (#5671)
-  * When redirecting, clean the path (#5669)
-  * Don't list an issue on its own dependency list UI. (#5658)
-  * Fix commit page showing status for current default branch (#5649) (#5650)
-  * Only count users own actions for heatmap contributions (#5647)
-  * Fix sqlite deadlock when assigning to a PR (#5640)
-  * Refactor issue indexer (#5363)
-* TESTING
-  * Run benchmark at tag to track performances (#6035)
-  * Add test environment for MySQL8 (#5234)
-* BUILD
-  * Use go 1.12 for tests and deprecate go 1.9 (#6186)
-  * Makefile changes for Windows and easier development (#6103)
-  * Update bleve dependency to latest master revision (#6100)
-  * Switch to more recent build of xgo (#6070)
-  * Add autoprefixer to css build (#6029)
-  * Update the version of less (#6010)
-  * Make log mailer for testing (#5893)
-* DOCS
-  * Add more tests and docs for issue indexer, add db indexer type for searching from database (#6144)
-  * update default value of `--must-change-password` cli flag (#6032)
-  * Update and expand information about building Gitea (#6019)
-  * Update U2F Section of app.ini.sample (#5994)
-  * Update swagger for release API pagination (#5841)
-  * Added docs for the tree api (#5834)
-* MISC
-  * Add single commit API support (#5843)
-  * Add missing GET teams endpoints (#5382)
-  * Migrate database if app.ini found (#5290)
-
-## [1.7.6](https://github.com/go-gitea/gitea/releases/tag/v1.7.6) - 2019-04-12
-
-* SECURITY
-  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6595)
-* BUGFIXES
-  * Allow resend of confirmation email when logged in (#6482) (#6487)
-
-## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
-
-* BUGFIXES
-  * Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
-  * Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
-  * Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
-
-## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
-
-* SECURITY
-  * Fix potential XSS vulnerability in repository description. (#6306) (#6308)
-* BUGFIXES
-  * Fix wrong release commit id (#6224) (#6300)
-  * Fix panic on empty signed commits (#6292) (#6300)
-  * Fix organization dropdown not being scrollable when using mouse wheel (#5988) (#6246)
-  * Fix displaying dashboard even if required to change password (#6214) (#6215)
-
-## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
-
-* BUGFIXES
-  * Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
-  * Load Issue attributes for API /repos/{owner}/{repo}/issues/{index} (#6122) (#6185)
-  * Fix bug whereby user could change private repository to public when force private enabled. (#6156) (#6165)
-  * Fix bug when update owner team then visit team's repo return 404 (#6119) (#6166)
-  * Fix heatmap and repository menu display in Internet Explorer 9+ (#6117) (#6137)
-  * Fix prohibit login check on authorization (#6106) (#6115)
-  * Fix LDAP protocol error regression by moving to ldap.v3 (#6105) (#6107)
-  * Fix deadlock in webhook PullRequest (#6102) (#6104)
-  * Fix redirect loop when password change is required and Gitea is installed as a suburl (#5965) (#6101)
-  * Fix compare button regression (#5929) (#6098)
-  * Recover panic in orgmode.Render if bad orgfile (#4982) (#5903) (#6097)
-
-## [1.7.2](https://github.com/go-gitea/gitea/releases/tag/v1.7.2) - 2019-02-14
-
-* BUGFIXES
-  * Remove all CommitStatus when a repo is deleted (#5940) (#5941)
-  * Fix notifications on pushing with deploy keys by setting hook environment variables (#5935) (#5944)
-  * Silence console logger in gitea serv (#5887) (#5943)
-  * Handle milestone webhook events for issues and PR (#5947) (#5955)
-  * Show user who created the repository instead of the organization in action feed (#5948) (#5956)
-  * Fix ssh deploy and user key constraints (#1357) (#5939) (#5966)
-  * Fix bug when deleting a linked account will removed all (#5989) (#5990)
-  * Fix empty ssh key importing in ldap (#5984) (#6009)
-  * Fix metrics auth token detection (#6006) (#6017)
-  * Create repository on organisation by default on its dashboard (#6026) (#6048)
-  * Make sure labels are actually returned in API (#6053) (#6059)
-  * Switch to more recent build of xgo (#6070) (#6072)
-  * In basic auth check for tokens before call UserSignIn (#5725) (#6083)
-
-## [1.7.1](https://github.com/go-gitea/gitea/releases/tag/v1.7.1) - 2019-01-31
-
-* SECURITY
-  * Disable redirect for i18n (#5910) (#5916)
-  * Only allow local login if password is non-empty (#5906) (#5908)
-  * Fix go-get URL generation (#5905) (#5907)
-* BUGFIXES
-  * Fix TLS errors when using acme/autocert for local connections (#5820) (#5826)
-  * Request for public keys only if LDAP attribute is set (#5816) (#5819)
-  * Fix delete correct temp directory (#5840) (#5839)
-  * Fix an error while adding a dependency via UI (#5862) (#5876)
-  * Fix null pointer in attempt to Sudo if not logged in (#5872) (#5884)
-  * When creating new repository fsck option should be enabled (#5817) (#5885)
-  * Prevent nil dereference in mailIssueCommentToParticipants (#5891) (#5895) (#5894)
-  * Fix bug when read public repo lfs file (#5913) (#5912)
-  * Respect value of REQUIRE_SIGNIN_VIEW (#5901) (#5915)
-  * Fix compare button on upstream repo leading to 404 (#5877) (#5914)
-* DOCS
-  * Added docs for the tree api (#5835)
-* MISC
-  * Include Go toolchain to --version (#5832) (#5830)
-
-## [1.7.0](https://github.com/go-gitea/gitea/releases/tag/v1.7.0) - 2019-01-22
-
-* SECURITY
-  * Do not display the raw OpenID error in the UI (#5705) (#5712)
-  * When redirecting clean the path to avoid redirecting to external site (#5669) (#5679)
-  * Prevent DeleteFilePost doing arbitrary deletion (#5631)
-* BREAKING
-  * Restrict permission check on repositories and fix some problems (#5314)
-  * Show only opened milestones on issues page milestone filter (#5051)
-* FEATURES
-  * Implement git refs API for listing references (branches, tags and other) (#5354)
-  * Approvals at Branch Protection (#5350)
-  * Add raw blob endpoint to get objects by SHA ID (#5334)
-  * Add api for user to create org (#5268)
-  * Create AuthorizedKeysCommand (#5236)
-  * User action heatmap (#5131)
-  * Refactor heatmap to vue component (#5401)
-  * Webhook for Pull Request approval/rejection (#5027)
-  * Add command for migrating database (#4954)
-  * Search keyword by splitting provided values by , (#4939)
-  * Create Progressive Web App (#4730)
-  * Give user a link to create PR after push (#4716)
-  * Add rebase with merge commit merge style (#3844) (#4052)
-* BUGFIXES
-  * Disallow empty titles (#5785) (#5794)
-  * Fix sqlite deadlock when assigning to a PR (#5640) (#5642)
-  * Don't close issues via commits on non-default branch. (#5622) (#5643)
-  * Fix commit page showing status for current default branch (#5650) (#5653)
-  * Only count users own actions for heatmap contributions (#5647) (#5655)
-  * Update xorm to fix issue postgresql dumping issues (#5680) (#5692)
-  * Use correct value for "MSpan Structures Obtained" (#5706) (#5716)
-  * Fix bug on modifying sshd username (#5624)
-  * Delete tags in mirror which are removed for original repo. (#5609)
-  * Fix wrong text getting saved on editing second comment on an issue. (#5608)
-  * Fix nil pointer when adding a due date  (#5587)
-  * Fix type mismatch of format string (#5574)
-  * Fix bug on upload file name (#5571)
-  * Issue is not overdue when it is on the same date #5566 (#5568)
-  * Fix indexer reindex bug when gitea restart (#5563)
-  * Fix table name typo on SQL (#5562)
-  * Synchronize SSH keys on login with LDAP + Fix SQLite deadlock on ldap ssh key deletion (#5557)
-  * Fix makefile generate buildstep (#5556)
-  * Fix nil pointer base branch bug (#5555)
-  * Fix permission check on api create org (#5523)
-  * Fix detect force push failure on deletion of protected branches (#5522)
-  * Fix approvals limitation (#5521)
-  * Fix bug when a read perm user to edit his issue (#5516)
-  * Fix adding reaction fail for read permission user (#5515)
-  * Fixing MSSQL timestamp type (#5511)
-  * Fix forgot deletion of notification when delete repository (#5506)
-  * Fix empty wiki (#5504)
-  * Fix clone wiki failed via ssh (#5503)
-  * Fix code review on mssql (#5502)
-  * Fix lfs version check warning log when using ssh protocol (#5501)
-  * Fix topic name length on database (#5493)
-  * Ensure that the `closed_at` is set for closed issues (#5449)
-  * Admin should be able to delete repos via the API even if he is not a member of the organization (#5443)
-  * Word-Break the WebHook url to prevent a ui-break (#5432)
-  * Fix forgot removed records when deleting user (#5429)
-  * Fix repository deletion when there is large number of issues in it (#5426)
-  * Fix heatmap colors for Chrome/Safari (#5421)
-  * Fix password variable shadowing (#5405)
-  * Fix dependent issue searching when gitea is run in subpath (#5392)
-  * Don't force a password change for the admin user when creating an account via cli (#5391)
-  * API: '/orgs/:org/repos': return private repos with read access (#5383)
-  * Don't send assign webhooks when creating issue (#5365)
-  * Removing Labels via EditPullRequest API (#5348)
-  * Migration fixes for gogs (0.11.66) to gitea (1.6.0) #5318 (#5341)
-  * Fix bug when users have serval teams with different units on different repositories (#5307)
-  * Fix U2F if gitea is configured in subpath (#5302)
-  * Fix file edit change preview functionality (#5300)
-  * Update gitignore list (#5258)
-  * Fixed heatmap not working in mssql (#5248)
-  * Fixed wrong api request url for instances running in subfolders (#5247)
-  * Fix compatibility heatmap with mysql 8 (#5232)
-  * Fix data race on migrate repository (#5224)
-  * Fix sqlite and mssql lock (#5214)
-  * Fix sqlite lock (#5210)
-  * Fix: Accept web-command cli flags if web-command is commited (#5200)
-  * Fix: Add secret to all webhook's payload where it has been missing (#5199)
-  * Fix race on updatesize (#5190)
-  * Fix create team, update team missing units (#5188)
-  * Fix sqlite lock (#5184 & #5176)
-  * Fix showing pull request link when delete a branch (#5166)
-  * Fix JSON result of empty array in heatmap data array (#5154)
-  * Update build tags for sqlite_unlock notify (#5144)
-  * This commit will reduce join star, repo_topic, topic tables on repo search, so that fix extra columns problem on mssql (#5136)
-  * Fix deadlock when sqlite (#5118)
-  * Add comment replies (#5104)
-  * Fix home page template regression (#5102)
-  * Fix regex to support optional end line of old section in diff hunk (#5096)
-  * LDAP via simple auth separate bind user and search base (#5055)
-  * Fix markdown image with link (#4675)
-  * Fix to 3819 - Filtering issues by tags on main screen issues (#3824)
-* ENHANCEMENTS
-  * Delete organization endpoint added (#5601)
-  * Update Licenses (#5558)
-  * Support reverse proxy providing email (#5554)
-  * Add git protocol v2 support via SSH on Docker image (#5520)
-  * Add tests for api user orgs (#5494)
-  * Allow link verification for services like Mastodon (#5481)
-  * Improve team members and repositories settings UI (#5457)
-  * Remove the required class from optional ssh port in installation page (#5428)
-  * Explicitly disable Git credential helper (#5367)
-  * Setting Labels via EditPullRequest API (#5347)
-  * Implement pasting image from clipboard for browsers that supports that (#5317)
-  * Milestone issues and pull requests (#5293)
-  * Support envs on external render commands (#5278)
-  * Add option to disable automatic mirror syncing. (#5242)
-  * Remove unused db init on commands serv, update, hooks (#5225)
-  * Serve audio files using HTML5 audio tag (#5221)
-  * Pass link prefixes to external markup parsers (#5201)
-  * Add AutoHead functionality. (#5186)
-  * Fix emojis not showing in commit messages (#5168)
-  * Block registration based on email domain (#5157)
-  * Update vendor/go-sqlite3 (#5133 & #5162)
-  * Update x/net lib (#5169)
-  * Show review summary in pull requests (#5132)
-  * Use type switch (#5122)
-  * Remove duplicated if bodies (#5121)
-  * Remove check for negative length (#5120)
-  * Make switch more clear (#5119)
-  * Use named const instead of a raw string (#5115)
-  * Fix issue where ecdsa and other key types are not synced from LDAP (#5092) (#5094)
-  * Refactor: err != nil check, just return error instead (#5093)
-  * Add notification interface and refactor UI notifications (#5085)
-  * Use APP_NAME on home page (#5048)
-  * Explicitly decide whether to  use TLS in mailer's configuration (#5024)
-  * Generate random password (#5023)
-  * UX of link account (Step 1) (#5006)
-  * Make sure argsSet verifies string isn't empty too (#4980)
-  * Improve performance of dashboard (#4977)
-  * Keys API changes (#4960)
-  * Add must-change-password flag to cli for creating a user (#4955)
-  * Use native go method to get current user rather than environment variable (#4930)
-  * Make gitea serv use api/internal (#4886)
-  * Add support for search by uid (#4876)
-  * Allow to add organization members as collaborators on organization owned repositories (#4748)
-* TESTING
-  * Kill testing processes if the test takes too long (#5174)
-  * Update outdated Go toolchain version for .drone.yml (#5146)
-  * Increase the retry limit to 20 times and the interval to 200ms (#5134)
-  * Retry test-fixtures loading in case of transaction rollback (#5125)
-  * Added test environment for mssql (#4282)
-* BUILD
-  * Replace lint to revive (#5422)
-  * Update golang version in Dockerfile (#5246)
-* DOCS
-  * Typo in routers/api/v1/org/org.go fixed. (#5598)
-  * Update the docs for sqlite_unlock_notify (#5145)
-  * CN translation of docs part (#5049)
-  * Kubernetes deployment file (#5046)
-* MISC
-  * Upgrade alpine to 3.8 (#5423)
-  * Git-Trees API (#5403)
-  * Only chown directories during docker setup if necessary. Fix #4425 (#5064)
-
-## [1.6.4](https://github.com/go-gitea/gitea/releases/tag/v1.6.4) - 2019-01-15
-
-* BUGFIX
-  * Fix SSH key now can be reused as public key after deleting as deploy key (#5671) (#5685)
-  * When redirecting clean the path to avoid redirecting to external site (#5669) (#5703)
-  * Fix to use correct value for "MSpan Structures Obtained" (#5706) (#5715)
-
-## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
-
-* SECURITY
-  * Prevent DeleteFilePost doing arbitrary deletion (#5631)
-* BUGFIX
-  * Fix wrong text getting saved on editing second comment on an issue (#5608)
-
-## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
-
-* SECURITY
-  * Sanitize uploaded file names (#5571) (#5573)
-  * HTMLEncode user added text (#5570) (#5575)
-* BUGFIXES
-  * Fix indexer reindex bug when gitea restart (#5563) (#5564)
-  * Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
-  * Fix bug when a read perm user to edit his issue (#5516) (#5534)
-  * Detect force push failure on deletion of protected branches (#5522) (#5531)
-  * Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
-  * Fix forgot deletion of notification when delete repository (#5506) (#5514)
-  * Fix undeleted content when deleting user (#5429) (#5509)
-  * Fix empty wiki (#5504) (#5508)
-
-## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
-
-* BUGFIXES
-  * Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
-  * API: '/orgs/:org/repos': return private repos with read access (#5393)
-  * Fix repository deletion when there is large number of issues in it (#5426) (#5434)
-  * Word-break the WebHook url to prevent a ui-break (#5445)
-  * Admin should be able to delete repos via the API even if they are not a member of the organization (#5443) (#5447)
-  * Ensure that the `closed_at` is set for closed (#5450)
-  * Fix topic name length on database (#5493) (#5495)
-
-## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
-
-* BREAKING
-  * Respect email privacy option in user search via API (#4512)
-  * Simply remove tidb and deps (#3993)
-  * Swagger.v1.json template (#3572)
-* SECURITY
-  * Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
-  * Improve URL validation for external wiki  and external issues (#4710)
-  * Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
-  * Don't disclose emails of all users when sending out emails (#4664)
-  * Check that repositories can only be migrated to own user or organizations (#4366)
-* FEATURES
-  * Add comment replies (#5147) (#5104)
-  * Pull request review/approval and comment on code (#3748)
-  * Added dependencies for issues (#2196) (#2531)
-  * Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
-  * Add sudo functionality to the API (#4809)
-  * Add oauth providers via cli (#4591)
-  * Disable merging a WIP Pull request (#4529)
-  * Force user to change password (#4489)
-  * Add letsencrypt to Gitea (#4189)
-  * Add push webhook support for mirrored repositories (#4127)
-  * Add csv file render support defaultly (#4105)
-  * Add Recaptcha functionality to Gitea (#4044)
-* ENHANCEMENTS
-  * Fix milestones sorted wrongly (#4987)
-  * Allow api to create tags for releases if they don't exist (#4890)
-  * Fix #4877 to follow the OpenID Connect Audiences spec (#4878)
-  * Enforce token on api routes [fixed critical security issue #4357] (#4840)
-  * Update legacy branch and tag URLs in dashboard to new format (#4812)
-  * Slack webhook channel name cannot be empty or just contain an hashtag (#4786)
-  * Add whitespace handling to PR-comparsion (#4683)
-  * Make reverse proxy auth optional (#4643)
-  * MySQL TLS (#4642)
-  * Make sure to set PR split view when creating/previewing a pull request  (#4617)
-  * Log user in after a successful sign up (#4615)
-  * Fix typo IsPullReuqestBroken -> IsPullRequestBroken (#4578)
-  * Allow admin toggle forcing a password change for newly created users (#4563)
-  * Update jQuery to v1.12.4 (#4551)
-  * Env var GITEA_PUSHER_EMAIL (#4516)
-  * Feat(repo): support search repository by topic name (#4505)
-  * Small improvements to dependency UI (#4503)
-  * Make max commits in graph configurable (#4498)
-  * Add valid for lfs oid (#4461)
-  * Add shortcut to save wiki page (#4452)
-  * Allow administrator to create repository for any organization (#4368)
-  * Fix repository last updated time update when delete a user who watched the repo (#4363)
-  * Switch plaintext scratch tokens to use hash instead (#4331)
-  * Increase default TOTP secret size to 320 bits (#4287)
-  * Keep preseeded database password (#4284)
-  * Implemented hover text showing user FullName (#4261)
-  * Add ability to delete a token (#4235)
-  * Fix typos in i18n variable names. (#4080)
-  * Api: repos/search: add parameters to control the sort order (#3964)
-  * Add missing path in the Docker app.ini template (#2181)
-  * Add file name and branch to page title (#4902)
-  * Offline use of google fonts (#4872)
-  * Add missing History link to directory listings v2 (#4829)
-  * Locale for Edit and Remove due date issue (#4802)
-  * Disable 'May Import Local Repository' when is disabled by setting (Is… (#4780)
-  * API /admin/users/{username} missing parameter (#4775)
-  * Display error when adding a user to a team twice (#4746)
-  * Remove UsePrivilegeSeparation from the Docker sshd_config, see #2876 (#4722)
-  * Focus title input when clicking helper link (#4696)
-  * Add vendor to user reserved words and format words list according alphabet (#4685)
-  * Add gitea/issues link to 500 page (#4654)
-  * Hide home button when landing page is not set to home (#4651)
-  * Remove link to GitHub issues in 404 template (#4639)
-  * Cmd/serve: pprof cpu and memory profile dumps to disk (#4560)
-  * Add flash message after an account has been successfully activated (#4510)
-  * Prevent html entity escaping on delete branch (#4471)
-  * Locale for button Edit on protected branch (#4442)
-  * Update notification icon (#4343)
-  * Added front-end topics validation (#4316)
-  * Don't display buttons if there are no system notifications (#4280)
-  * Issue due date api (#3890)
-* BUGFIXES
-  * dont' send assign webhooks when creating issue (#5365)
-  * Fix create team, update team missing units (#5188)
-  * Fix file edit change preview functionality (#5300)
-  * *ix bug when users have serval teams with different units on different repositories (#5307)
-  * Fix U2F if gitea is configured in subpath (#5302)
-  * Fix markdown image with link (#4675)
-  * Remove maxlines option for file logger (#5282)
-  * Fix wrong api request url for instances running in subfolders (#5261) (#5247)
-  * Accept web-command cli flags if web-command is commited (#5245) (#5200)
-  * Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
-  * Fix data race on migrate repository (#5224) (#5230)
-  * Add secret to all webhook's payload where it has been missing (#5208) (#5199)
-  * Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
-  * Fix race on updatesize (#5190) (#5215)
-  * Fix filtering issues by tags on main screen issues (#5219) (#3824)
-  * Fix SQL quoting (#5137) (#5117)
-  * Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
-  * Fix release creation via API (#5076)
-  * Remove links from topics in edit mode  (#5026)
-  * Fix missing AppSubUrl in few more templates (fixup) (#5021)
-  * Fix missing AppSubUrl in some templates (#5020)
-  * Hide outdated comments in file view (#5017)
-  * Upgrade gopkg.in/testfixtures.v2 (#4999)
-  * Disable debug routes unless PPROF is enabled in configuration (#4995)
-  * Fix user menu item styling (#4985)
-  * Fix layout of the topics editing form (#4971)
-  * Fix null pointer dereference in ParseCommitWithSignature (#4962)
-  * Fix url in discord webhook (#4953)
-  * Detect charset and convert non UTF-8 files for display (#4950)
-  * Make sure to catch the right error so it is displayed on the UI (#4945)
-  * Fix(topics): don't redirect to explore page. (#4938)
-  * Fix bug forget to remove Stopwatch when remove repository (#4928)
-  * Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
-  * Fix: Crippled diff (#4726) (#4900)
-  * Fix trimming of markup section names (#4863)
-  * Issues api allow pulls and fix #4832 (#4852)
-  * Do not autocreate directory for new users/orgs (#4828) (#4849)
-  * Fix redirect with non-ascii branch names (#4764) (#4810)
-  * Fix missing release title in webhook (#4783) (#4796)
-  * User shouldn't be able to approve or reject his/her own PR (#4729)
-  * Make sure to reset commit count in the cache on mirror syncing (#4720)
-  * Fixed bug where team with admin privelege type doesn't get any unit  (#4719)
-  * Fix incorrect caption of webhook setting (#4701) (#4717)
-  * Allow WIP marker to contains < or > (#4709)
-  * Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
-  * Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
-  * Fix custom templates being ignored (#4638)
-  * Fix starring icon after semantic ui update (#4628)
-  * Fix Split-View line adjustment (#4622)
-  * Fix integer constant overflows in tests (#4616)
-  * Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
-  * Fix bugs when too many IN variables (#4594)
-  * Fix failure on creating pull request with assignees (#4419) (#4583)
-  * Fix panic issue on update avatar email (#4580) (#4581)
-  * Fix status code label for a successful webhook (#4540)
-  * An inactive user shouldn't be able to be added as a collaborator (#4535)
-  * Don't fail silently if trying to add a collaborator twice (#4533)
-  * Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
-  * Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
-  * Fix migration from older releases (#4495)
-  * Accept 'Data:' in commit graph (#4487)
-  * Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
-  * Relative URLs for LibreJS page (#4460)
-  * Redirect to correct page after using scratch token (#4458)
-  * Fix column droping for MSSQL that need new transaction for that (#4440)
-  * Replace src with raw to fix image paths (#4377)
-  * Add default merge options when creating new repository (#4369)
-  * Fix docker build (#4358)
-  * Fixes repo membership check in API (#4341)
-  * Dep upgrade mysql lib (#4161)
-  * Fix some issues with special chars in branch names (#3767)
-  * Responsive design fixes (#4508)
-* TRANSLATION
-  * Fix punctuation in English translation (#4958)
-  * Fix translation (#4355)
-
-## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
-
-* SECURITY
-  * Fix remote command execution vulnerability in upstream library (#5177) (#5196)
-
-## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
-
-* SECURITY
-  * Enforce token on api routes (#4840) (#4905)
-* BUGFIXES
-  * Remove links from topics in edit mode (#5030)
-  * Detect charset and convert non UTF-8 files for display (#4950) (#4994)
-  * Fix layout of the topics editing form (#4971) (#4993)
-  * Fix null pointer dereference in ParseCommitWithSignature (#4964)
-  * Fix url in discord webhook (#4951)
-  * Fix font-cropping UI bug in diff (#4726) (#4929)
-  * Fix bug forget to remove Stopwatch when remove repository (#4933)
-  * Fix bug when repo remained bare if multiple branches pushed (#4927)
-  * Fix redirect with non-ascii branch names (#4764) (#4887)
-  * Fix issues api allow pulls (#4852) (#4862)
-  * Fix trimming of markup section names (#4864)
-
-## [1.5.1](https://github.com/go-gitea/gitea/releases/tag/v1.5.1) - 2018-09-03
-
-* SECURITY
-  * Don't disclose emails of all users when sending out emails (#4784)
-  * Improve URL validation for external wiki and external issues (#4710) (#4740)
-  * Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706) (#4707)
-* BUGFIXES
-  * Fix missing release title in webhook (#4783) (#4800)
-  * Make sure to reset commit count in the cache on mirror syncing (#4770)
-  * Fixed bug where team with admin privelege type doesn't get any unit (#4759)
-  * Fix failure on creating pull request with assignees (#4583) (#4727)
-  * Hide org/create menu item in Dashboard if user has no rights (#4678) (#4686)
-* TRANSLATION
-  * Fix incorrect caption of webhook setting (#4701) (#4718)
-
-## [1.5.0](https://github.com/go-gitea/gitea/releases/tag/v1.5.0) - 2018-08-10
-
-* SECURITY
-  * Check that repositories can only be migrated to own user or organizations (#4366) (#4370)
-  * Limit uploaded avatar image-size to 4096px x 3072px by default (#4353)
-  * Do not allow to reuse TOTP passcode (#3878)
-* BUGFIXES
-  * Fix column droping for MSSQL that need new transaction for that (#4440) (#4484)
-  * Redirect to correct page after using scratch token (#4458) (#4472)
-  * Replace src with raw to fix image paths (#4377) (#4386)
-  * Fixes repo membership check in API (#4341) (#4379)
-  * Add default merge options when adding new repository (#4369) (#4373)
-  * Fix repository last updated time update when delete a user who watched the repo (#4363) (#4371)
-  * Fix html entity escaping in branch deletion message (#4471) (#4485)
-  * Fix out-of-transaction query in removeOrgUser (#4521) (#4524)
-  * Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519)
-  * Fix panic issue on update avatar email (#4580) (#4590)
-  * Fix bugs when too many IN variables (#4594) (#4597)
-  * Push whitelist now doesn't apply to branch deletion (#4601) (#4640)
-  * Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645) (#4650)
-* FEATURES
-  * Add cli commands to regen hooks & keys (#3979)
-  * Add support for FIDO U2F (#3971)
-  * Added user language setting (#3875)
-  * LDAP Public SSH Keys synchronization (#1844)
-  * Add topic support (#3711)
-  * Multiple assignees (#3705)
-  * Add protected branch whitelists for merging (#3689)
-  * Global code search support (#3664)
-  * Add label descriptions (#3662)
-  * Add issue search via API (#3612)
-  * Add repository setting to enable/disable health checks (#3607)
-  * Emoji Autocomplete (#3433)
-  * Implements generator cli for secrets (#3531)
-* ENHANCEMENTS
-  * Add more webhooks support and refactor webhook templates directory (#3929)
-  * Add new option to allow only OAuth2/OpenID user registration (#3910)
-  * Add option to use paged LDAP search when synchronizing users (#3895)
-  * Symlink icons (#1416)
-  * Improve release page UI (#3693)
-  * Add admin dashboard option to run health checks (#3606)
-  * Add branch link in branch list (#3576)
-  * Reduce sql query times in retrieveFeeds (#3547)
-  * Option to enable or disable swagger endpoints (#3502)
-  * Add missing licenses (#3497)
-  * Reduce repo indexer disk usage (#3452)
-  * Enable caching on assets and avatars (#3376)
-  * Add repository search ordered by stars/forks. Forks column in admin repo list (#3969)
-  * Add Environment Variables to Docker template (#4012)
-  * LFS: make HTTP auth period configurable (#4035)
-  * Add config path as an optionial flag when changing pass via CLI (#4184)
-  * Refactor User Settings sections (#3900)
-  * Allow square brackets in external issue patterns (#3408)
-  * Add Attachment API (#3478)
-  * Add EnableTimetracking option to app settings (#3719)
-  * Add config option to enable or disable log executed SQL (#3726)
-  * Shows total tracked time in issue and milestone list (#3341)
-* TRANSLATION
-  * Improve English grammar and consistency (#3614)
-* DEPLOYMENT
-  * Allow Gitea to run as different USER in Docker (#3961)
-  * Provide compressed release binaries (#3991)
-  * Sign release binaries (#4188)
-
-## [1.4.3](https://github.com/go-gitea/gitea/releases/tag/v1.4.3) - 2018-06-26
-
-* SECURITY
-  * HTML-escape plain-text READMEs (#4192) (#4214)
-  * Fix open redirect vulnerability on login screen (#4312) (#4312)
-* BUGFIXES
-  * Fix broken monitoring page when running processes are shown (#4203) (#4208)
-  * Fix delete comment bug (#4216) (#4228)
-  * Delete reactions added to issues and comments when deleting repository (#4232) (#4237)
-  * Fix wiki URL encoding bug (#4091) (#4254)
-  * Fix code tab link when viewing tags (#3908) (#4263)
-  * Fix webhook type conflation (#4285) (#4285)
-
-## [1.4.2](https://github.com/go-gitea/gitea/releases/tag/v1.4.2) - 2018-06-04
-
-* BUGFIXES
-  * Adjust z-index for floating labels (#3939) (#3950)
-  * Add missing token validation on application settings page (#3976) #3978
-  * Webhook and hook_task clean up (#4006)
-  * Fix webhook bug of response info is not displayed in UI (#4023)
-  * Fix writer cannot read bare repo guide (#4033) (#4039)
-  * Don't force due date to current time (#3830) (#4057)
-  * Fix wiki redirects (#3919) (#4065)
-  * Fix attachment ENABLED (#4064) (#4066)
-  * Added deletion of an empty line at the end of file (#4054) (#4074)
-  * Use ResolveReference instead of path.Join (#4073)
-  * Fix #4081 Check for leading / in base before removing it (#4083)
-  * Respository's home page not updated after first push (#4075)
-
-## [1.4.1](https://github.com/go-gitea/gitea/releases/tag/v1.4.1) - 2018-05-03
-
-* BREAKING
-  * Add "error" as reserved username (#3882) (#3886)
-* SECURITY
-  * Do not allow inactive users to access repositories using private key (#3887) (#3889)
-  * Fix path cleanup in file editor, when initilizing new repository and LFS oids  (#3871) (#3873)
-  * Remove unnecessary allowed safe HTML (#3778) (#3779)
-  * Correctly check http git access rights for reverse proxy authorized users (#3721) (#3743)
-* BUGFIXES
-  * Fix to use only needed columns from tables to get repository git paths (#3870) (#3883)
-  * Fix GPG expire time display when time is zero (#3584) (#3884)
-  * Fix to update only issue last update time when adding a comment (#3855) (#3860)
-  * Fix repository star count after deleting user (#3781) (#3783)
-  * Use the active branch for the code tab (#3720) (#3776)
-  * Set default branch name on first push (#3715) (#3723)
-  * Show clipboard button if disable HTTP of git protocol (#3773) (#3774)
-
-## [1.4.0](https://github.com/go-gitea/gitea/releases/tag/v1.4.0) - 2018-03-25
-
-* BREAKING
-  * Drop deprecated GOGS\_WORK\_DIR use (#2946)
-  * Fix API status code for hook creation (#2814)
-* SECURITY
-  * Escape branch name in dropdown menu (#3691) (#3692)
-  * Refactor and simplify to correctly validate redirect to URL (#3674) (#3676)
-  * Fix escaping changed title in comments (#3530) (#3534)
-  * Escape search query (#3486) (#3488)
-  * Sanitize logs for mirror sync (#3057)
-* FEATURES
-  * Serve .patch and .diff for pull requests (#3305, #3293)
-  * Add repo-sync-releases admin command (#3254)
-  * Support default private when creating or migrating repository (#3239)
-  * Writable deploy keys (closes #671) (#3225)
-  * Add Pull Request merge options - Ignore white-space for conflict checking, Rebase, Squash merge (#3188)
-  * Added progressbar for issues with checkboxes (#1146). (#3171)
-  * Mention completion for issue editor. (#3136)
-  * Add 'mark all read' option to notifications (#3097)
-  * Git LFS lock api (#2938)
-  * Add reactions to issues/PR and comments (#2856)
-  * Add dingtalk webhook  (#2777)
-  * Responsive view (#2750)
-* BUGFIXES
-  * Fix wiki inter-links with spaces (#3560) (#3632)
-  * Fix query protected branch bug (#3563) (#3571)
-  * Fix remove team member issue (#3566) (#3570)
-  * Fix the protected branch panic issue (#3567) (#3569)
-  * If Mirrors repository no content is fetched, updated time should not be changed (#3551) (#3565)
-  * Bug fix for mirrored repository releases sorted (#3522) (#3555)
-  * Add issue closed time column to fix activity closed issues list (#3537) (#3540)
-  * Update markbates/goth library to support OAuth2 with new dropbox API (#3533) (#3539)
-  * Fixes missing avatars in offline mode (#3471) (#3477)
-  * Fix synchronization bug in repo indexer (#3455) (#3461)
-  * Fix rendering of wiki page list if wiki repo contains other files (#3454) (#3463)
-  * Fix webhook X-GitHub-* headers casing for better compatibility (#3429)
-  * Add content type and doctype to requests made with go-get (#3426, #3423)
-  * Fix SQL type error for webhooks (#3424)
-  * Fix PR merge error (#3421)
-  * Recognize more characters in crossreferenced repo name (#3413)
-  * Fix MSSQL bug on org (#3405)
-  * HTML escape all lines of the search result (#3402)
-  * Change local copy origin url after repository rename (#3399)
-  * Force-push to base repo's ref/pull/#/head (#3393)
-  * Fix bug when a user delete but assigned on issue (#3318)
-  * Use issue number/index instead of id for API URL. Fix #3297 (#3298)
-  * Fix repo-transfer-and-team-repo-count bug (#3241)
-  * Fix always-on SSL Mode checkbox in admin page (#3208)
-  * Fix source download link when no code unit allowed (#3166)
-  * Fix org owner cannot be removed if he is not in owner team (#3164)
-  * Fix run web with -p push failed (#3154)
-  * Fix gpg tmpl (#3153)
-  * Fix SSH auth lfs locks (#3152)
-  * Improvements for supporting UI Location (#3146)
-  * Fix new pull request link (#3133)
-  * Fix missing branch in release bug (#3108)
-  * Allow adding collaborators with (fullname) (#3103)
-  * Fix repo links (#3093)
-  * fix lfs url refs + keep path upper/lowercase in db. (#3092)
-  * Fix redis session failed (#3086)
-  * Fix bugs in issue dashboard stats (#3073)
-  * Fix avatar URLs (#3069)
-  * Fix ref parsing in commit messages (#3067)
-  * Fix issue list branch link broken (#3061)
-  * sendmail: correct option to set envelope-sender (#3044)
-  * Fix missing password length check when change password (#3039)
-  * Fix git lfs path (#3016)
-  * Fix API-Endpoint release (#3005) (#3012)
-  * Set OpenID support on by default when installing new instance (#3010)
-  * Various wiki bug fixes (#2996)
-  * Fix go-get, src and raw urls to new scheme (#2978)
-  * Fix error when add user has full name to team (#2973)
-  * Fix memcache support when value is returned as string always (#2924)
-* ENHANCEMENTS
-  * Use GiteaServer as the user agent for http requests (#3404)
-  * Delete indexer DB entries when (re)creating index (#3385)
-  * Change how merged PR commit info are prepared (#3368)
-  * Asynchronously populate the repo indexer (#3366)
-  * Make the default action for the gitea executable that of running the webserver (#3331)
-  * Templates for extra links in top navbar and repo tool tabs. (#3308)
-  * Fixed asterisk based tasklist items #3295 (#3296)
-  * Add more additional template snippets (#3286)
-  * Open external tracker in blank window, consistently with wiki (#3227)
-  * Fix repo links on user profile (#3197)
-  * Enable emoji for wiki view (#3158)
-  * Small improve on deleting attachements (#3145)
-  * Reduce overhead of upgrades for users with custom stylesheets/JS (#3051)
-  * Default log level to Info without hardcoding it in installer (#3041)
-  * Memory usage improvements (#3013)
-  * Add fingerprint to ssh key endpoints. (#3009)
-  * Improve memory usage when reaching diff limits (#2990)
-  * Expandable commit bodies (#2980)
-  * Update gitgraph.js to fix blurry commit graph on HiDPI screens (#2957)
-  * Fix language names (#2955)
-  * Remove render issue link (#2954)
-  * Page parameter for repo search API (#2915)
-  * Apply LANDING\_PAGE config options for logged in users (#2894)
-  * Enable admin to search by email (#2888)
-  * Hide add key button if SSH is disabled (#2873)
-  * Fix comment API paths (#2813)
-  * Add an option to allow redirect of http port 80 to https. (#1928)
-* MISC
-  * Fix organization profile on mobile devices (#3332)
-  * Fix guide link for webhooks in repository settings (#3291) (#3292)
-  * Enable Libravatar by default in new installations (#3287)
-  * Improve suppressed diff boxes (#3193)
-  * fix button heights on commits page (#3091)
-  * Minor copy changes (#3074)
-  * Sort repos in issues dashboard sidebar (#3072)
-  * Remove box-shadow from UI, fix dashboard issue (#3065)
-  * Adjust branch button size (#3063)
-  * Fix misalignment issue in repo header (#3062)
-  * Delete a user's public key via admin api (closes #3014) (#3059)
-  * Dashboard: Fix line height problem in issue titles (#3054)
-  * Remove duplicate "Max Diff Lines" from config view (#2987)
-  * Drop unmaintained gogs migration script (#2947)
-  * App restarts to quickly if it fails to start. (#2945)
-  * Add owner to delete repo message (#2886)
-
-## [1.3.1](https://github.com/go-gitea/gitea/releases/tag/v1.3.1) - 2017-12-08
-
-* BUGFIXES
-  * Sanitize logs for mirror sync (#3057, #3082) (#3078)
-  * Fix missing branch in release bug (#3108) (#3117)
-  * Fix repo indexer and submodule bug (#3107) (#3110)
-  * Fix legacy URL redirects (#3100) (#3106)
-  * Fix redis session failed (#3086) (#3089)
-  * Fix issue list branch link broken (#3061) (#3070)
-  * Fix missing password length check when change password (#3039) (#3071)
-
-## [1.3.0](https://github.com/go-gitea/gitea/releases/tag/v1.3.0) - 2017-11-29
-
-* BREAKING
-  * Make URL scheme unambiguous (#2408)
-* FEATURES
-  * Add branch overiew page (#2108)
-  * Code/repo search (#2582)
-  * Add Activity page to repository (#2674)
-  * Issue Timetracking (#2211)
-  * Add orgmode document type on file view and readme (#2525)
-  * Add external markup render support (#2570)
-  * Implementation of discord webhook (#2402)
-  * Webhooks for repo creation/deletion (#1663)
-  * Complete push webhooks (#2530)
-  * Add possibility to record branch information in an issue (#780)
-  * Create new branch from branch selection dropdown (#2130)
-  * Implementation of all repositories of a user from user->settings (#1740)
-  * Add LFS object verification step after upload (#2868)
-  * Configurable SSH cipher suite (#913)
-  * Disable custom Git Hooks globally via configuration file (#2450)
-  * Sync releases table with tags on push and for mirrors (#2459)
-* BUGFIXES
-  * Fix label comments for French locale (#3017)
-  * Remove duplicate "Max Diff Lines" from config view (#3001)
-  * Fix over-escaped characters (#2992)
-  * Fix go-get, src and raw urls to new scheme (#2986)
-  * Fix error when add user has full name to team (#2975)
-  * Fix files/commits of merged PRs (#2970)
-  * Update golang x/crypto dependencies - Fix SSH transport fail (#2951)
-  * Fix memcache support when value is returned as string always (#2950)
-  * Fix issue link rendering in commit messages (#2897)
-  * Fix adding a new authentication source after selecting OAuth (#2889)
-  * Fix new branch creation to new url scheme (#2884)
-  * Allow spaces in username for LDAP users (#2880)
-  * Fix LFS not returning correct content length when requesting a range … (#2864)
-  * Fix fork repository cycle to self (#2860)
-  * Fix click create pull request button 404 (#2859)
-  * Fix API raw file content access for default branch (#2849)
-  * Clean repository ROOT directory name with filepath.Clean (#2846)
-  * Fix API raw requests for commits and tags (#2841)
-  * Fix order of comments (#2835)
-  * Issue content should not be updated when closing with comment (#2833)
-  * Fix ordering in app.ini and fix run mode option (#2829)
-  * Fix redirect url of legacy commits route (#2825)
-  * Fix commits page url (#2823)
-  * Fix wrong translations (#2818)
-  * Fix dropdown menu position when explore repos (#2808)
-  * Fix Git LFS object/repo link storage in database and small refactoring (#2803)
-  * Use relative URLs for avatars on the dashboard (#2800)
-  * Add checks for commits with missing author and time (#2771)
-  * Fix emojify image URL (#2769)
-  * Hide unactive on explore users and some refactors (#2741)
-  * Fix IE unsupported javascript construction in branch dropdown (#2736)
-  * Only update mirror last update after successful sync (#2730)
-  * Fix semantic-ui style conflict with v-cloak (#2722)
-  * Fixing wrong translation on sort type oldest/latest (#2720)
-  * Fix PR, milestone and label functionality if issue unit is disabled (#2710)
-  * Fix plain readme didn't render correctly on repo home page (#2705)
-  * Fix organization removal from watch table migration (#2703)
-  * Fix repository search function (#2689)
-  * fix panic on gogs webhook creation (#2675)
-  * Fix orgnization user watch repository (#2670)
-  * GPG key email verification no longer case sensitive (#2661) (#2663)
-  * Fix index column deletion (#2651)
-  * table `pull_request` wasn't updated correctly (#2649)
-  * Fix go get response if only app URL is custom in configuration (#2634)
-  * Fix doubled issue tab introduced in migration v16 (#2611)
-  * Rewrite migrations to not depend on future code changes (#2604)
-  * Fix implementation of repo Home func (#2601)
-  * Fix translation upload to crowdin (#2599)
-  * Reduce usage of allcols on update (#2596)
-  * fix go get subpackage bug (#2584)
-  * Fix broken migration to add can_push field back to table (#2574)
-  * fix readme view bug (#2566)
-  * Fix sending mail with a non-latin display name. #2102 (#2559)
-  * Restricting access to fork functioanlity to users with Code access (#2534)
-  * fix updated update on public key (#2514)
-  * Added bucket name to s3 drone plugin (#2505)
-  * fixes 500 error on dashboard when using MSSQL (#2504)
-  * fix wrong rendering of commit detail page (#2503)
-  * Hotfix: Add time manually adds time in nanoseconds (#2499)
-  * Remove repository mirrors from "collaborative" list (#2497)
-  * fix release failed since the wrong token name (#2496)
-  * Fix slice out of bounds error in mailer (#2479)
-  * Fix #2470 (#2477)
-  * fix orgnization webhooks (#2422)
-  * fix webhook test (#2415)
-  * fix missing orgnization discord webhook (#2414)
-  * Fix route handler order (#2409)
-  * Prevent sending emails and notifications to inactive users (#2384)
-  * Move themes to plugin directory. Fixes #2372 (#2375)
-  * fix duplicated feed (#2370)
-  * Fix missing collabrative repos (#2367)
-  * Only check at least one email gpg key (#2266)
-  * don't check minimum key size when disabled (#1754)
-  * Fix run command race (#1470)
-  * fix .netrc authentication (#2700)
-  * Fix so that user can still fork his own repository to his organizations (#2699)
-  * Fix can_push value to false in protected_branch (#2560)
-  * Fix copy in email templates (#2801)
-  * Fix inconsistencies in user settings UI (#2901)
-  * Fix attachments icon size on zoom in/out (#2853)
-  * Fix ignored errors in API route (#2850)
-  * Fix activity css conflit with semantic ui (#2758)
-  * Fix notifications tabs according to semantic-ui docs (#2733)
-  * Fix typos in app.ini (#2732)
-  * Fix duplicated rel attribute (#2549)
-  * Fix tests code to prevent some runtime errors (#2381)
-* ENHANCEMENTS
-  * Memory usage improvements and lower minimal git requirement to 1.7.2 (#3013) (#3028)
-  * Set OpenID support on by default when installing new instance (#3010) (#3027)
-  * Use api.TrackedTime in API (#2807)
-  * Configurable SSH key exchange algorithm and MAC suite (#2806)
-  * Add Safari pinned tab icon (#2799)
-  * Improve force push detect when push (#2798)
-  * Add wrapping to long diff lines (#2789)
-  * Link members and repositories count to each page on org home. (#2787)
-  * Show Sendmail settings on admin config page (#2782)
-  * Add commit count caching (#2774)
-  * Use identicon image for default gravatar. (#2767)
-  * Add default ssh ciphers (#2761)
-  * Remove manual of unsupported option (#2757)
-  * Add search mode option to /api/repo/search (#2756)
-  * Move swagger-ui under /api/v1 (#2746)
-  * Add support for extra sendmail arguments (#2731)
-  * Use buffersize to reduce database connection when iterate (#2724)
-  * Render plain text README.txt monospaced (#2721)
-  * Integration test for activity page (#2704)
-  * Merge password and 2fa page on user settings (#2695)
-  * Allow custom SSH user in UI for built-in SSH server (#2617) (#2678)
-  * Refactor duplicated code in repo handlers (#2657)
-  * Replace deprecated Id method with ID (#2655)
-  * Remove redudant functions and code (#2652)
-  * hide navbar when only 1 sign-in method is available (#2444) (#2648)
-  * Change default sort order (#2647)
-  * Change pull description text (#2075) (#2646)
-  * Remove direct user adding to organization members (#2641)
-  * Use session when creating user (#2638)
-  * Use Semantic UI's Search component for user and repo search (#2636)
-  * Use AfterLoad instead of AfterSet on Structs (#2628)
-  * Remove redudant CheckUnit calls in router (#2627)
-  * Remove repo unit index (#2621)
-  * Remove redudant issue LoadAttributes() calls (#2614)
-  * Make indexer code more reusable (#2590)
-  * Use custom type and constants to hold available order by options (#2572)
-  * Use named ActionType constants in template helper (#2545)
-  * Make basic functionality work without JavaScript (#2541)
-  * Ctrl + Enter to submit forms (#2540)
-  * Automatically regenerate indexer for incompatible versions (#2524)
-  * Set default lfs content path to data/lfs (#2521)
-  * Convert spaces to tabs in footer.tmpl (#2520)
-  * Sort repository tree entries in natural way (#2506)
-  * Open external wiki in new window (#2489)
-  * Use created & updated instead BeforeInsert & BeforeUpdate (#2482)
-  * Hide branch on pull request view or create UI (#2454)
-  * improve protected branch to add whitelist support (#2451)
-  * some refactors for issue and comments (#2419)
-  * Restructure markup & markdown to prepare for multiple markup language… (#2411)
-  * Improve issue search (#2387)
-  * Add UseCompatSSHURI setting (#2356)
-  * Use custom search for each filter type in dashboard (#2343)
-  * Failed authentication are now properly logged (#2334)
-  * Add environment variable support for Docker image (#2201)
-  * Set session and indexers' data files rel to AppDataPath (#2192)
-  * Display commit status on landing page of repo (#1784)
-* TESTING
-  * Add integration test for logging out (#2892)
-  * Integration test for user deleting account (#2891)
-  * Use different directories for session files in integration tests (#2834)
-  * Add deleted_branch table fixture (#2832)
-  * Include HTTP method in test error message (#2815)
-  * Add repository search unit and integration tests (#2575)
-  * Expand fixtures (#2571)
-  * Fix /api/repo/search integration tests (#2550)
-  * Make integration tests more user-friendly (#2536)
-  * Fix unit test race condition (#2516)
-  * Add missing fixture to clean gpg_key table (#2494)
-  * Hotfix for integration testing (#2473)
-  * Make repo private to not interfere with other tests (#2467)
-  * Error message for integration test (#2410)
-  * Fix "index out of range" runtime error in repo_list tests (#2376)
-  * Add git clone test on integration test (#1682)
-* TRANSLATION
-  * Fix localization texts that contain semicolon (#2900)
-  * Fix activity locale (#2709)
-  * Update translation from crowdin (#2368)
-* BUILD
-  * change the email and name to GitBot account. (#2848)
-  * Fix removing backslash before quotes in translations (#2831)
-  * add gitea remote in drone. (#2817)
-  * add remote name for git push. (#2816)
-  * Launch Gitea with custom UID/GID for 'git' user (fixes #2286) (#2791)
-  * Download and pushing translations (#2727)
-  * Automatic update of translations (#2585)
-  * Add pre-build step for nodejs stuff (#2581)
-  * Compress css with nodejs (#2580)
-  * Remove go version check for make fmt (#2558)
-  * Fix lint errors (#2547)
-  * Always run fmt check in CI (#2546)
-  * Fix fmt errors (#2544)
-  * add codecov.io service. (#2493)
-  * Fix some tests : make coverage -> test (#2492)
-  * Fix fmt error in mailer (#2490)
-  * Allow changing integration test database connection using env variables (#2484)
-  * Add changelog config file for generate changelog (#2461)
-  * Changes for latest DroneCI (#2362)
-  * Use standard lessc and minify CSS using Node.js (#2337)
-* DOCS
-  * Update screenshots on README (#2910)
-  * Gogs -> Gitea (#2909)
-  * Update swagger documentation (#2899)
-  * Fix typo (#2810)
-  * Fix Polish language name spelling (#2766)
-  * Fix Various Grammar Issues and Adjust Unnatural Wording (#2737)
-  * Add maintainer label for docker file (#2658)
-  * Link to gitea-specific Vagrant example (#2624)
-  * add release notes of v1.1.4 (#2463)
-  * Wrap most paragraphs to 80 columns (#2396)
-  * Update CONTRIBUTING following #2329  discussion (#2394)
-  * Update hard-coded version to 1.3.0+dev (#2390)
-  * Clarify Translation Process. Also fix branch names (#2378)
-  * Admin grammar fixes and improvements (#2056)
-* MISC
-  * Sync MaxGitDiffLineCharacters with conf/app.ini (#2779)
-  * Dockerfile: Updated alpine image to 3.6. (#2486)
-  * Basic VSCode configuration for building and debugging (#2483)
-  * Added vendor dir for js/css libs; Documented sources (#1484) (#2241)
-
-## [1.2.3](https://github.com/go-gitea/gitea/releases/tag/v1.2.3) - 2017-11-03
-
-* BUGFIXES
-  * Only require one email when validating GPG key (#2266, #2467, #2663) (#2788)
-  * Fix order of comments (#2835) (#2839)
-
-## [1.2.2](https://github.com/go-gitea/gitea/releases/tag/v1.2.2) - 2017-10-26
-
-* BUGFIXES
-  * Add checks for commits with missing author and time (#2771) (#2785)
-  * Fix sending mail with a non-latin display name (#2559) (#2783)
-  * Sync MaxGitDiffLineCharacters with conf/app.ini (#2779) (#2780)
-  * Update vendor git (#2765) (#2772)
-  * Fix emojify image URL (#2769) (#2773)
-
-## [1.2.1](https://github.com/go-gitea/gitea/releases/tag/v1.2.1) - 2017-10-16
-
-* BUGFIXES
-  * Fix PR, milestone and label functionality if issue unit is disabled (#2710) (#2714)
-  * Fix plain readme didn't render correctly on repo home page (#2705) (#2712)
-  * Fix so that user can still fork his own repository to his organizations (#2699) (#2707)
-  * Fix .netrc authentication (#2700) (#2708)
-  * Fix slice out of bounds error in mailer (#2479) (#2696)
-
-## [1.2.0](https://github.com/go-gitea/gitea/releases/tag/v1.2.0) - 2017-10-10
-
-* SECURITY
-  * Sanitation fix from Gogs (#1461)
-* BREAKING
-  * Rename /forget_password url to /forgot_password (#1219)
-* FEATURES
-  * Logo: Add task to generate images from SVG and change to new logo (#2194)
-  * Status-API (#1332)
-  * Show commit status icon in commits table (#1688)
-  * Additional OAuth2 providers (#1010)
-  * GPG commit validation (#1150)
-  * Rework SSH key management UI to add GPG (#1293)
-  * Implement GPG api (#710)
-  * Login via OpenID-2.0 (#618)
-  * Add units to team (#947)
-  * Batch updates for issues (#926)
-  * Add Gitea Webhook (#1755)
-  * API: support '/orgs/:org/repos' (#2047)
-  * Display all organization from user settings (#1739)
-  * LDAP user synchronization (#1478)
-  * Adding #issuecomment to the URL in E-Mail notifications (#1674)
-  * Add download count field and unit testing for attachment. (#1512)
-  * Add repo mirror sync API endpoint (#1508)
-  * Add markup package to prepare for org markup format (#1493)
-  * Support for custom html meta  (#1423)
-  * Per issue/PR watch/unwatch (#1410)
-  * Allow ENABLE_OPENID_SIGNUP to depend on DISABLE_REGISTRATION (#1369)
-  * Repo size in admin panel (#1482)
-  * Show user OpenID URIs in their profile (#1314)
-  * Add change-password admin command (#1304)
-  * Only use issue and wiki on repo. (#1297)
-  * Allow push to init a wiki repo (#1279)
-* ENHANCEMENTS
-  * Make time diff translatable (#2057)
-  * Smaller watch, star, and fork buttons (#2052)
-  * Display config file path on admin panel (#2030)
-  * Only show SSH clone URL if signed in (#2169) (#2170)
-  * Only show "No Description" to repo admins (#2167)
-  * Always return valid go-get meta, even if unauthorized (#2010)
-  * Enable assignee e-mail notification (#2003)
-  * Let not-logged-in users view releases (#1999)
-  * No highlighting for .txt files (#1922)
-  * Make side nav on dashboard stackable (#1778)
-  * Setting to disable authorized_keys backup (#1856)
-  * Hide the create organization button (in dashboard/organization section) (#1705)
-  * LFS: Return 404 for unimplemented endpoints (#1330)
-  * Show a link to password reset from user settings requiring a password (#862)
-  * Reserve the "explore" user/org name (#1222)
-  * Send notifications to partecipants in issue comments (#1217)
-  * Improve style of user OpenID setting page (#1324)
-  * Use font-awesome OpenID icon more (#1320)
-  * Use readonly input form to show the validated OpenID URI (#1308)
-  * Add captcha support to OpenID based signup (#1307)
-  * Minor improvements on commit graph UI (#1380)
-  * Mirror sync interval specified as duration string (#1407)
-  * Make issue in commit graph "clickable" (#1392)
-  * Use whole button (commit graph) as link (#1390)
-  * Autofocus on 2fa passcode fields (#1460)
-  * Sort on repo size in admin panel (#1654)
-  * Improve dashboard repo search (#1652)
-  * Use a better default MAX_GIT_DIFF_LINE_CHARACTERS (#1845)
-  * Adds Parent property to the repo API (#1687)
-  * Add configuration option for default permission to create Organizations (#1686)
-  * Remove sha1 hash display in repository table (#1678)
-  * Download files to their original filename (#1676)
-  * Exposes in API the Repo entity's Size and IsBare property (#1668)
-  * Change two factor code entry box from text to number (#1733)
-  * Directly show error if user hit repository limit  (#1767)
-  * Generate small and large logos at 4x resolution (#2233)
-  * Tags listed in releases tab (#2389) (#2424)
-* BUGFIXES
-  * Fix adding branch as protected to not allow pushing to it (#2556)
-  * Orgs: fix org page title when full name is not defined (#1495)
-  * Fix double borders on edit page (#1152) (#1153)
-  * Search bar fixes for #1187 and #1205 (#1207)
-  * Fix upgrade failed after ever rollback (#1194)
-  * Fix FCGI (over TCP) support (#1368)
-  * Backport of migration fixes (#2604) (#2677)
-  * fix panic on gogs webhook creation (#2675) (#2676)
-  * Backport: Fixes 500 error on dashboard when using MSSQL (#2504) (#2662)
-  * Fix go get response if only app URL is custom in configuration (#2634) (#2640)
-  * Fix deletion of unprotected branches (#2630)
-  * Backport of 2611 / Fix doubled issue tab introduced in migration v16 (#2622)
-  * v38 migration used an outdated version of RepoUnit model (#2602)
-  * fix go get subpackage bug (#2584) (#2589)
-  * Backport: Sync releases table with tags on push and for mirrors (#2459) (#2554)
-  * Backport: Restricting access to fork functioanlity to users with Code access (#2542)
-  * Fix migration from pre-v15 to 1.2.0 (#2460) (#2465)
-  * Fix migration from pre-v15 to 1.2.0 (#2460)
-  * fix duplicated feed (#2370) (#2413)
-  * Fix releases to be counted from database not tags (#2389)
-  * Fix missing collabrative repos (#2367) (#2382)
-  * Add more test for login links and fix a bug on action retrieve (#2361)
-  * Fix SQL condition bug in GetFeeds(..) (#2360)
-  * fix bug on create repo link on dashboard (#2359)
-  * Fix order of elements in dashboard html (#2344)
-  * Fix repo-search template errors for go1.7 (#2336)
-  * Add missing forks key for dashboard repository component (#2325)
-  * fix template error on explore repos (#2319)
-  * Trigger sync webhooks on UI commit (#2302)
-  * fix 500 error when view an issue which's milestone deleted (#2297)
-  * Only update needed columns when update user (#2296)
-  * Fix rendering of external links (#2292)
-  * Fix and improve dashboard repo UI (#2285)
-  * Make short link pattern greedy (#2259)
-  * Temporarily patch go-ini/ini with fork (#2255)
-  * Convert xorm literal queries to method calls (#2253)
-  * update code.gitea.io/git in vendor to fix delete branch fails (#2250)
-  * Replace calls to xorm UseBool with Where (#2237)
-  * rhel7 has a git version with four digits (1.8.3.1) (#2236)
-  * Fix internal requests when gitea listens to unix socket or only external IP (#2234)
-  * Check for access in /repositories/:id (#2227)
-  * Fixed robots.txt 404 error (#2226)
-  * Fix counts on issues dashboard (#2215)
-  * Fix unclosed session bug (#2214)
-  * Add collaborative repositories to the dashboard (#2205)
-  * Fix issue updated_unix bug (#2204)
-  * Fix Commits nil pointer dereference (#2203)
-  * Fix bare-repo bugs (#2199)
-  * Fix PR nil-dereference bug (#2195)
-  * Allow only single fork per user/organization (#2193)
-  * Fix key usage time update if the key is used in parallel for multiple operations (#2185)
-  * Only allow token authentication with 2FA enabled (#2184)
-  * Fix profile update for non-local users (#2178)
-  * Fix compiling without sqlite and gcc (#2177)
-  * Make compare button URL aware if current repo is a fork (#2162) (#2163)
-  * Remove unit types commits and settings (#2161)
-  * Fix OpenID registration route (#2160)
-  * Fix repository settings collobration list display (#2151)
-  * Ignore invalid issue numbers in commit messages. Fixes  #2022 (#2150)
-  * Fix SHA1 hash linking (#2143)
-  * Fix repo API bug (#2133)
-  * Use POSIX complaint ! operator in find (#2132)
-  * Fix GET /users/:username/repos endpoint (#2125)
-  * Fix username rendering bug (#2122)
-  * Fix wiki preview links (#2119)
-  * vendor: update sqlite to fix "database is locked" errors (#2116)
-  * Fix unchecked error bug (#2110)
-  * Fix missing-return bug (#2109)
-  * Fix API for branches with slashes (#2096)
-  * Fix git hooks update to receive required arguments (#2095)
-  * upgrade git source code. (#2094)
-  * Fix SQL bug in models.PullRequests (#2092)
-  * Don't ignore gravatar error (#2083)
-  * Fix release display and correct paging (#2080)
-  * remove unnecessary blank lines and wrong error log (#2079)
-  * Check for valid renamed usernames (#2077)
-  * Update git module (#2074)
-  * Fix org hooks UI (#2072)
-  * Fix #1271: Call location.reload after XHR finishes (#2071)
-  * Fix default ghost assignee bug (#2069)
-  * Fix bug in issue labels API (#2048)
-  * Load label ID in NewLabels (#2045)
-  * Fix: `http: multiple response.WriteHeader calls` (#2038)
-  * Pagination on releases page (#2035)
-  * repo/editor: fix breadcrumb path cuts parent dirs (#3859) (#2032)
-  * Fix displaying commits and files of PR created from now deleted fork (#2023)
-  * Fix #2001 and fix issue comments hidden (#2016)
-  * Update code.gitea.io/git (#2014)
-  * Keep sort when switching page (#2013)
-  * Important: wrong PR merge commit ID saved (#2007)
-  * Don't show non-comments in comments API (#2001)
-  * Fix "Dashboard shows deleted comments" (#1995)
-  * Make branch deletion URL more like GitHub's, fixes #1397 (#1994)
-  * Fix fast-forward PR bug (#1989)
-  * Fix GPG email checking to be case insensitive (#1988)
-  * fix bug for normal user visit public repo (#1984)
-  * fix collborators lack of units on orgnization repositories (#1968)
-  * Fix diff of renamed and modified file (#1967)
-  * Fix uppercase default branch bug (#1965)
-  * Fix bug in Action.loadRepo() (#1959)
-  * Fix deleted milestone bug (#1942)
-  * Fix engine bug in getIssueByID (#1934)
-  * Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
-  * Fix setting.AppPath for integration tests (#1923)
-  * Fix search by issue type (#1914)
-  * Fix ghost user bug (#1913)
-  * Require token before checking membership/ownership (#1905)
-  * Bug fixes for org member API (#1904)
-  * A missing / to provide a correct endpoint (#1903)
-  * Fix 500 in public activity page (#1901)
-  * Center-aligned login topbar (#1880)
-  * Migration to fix existing owner team units (#1873)
-  * Fix paginater length (#1866)
-  * Fix bug in removeOrgRepo (#1858)
-  * Display draft releases (#1854)
-  * Fix 404 for external tracking issues (#1852)
-  * Update code.gitea.io/git (#1849)
-  * Fix user profile activity feed (#1848)
-  * Don't ignore error in getMergeCommit (#1843)
-  * Fix locking bug in removeOrgRepo (#1842)
-  * Fix status table race condition (#1835)
-  * Fix PR template error (#1834)
-  * Fix pull request compare link (#1832)
-  * Use ghost users in issues/PRs (#1831)
-  * Commitless repos should be bare (#1829)
-  * Update code.gitea.io/git (#1824)
-  * Fix invalid reference in feeds template (#1820)
-  * fix bug to deny to add orgnization as a member of an orgnization or team (#1815)
-  * xxx_active_code_live setting in printed in hours and minutes instead … (#1814)
-  * Fix deadlock in updateRepository (#1813)
-  * Give all units to owner team (#1812)
-  * Fix 500 for GET /teams/:id endpoints (#1811)
-  * fix bug not to trim space of login username (#1796)
-  * Fix renaming bug (#1786)
-  * Fix activity feed (#1779)
-  * Make navbar scroll on overflow (#1777)
-  * Delete repo redirects on repo deletion (#1776)
-  * Fix unloaded owner bug (#1770)
-  * Admin should always be allowed to create repositories even if hit limit (#1765)
-  * Update HighlightJS and fix YAML files highlighting (#1764)
-  * fix: #1757 fix set MAX_CREATION_LIMIT as zero. (#1762)
-  * fix admin lost permission caused by #947 (#1753)
-  * More fixes for dashboard search (#1750)
-  * fixes wrong after field in webhook payload (#1746)
-  * fix avatar update bug (#1729)
-  * Fix FOUC on Firefox (#1728)
-  * Fix changes introduce by update of go-swagger. (#1727)
-  * Fix #1719 (#1722)
-  * Correct flash after sending password reset email (#1718)
-  * Fix and test for delete user (#1713)
-  * Fix rendering of issue checkboxes (#1709)
-  * Enforce netgo build tag while cross-compilation (#1690)
-  * fix bug when push a branch name with / & fix an integration test bug (#1689)
-  * fix potential sqlite lock (#1680)
-  * Fix commit sha1 URL rendering in markdown (#1677)
-  * Fix static files permission under public/ (#1675)
-  * fix: tag contain character ) will http 500 on release page (#1670)
-  * Fix CSS for code in wiki markdown (#1660)
-  * fix multiple readme file rendering and fix #1657 (#1658)
-  * Add primary key and index to external login user table (#1656)
-  * fix #1643 and improve integration test (#1645)
-  * Fix version in Makefile (#1636)
-  * Handle display of GPG key without end date (#1628)
-  * fix bug on issue view when not login (#1624)
-  * bug fixed for API to get user's repos (#1622)
-  * fix lost text color on button on set as primary email (#1621)
-  * Add create_at and updated_at in PR json (#1616)
-  * update git and fix #1133 (#1614)
-  * fix bug on status API (#1533)
-  * Do not show empty collaborators segment (#1531)
-  * Fix markdown rendering (#1530)
-  * fix go get sub package and add domain on installation to let go get work defaultly (#1518)
-  * fix #1501 ssh hangs caused by #1461 (#1513)
-  * Fix empty file download (#1506)
-  * Fix broken v27 migration - change mirror interval from int to bigint (#1504)
-  * Do not allow commiting to protected branch from online editor (#1502)
-  * Add internal routes for ssh hook comands (#1471)
-  * Fix races within code.gitea.io/git.(*Command).RunInDirTimeoutPipeline (#1465)
-  * Simple quick fix for #1418 (#1456)
-  * fix gpg API panic when no verification (#1451)
-  * fix migrate failed and org dashboard failed on MSSQL database (#1448)
-  * Optimize and fix autolink function (#1442) (#1444)
-  * Fix and simplify repo branches (settings) UI (#1435)
-  * Fix disabled fields in repo settings UI (#1431)
-  * fixes pull request hanging when it contains normal and LFS files (#1425)
-  * Fix races in the log module by using syncmap (#1421)
-  * Add length check for the return string (#1420)
-  * Fix "Error: No issue number specified"  when pushing (#1393)
-  * Corrected Mirror.NextUpdate not set (#1388)
-  * fix: remove `str2html` from org full name (#1360)
-  * Correct broken unaligned load/store in armv5 (#1355)
-  * Remove href on first/last link when on first/last page (#1345)
-  * Fix broken table layout (#1344)
-  * LFS: Fix SSH authentication for trailing arguments (#1328)
-  * Remove empty file (#1326)
-  * Fix delete user failed on sqlite (#1321)
-  * Fix inconsistency in layout (#1316)
-  * Fix gpg wrong column types (#1303)
-  * Fix wiki bugs (#1294)
-  * Fix missing less sources for oauth (#1288)
-  * Make sure both scripts/ can live side by side (#1264)
-  * Fix nil-dereference bug (#1258)
-  * rewrite pre-commit, post-commit and options hooks (fixes #1250) (#1257)
-  * Commit search appearence fixes (#1254)
-  * Fix forget migration for wiki hooks (#1227)
-  * Fix repo settings external tracker failed and check external urls (#1215)
-  * Fix 500 caused by branches settings introduced by #1198 (#1214)
-  * fix #1189, commit messages containing a pipe (#1203)
-  * Bug fixed for delete repo failed (#1193)
-  * Fix migration failed when authorized_keys is not exist (#1180)
-  * Fix ini format incomiptable with crowdin (#1177)
-* TESTING
-  * Integration tests for issues API (#2059)
-  * Add integration tests for signin (#2363)
-  * Add INTERNAL_TOKEN to integration .ini file (#2346)
-  * Add public links check (#2323)
-  * Fix hooks for integration repo (#2216)
-  * More integration tests for comment API (#2156)
-  * Cache session cookies in tests (#2128)
-  * Less verbose integration tests (#2123)
-  * Fix improper setup for integration tests (#2050)
-  * Improve integration test helper functions (#2049)
-  * Add integration test for issue creating (#2002)
-  * Use testing/benchmark interface (#1993)
-  * Add integration test for repository migration (#1983)
-  * Consolidate boilerplate in integration tests (#1979)
-  * Set console to debug for integration tests (#1976)
-  * Add pull-create integration test (#1972)
-  * Coverage reports for integration tests (#1960)
-  * Add integration test for pull-request merge (#1912)
-  * Add integration test for file editing (#1907)
-  * Add integration test for repository forking (#1896)
-  * Run unused test (#1875)
-  * Don't recreate database in integration tests (#1697)
-  * remove sqlite tag when integration test with mysql/postgres and recreate database when init integration test (#1693)
-  * MySQL, Postgres integration tests in drone (#1638)
-  * improve integration test to resue models/fixtures and store git repos with tests (#1627)
-  * Improve govendor testing (#1623)
-  * Integration test framework (#1290)
-  * Unit tests for issue_list (#1209)
-  * Add integration test for signup (#1135)
-* TRANSLATION
-  * update translation from crowdin (#2368) (#2380)
-  * Small fixes (#2144)
-  * Missing signed commit display translations (#2134)
-  * Sync latest translations from crowdin (#2104)
-  * Add make command update-translations for update translations from crodwin (#2097)
-  * Fix some mistakes (#1833)
-  * Improve clarity between is_activated and prohibit_login (#1788)
-  * Improve grammar (#1775)
-  * Fix bad grammar and wordiness (#1741)
-  * Make strings translatable (#1188) (#1198)
-* BUILD
-  * Dockerfile for aarch64 (#1128) (#1130)
-  * backport from v1.2 branch: add secrets for github release (#2588) (#2598)
-  * Add secrets for github release to fix drone failed (#2588)
-  * Backport changes for latest drone (#2586)
-  * Removing .drone.yml.sig (#2579)
-  * Fix drone for tags (#2573) (#2576)
-  * Backport: Remove go version check for make fmt (#2558) (#2561)
-  * Backport: Fix lint, fmt and integration testing errors (#2553)
-  * update latest xorm version to vendor (#2353)
-  * Remove integration test executables on `make clean` (#2340)
-  * refactor(Makefile): allow overriding default go program (#2310)
-  * Revert to upstream ini dependency (#2304)
-  * Use /dev/urandom to create random password (#2298)
-  * update drone sig file. (#2262)
-  * go get github.com/wadey/gocovmerge when needed (#2235)
-  * fix typo (#2145)
-  * Revert "Reduce number of layer" (#2086)
-  * Reduce number of layer (#2078)
-  * Skip sqlite integration in CI (#2058)
-  * fix golint error and rename func for suggestion. (#1997)
-  * fix misspell (#1996)
-  * update drone sig file (#1981)
-  * send notification if status changed (#1973)
-  * switch gitter to discord for drone. (#1971)
-  * Fix missing backslash in Dockerfile.rpi (#1952)
-  * Don't run 'make release' on PRs (#1908)
-  * Update code.gitea.io/git (#1892)
-  * Use production version of vuejs (#1869)
-  * Add a variable for docker tag (#1825)
-  * resign drone and fix #1816 (#1819)
-  * Separate generate swagger + fix sed os specific (#1791)
-  * Only run coverage on merges/pushes to master (#1783)
-  * Remove stale rule from Makefile (#1782)
-  * feat: upgrade drone docker image to support multi-stage build. (#1732)
-  * Realy don't cache apk index (#1694)
-  * Limit clone depth when drone-building (#1644)
-  * Refactor Dockerfile (#1632)
-  * Check if missing/modified/unused deps in vendor and fix errors (#1468)
-  * Add GOFLAGS and EXTRA_GOFLAGS (#1438)
-  * Include formatting check to the `make test` (and thus also `check`) rule (#1366)
-* DOCS
-  * fix wrong changelog title (#2395)
-  * fix webhook link (#2289)
-  * Improve swagger doc (#2274)
-  * Add link to forum in issue template (#2070)
-  * add missing lfs config on example file (#2039)
-  * Add discourse link (#2027)
-  * Fix wording (#2024)
-  * Fix typo (#1974)
-  * Swagger docs for list/create forks (#1941)
-  * Update links to Discord server (#1940)
-  * [ci skip] update discord badge. (#1930)
-  * Change join chat from gitter to discord (#1929)
-  * Update changelog with v1.1.1 (#1926)
-  * Correct grammar in APIEmpty documentation (#1748)
-  * Add swagger comment for MirrorSync (#1747)
-  * Add "Table of Contents" in CONTRIBUTING.md (#1634)
-  * Fix service description in Debian init file (#1538)
-  * Use MAINTAINERS file in repository in CONTRIBUTING (#1489)
-  * Generate swagger json (#1402)
-  * Changed text when password reset disabled. (#1364)
-  * Removed email copyright year (#1348)
-  * Specify that time interval units are seconds (#1311)
-  * Gitea OpenID-2.0 login has been tested with livejournal.com too (#1306)
-  * Make wording of commit search more clear (#1291)
-  * Add notice that LFS mirroring is not supported (#1251)
-  * Fix typos in models/ and modules/ (#1248)
-  * Refactor and fix incorrect comment (#1247)
-  * Fix migration comment (#1241)
-  * Update locale_en-US.ini (#1235)
-  * Add LibreJS support (#1201)
-  * rename OSX to macOS (#1176)
-  * add mssql to app.ini db config comment (#1172)
-  * Add MSSQL to issues template (#1171)
-* MISC
-  * Add badge and link to the Matrix room (#2348)
-  * ignore coverage steps. (#2257)
-  * Use sqlite3 database as default for Docker image (#2182)
-  * update drone discord plugin to 0.0.4 version (#1992)
-  * fix typo (#1990)
-  * Move 3rd party js/css into `public/vendor` and document sources (#2383)
-  * Prevent conflicting TOTP accounts by adding AppURL to issuer parameter (#2335)
-  * Fix variable name typo (#2327)
-  * Make use of Vue more universal (#2318)
-  * Remove (almost) server side data rendering from repo-search component (#2317)
-  * Add OpenID configuration in install page (#2276)
-  * More tweaks to repo top panel (#2267)
-  * File path tweaks in UI (#2264)
-  * Make SHOW_USER_EMAIL also apply to profiles (#2258)
-  * EnableUnit() -> UnitEnabled() (#2242)
-  * Prevent selection of diff line numbers (#2240)
-  * Remove unused variable on makefile (#2225)
-  * No error log entries for repo 404 (#2200)
-  * Refactor vue delimeters to use es6 template delimeters (#2171)
-  * Replace tmp with TMPDIR. (#2152)
-  * Remove unused files (#2124)
-  * Improve org error handling (#2117)
-  * Absolute path for setting.CustomConf (#2085)
-  * remove deprecated code for Gogs compitable (#2041)
-  * Refactor session close as xorm already does everything needed internally  (#2020)
-  * SQLite has a query timeout. Hopefully fixes most 'database locked' errors (#1961)
-  * Use monospace font in githook editor (#1958)
-  * Fix import order (#1951)
-  * Gracefully handle bare repositories on API operations. (#1932)
-  * Fix errors caused by force push (#1927)
-  * Display URLs in integration test logs (#1924)
-  * Set TMPDIR enviroment variable for dump command (#1915)
-  * Cache ctx.User in retrieveFeeds (#1902)
-  * Make `LocalCopyPath` a setting instead of a hard-coded path (#1881)
-  * Add check misspelling (#1877)
-  * Fix misspelled variables (#1874)
-  * Gofmt (#1868, #1710, #1662)
-  * Rename misnamed migration (#1867)
-  * Support CRLF when splitting code lines for display (#1862)
-  * Add convert less css file step. (#1861)
-  * Prevent accidential selection of line numbers in code view (#1860)
-  * Delete Public SSH Key tmp file after calculating fingerprint (#1855)
-  * Remove annoying difference in button heights. (#1853)
-  * Only run test coverage on master branch. (#1838)
-  * Error from mktemp command in MacOS. (#1837)
-  * Use writeTmpKeyFile in calcFingerprint (#1828)
-  * ROOT_URL setting use the default as shown in conf/app.ini (#1823)
-  * Rename RepoCreationNum -> MaxCreationLimit (#1766)
-  * Add button to admin ui (#1738)
-  * Correct spelling mistakes (#1703)
-  * Make openid support default false for compitable with v1.1 (#1650)
-  * Send mails as HTML as default. Setting for send as plain text. (#1648)
-  * fix potential lock when sqlite (#1647)
-  * Optimize png images via Google zopflipng [ci skip] (#1639)
-  * Upgrade alpine to v3.5 in Dockerfile (#1633)
-  * remove unused vendor packages (#1620)
-  * markup: microoptimise for many short filenames in directory (#1534)
-  * support health check via / and fix #969 (#1520)
-  * Remove env user salt since no need to use (#1515)
-  * Drop db operations from hook commands (#1514)
-  * Better URL validation (#1507)
-  * Migrate WatchInfo struct to api (#1492)
-  * refactor: show command help message. (#1486)
-  * refactor update ssh key use time (#1466)
-  * Set VERSION from git once, in a variable (#1447)
-  * Remove unused mutex field (#1440)
-  * Simplify settings pages with item list (#1389)
-  * Clean-up PostgreSQL Tests (#1361)
-  * refactor: remove workaround after the golang 1.7 release. (#1349)
-  * Delete the useless code (#1335)
-  * Run "make fmt" with go-1.6 (#1333)
-  * Refactor admin/auth/new.tmpl (#1277)
-  * Refactor repo/issue/view_content.tmpl (#1276)
-  * Cleaner ui for admin, repo settings, and user settings page (#1269) (#1270)
-  * Cleaner UI for explore page (#1253) (#1255)
-  * Synced licenses with github repo (#1246)
-  * Synced gitignores with github repo (#1245)
-  * Simplify RepositoryList.loadAttributes() (#1211)
-  * Move user_follow to separate file (#1210)
-  * Reduce conditionals in signin/signup inner forms (#1138)
-
-## [1.1.4](https://github.com/go-gitea/gitea/releases/tag/v1.1.4) - 2017-09-04
-
-* BUGFIXES
-  * Fix rendering of external links (#2292) (#2315)
-  * Fix deleted milestone bug (#1942) (#2300)
-  * fix 500 error when view an issue which's milestone deleted (#2297) (#2299)
-  * Fix SHA1 hash linking (#2143) (#2293)
-  * back port from #1709 (#2291)
-
-## [1.1.3](https://github.com/go-gitea/gitea/releases/tag/v1.1.3) - 2017-08-03
-
-* BUGFIXES
-  * Fix PR template error (#2008)
-  * Fix markdown rendering (fix #1530) (#2043)
-  * Fix missing less sources for oauth (backport #1288) (#2135)
-  * Don't ignore gravatar error (#2138)
-  * Fix diff of renamed and modified file (#2136)
-  * Fix fast-forward PR bug (#2137)
-  * Fix some security bugs
-
-## [1.1.2](https://github.com/go-gitea/gitea/releases/tag/v1.1.2) - 2017-06-13
-
-* BUGFIXES
-  * Enforce netgo build tag while cross-compilation (Backport of #1690) (#1731)
-  * fix update avatar
-  * fix delete user failed on sqlite (#1321)
-  * fix bug not to trim space of login username (#1806)
-  * Backport bugfixes #1220 and #1393 to v1.1 (#1758)
-
-## [1.1.1](https://github.com/go-gitea/gitea/releases/tag/v1.1.1) - 2017-05-04
-
-* BUGFIXES
-  * Markdown Sanitation Fix [#1646](https://github.com/go-gitea/gitea/pull/1646)
-  * Fix broken hooks [#1376](https://github.com/go-gitea/gitea/pull/1376)
-  * Fix migration issue [#1375](https://github.com/go-gitea/gitea/pull/1375)
-  * Fix Wiki Issues [#1338](https://github.com/go-gitea/gitea/pull/1338)
-  * Forgotten migration for wiki githooks [#1237](https://github.com/go-gitea/gitea/pull/1237)
-  * Commit messages can contain pipes [#1218](https://github.com/go-gitea/gitea/pull/1218)
-  * Verify external tracker URLs [#1236](https://github.com/go-gitea/gitea/pull/1236)
-  * Allow upgrade after downgrade [#1197](https://github.com/go-gitea/gitea/pull/1197)
-  * 500 on delete repo with issue [#1195](https://github.com/go-gitea/gitea/pull/1195)
-  * INI compat with CrowdIn [#1192](https://github.com/go-gitea/gitea/pull/1192)
-
-## [1.1.0](https://github.com/go-gitea/gitea/releases/tag/v1.1.0) - 2017-03-09
-
-* BREAKING
-  * The SSH keys can potentially break, make sure to regenerate the authorized keys
-* FEATURES
-  * Git LFSv2 support [#122](https://github.com/go-gitea/gitea/pull/122)
-  * API endpoints for repo watching [#191](https://github.com/go-gitea/gitea/pull/191)
-  * Search within private repos [#222](https://github.com/go-gitea/gitea/pull/222)
-  * Hide user email address on explore page [#336](https://github.com/go-gitea/gitea/pull/336)
-  * Protected branch system [#339](https://github.com/go-gitea/gitea/pull/339)
-  * Sendmail for mail delivery [#355](https://github.com/go-gitea/gitea/pull/355)
-  * API endpoints for org webhooks [#372](https://github.com/go-gitea/gitea/pull/372)
-  * Enabled MSSQL support [#383](https://github.com/go-gitea/gitea/pull/383)
-  * API endpoints for org teams [#370](https://github.com/go-gitea/gitea/pull/370)
-  * API endpoints for collaborators [#375](https://github.com/go-gitea/gitea/pull/375)
-  * Graceful server restart [#416](https://github.com/go-gitea/gitea/pull/416)
-  * Commitgraph / timeline on commits page [#428](https://github.com/go-gitea/gitea/pull/428)
-  * API endpoints for repo forks [#509](https://github.com/go-gitea/gitea/pull/509)
-  * API endpoints for releases [#510](https://github.com/go-gitea/gitea/pull/510)
-  * Folder jumping [#511](https://github.com/go-gitea/gitea/pull/511)
-  * Stars tab on profile page [#519](https://github.com/go-gitea/gitea/pull/519)
-  * Notification system [#523](https://github.com/go-gitea/gitea/pull/523)
-  * Push and pull through reverse proxy basic auth [#524](https://github.com/go-gitea/gitea/pull/524)
-  * Search for issues and pull requests [#530](https://github.com/go-gitea/gitea/pull/530)
-  * API endpoint for stargazers [#597](https://github.com/go-gitea/gitea/pull/597)
-  * API endpoints for subscribers [#598](https://github.com/go-gitea/gitea/pull/598)
-  * PID file support [#610](https://github.com/go-gitea/gitea/pull/610)
-  * Two factor authentication (2FA) [#630](https://github.com/go-gitea/gitea/pull/630)
-  * API endpoints for org users [#645](https://github.com/go-gitea/gitea/pull/645)
-  * Release attachments [#673](https://github.com/go-gitea/gitea/pull/673)
-  * OAuth2 consumer [#679](https://github.com/go-gitea/gitea/pull/679)
-  * Add ability to fork your own repos [#761](https://github.com/go-gitea/gitea/pull/761)
-  * Search repository on dashboard [#773](https://github.com/go-gitea/gitea/pull/773)
-  * Search bar on user profile [#787](https://github.com/go-gitea/gitea/pull/787)
-  * Track label changes on issue view [#788](https://github.com/go-gitea/gitea/pull/788)
-  * Allow using custom time format [#798](https://github.com/go-gitea/gitea/pull/798)
-  * Redirects for renamed repos [#807](https://github.com/go-gitea/gitea/pull/807)
-  * Track assignee changes on issue view [#808](https://github.com/go-gitea/gitea/pull/808)
-  * Track title changes on issue view [#841](https://github.com/go-gitea/gitea/pull/841)
-  * Archive cleanup action [#885](https://github.com/go-gitea/gitea/pull/885)
-  * Basic Open Graph support [#901](https://github.com/go-gitea/gitea/pull/901)
-  * Take back control of Git hooks [#1006](https://github.com/go-gitea/gitea/pull/1006)
-  * API endpoints for user repos [#1059](https://github.com/go-gitea/gitea/pull/1059)
-* BUGFIXES
-  * Fixed counting issues for issue filters [#413](https://github.com/go-gitea/gitea/pull/413)
-  * Added back default settings for SSH [#500](https://github.com/go-gitea/gitea/pull/500)
-  * Fixed repo permissions [#513](https://github.com/go-gitea/gitea/pull/513)
-  * Issues cannot be created with labels [#622](https://github.com/go-gitea/gitea/pull/622)
-  * Add a reserved wiki paths check to the wiki [#720](https://github.com/go-gitea/gitea/pull/720)
-  * Update website binding MaxSize to 255 [#722](https://github.com/go-gitea/gitea/pull/722)
-  * User can see the private activity on public history [#818](https://github.com/go-gitea/gitea/pull/818)
-  * Wrong pages number which includes private repositories [#844](https://github.com/go-gitea/gitea/pull/844)
-  * Trim whitespaces for search keyword [#893](https://github.com/go-gitea/gitea/pull/893)
-  * Don't rewrite non-gitea public keys [#906](https://github.com/go-gitea/gitea/pull/906)
-  * Use fingerprint to check instead content for public key [#911](https://github.com/go-gitea/gitea/pull/911)
-  * Fix random avatars [#1147](https://github.com/go-gitea/gitea/pull/1147)
-* ENHANCEMENTS
-  * Refactored process manager [#75](https://github.com/go-gitea/gitea/pull/75)
-  * Restrict rights to create new orgs [#193](https://github.com/go-gitea/gitea/pull/193)
-  * Added label and milestone sorting [#199](https://github.com/go-gitea/gitea/pull/199)
-  * Make minimum password length configurable [#223](https://github.com/go-gitea/gitea/pull/223)
-  * Speedup conflict checking on pull requests [#276](https://github.com/go-gitea/gitea/pull/276)
-  * Added button to delete merged pull request branches [#441](https://github.com/go-gitea/gitea/pull/441)
-  * Improved issue references within markdown [#471](https://github.com/go-gitea/gitea/pull/471)
-  * Dutch translation for the landingpage [#487](https://github.com/go-gitea/gitea/pull/487)
-  * Added Gogs migration script [#532](https://github.com/go-gitea/gitea/pull/532)
-  * Support a .gitea folder for issue templates [#582](https://github.com/go-gitea/gitea/pull/582)
-  * Enhanced diff-view coloring [#584](https://github.com/go-gitea/gitea/pull/584)
-  * Added ETag header to avatars [#721](https://github.com/go-gitea/gitea/pull/721)
-  * Added option to config to disable local path imports [#724](https://github.com/go-gitea/gitea/pull/724)
-  * Allow custom public files [#782](https://github.com/go-gitea/gitea/pull/782)
-  * Added pprof endpoint for debugging [#801](https://github.com/go-gitea/gitea/pull/801)
-  * Added `X-GitHub-*` headers [#809](https://github.com/go-gitea/gitea/pull/809)
-  * Fill SSH key title automatically [#863](https://github.com/go-gitea/gitea/pull/863)
-  * Display Git version on admin panel [#921](https://github.com/go-gitea/gitea/pull/921)
-  * Expose URL field on issue API [#982](https://github.com/go-gitea/gitea/pull/982)
-  * Statically compile the binaries [#985](https://github.com/go-gitea/gitea/pull/985)
-  * Embed build tags into version string [#1051](https://github.com/go-gitea/gitea/pull/1051)
-  * Gitignore support for FSharp and Clojure [#1072](https://github.com/go-gitea/gitea/pull/1072)
-  * Custom templates for static builds [#1087](https://github.com/go-gitea/gitea/pull/1087)
-  * Add ProxyFromEnvironment if none set [#1096](https://github.com/go-gitea/gitea/pull/1096)
-* MISC
-  * Replaced remaining Gogs references
-  * Added more tests on various packages
-  * Use Crowdin for translations again
-  * Resolved some XSS attack vectors
-  * Optimized and reduced number of database queries
-
-## [1.0.2](https://github.com/go-gitea/gitea/releases/tag/v1.0.2) - 2017-02-21
-
-* BUGFIXES
-  * Fixed issue counter [#882](https://github.com/go-gitea/gitea/pull/882)
-  * Fixed XSS vulnerability on wiki page [#955](https://github.com/go-gitea/gitea/pull/955)
-  * Add data dir without session to dump [#587](https://github.com/go-gitea/gitea/pull/587)
-  * Fixed wiki page renaming [#958](https://github.com/go-gitea/gitea/pull/958)
-  * Drop default console logger if not required [#960](https://github.com/go-gitea/gitea/pull/960)
-  * Fixed docker docs link on install page [#972](https://github.com/go-gitea/gitea/pull/972)
-  * Handle SetModel errors [#957](https://github.com/go-gitea/gitea/pull/957)
-  * Fixed XSS vulnerability on milestones [#977](https://github.com/go-gitea/gitea/pull/977)
-  * Fixed XSS vulnerability on alerts [#981](https://github.com/go-gitea/gitea/pull/981)
-
-## [1.0.1](https://github.com/go-gitea/gitea/releases/tag/v1.0.1) - 2017-01-05
-
-* BUGFIXES
-  * Fixed localized `MIN_PASSWORD_LENGTH` [#501](https://github.com/go-gitea/gitea/pull/501)
-  * Fixed 500 error on organization delete [#507](https://github.com/go-gitea/gitea/pull/507)
-  * Ignore empty wiki repo on migrate [#544](https://github.com/go-gitea/gitea/pull/544)
-  * Proper check access for forking [#563](https://github.com/go-gitea/gitea/pull/563)
-  * Fix SSH domain on installer [#506](https://github.com/go-gitea/gitea/pull/506)
-  * Fix missing data rows on admin UI [#580](https://github.com/go-gitea/gitea/pull/580)
-  * Do not delete tags with releases by default [#579](https://github.com/go-gitea/gitea/pull/579)
-  * Fix missing session config data on admin UI [#578](https://github.com/go-gitea/gitea/pull/578)
-  * Properly show the version within footer on the UI [#593](https://github.com/go-gitea/gitea/pull/593)
-
-## [1.0.0](https://github.com/go-gitea/gitea/releases/tag/v1.0.0) - 2016-12-23
-
-* BREAKING
-  * We have various changes on the API, scripting against API must be updated
-* FEATURES
-  * Show last login for admins [#121](https://github.com/go-gitea/gitea/pull/121)
-* BUGFIXES
-  * Fixed sender of notifications [#2](https://github.com/go-gitea/gitea/pull/2)
-  * Fixed keyword hijacking vulnerability [#20](https://github.com/go-gitea/gitea/pull/20)
-  * Fixed non-markdown readme rendering [#95](https://github.com/go-gitea/gitea/pull/95)
-  * Allow updating draft releases [#169](https://github.com/go-gitea/gitea/pull/169)
-  * GitHub API compliance [#227](https://github.com/go-gitea/gitea/pull/227)
-  * Added commit SHA to tag webhook [#286](https://github.com/go-gitea/gitea/issues/286)
-  * Secured links via noopener [#315](https://github.com/go-gitea/gitea/issues/315)
-  * Replace tabs with spaces on wiki title [#371](https://github.com/go-gitea/gitea/pull/371)
-  * Fixed vulnerability on labels and releases [#409](https://github.com/go-gitea/gitea/pull/409)
-  * Fixed issue comment API [#449](https://github.com/go-gitea/gitea/pull/449)
-* ENHANCEMENTS
-  * Use proper import path for libravatar [#3](https://github.com/go-gitea/gitea/pull/3)
-  * Integrated DroneCI for tests and builds [#24](https://github.com/go-gitea/gitea/issues/24)
-  * Integrated dependency manager [#29](https://github.com/go-gitea/gitea/issues/29)
-  * Embedded bindata optionally [#30](https://github.com/go-gitea/gitea/issues/30)
-  * Integrated pagination for releases [#73](https://github.com/go-gitea/gitea/pull/73)
-  * Autogenerate version on every build [#91](https://github.com/go-gitea/gitea/issues/91)
-  * Refactored Docker container [#104](https://github.com/go-gitea/gitea/issues/104)
-  * Added short-hash support for downloads [#211](https://github.com/go-gitea/gitea/issues/211)
-  * Display tooltip for downloads [#221](https://github.com/go-gitea/gitea/issues/221)
-  * Improved HTTP headers for issue attachments [#270](https://github.com/go-gitea/gitea/pull/270)
-  * Integrate public as bindata optionally [#293](https://github.com/go-gitea/gitea/pull/293)
-  * Integrate templates as bindata optionally [#314](https://github.com/go-gitea/gitea/pull/314)
-  * Inject more ENV variables into custom hooks [#316](https://github.com/go-gitea/gitea/issues/316)
-  * Correct LDAP login validation [#342](https://github.com/go-gitea/gitea/pull/342)
-  * Integrate conf as bindata optionally [#354](https://github.com/go-gitea/gitea/pull/354)
-  * Serve video files in browser [#418](https://github.com/go-gitea/gitea/pull/418)
-  * Configurable SSH host binding [#431](https://github.com/go-gitea/gitea/issues/431)
-* MISC
-  * Forked from Gogs and renamed to Gitea
-  * Catching more errors with logs
-  * Fixed all linting errors
-  * Made the go linter entirely happy
-  * Really integrated vendoring
+* [CHANGELOG-archived.md](CHANGELOG-archived.md)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2f95fdca50..eed87529a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -60,3 +60,4 @@ Nanguan Lin  (@lng2020)
 kerwin612  (@kerwin612)
 Gary Wang  (@BLumia)
 Tim-Niclas Oelschläger  (@zokkis)
+Yu Liu <1240335630@qq.com> (@HEREYUA)
diff --git a/Makefile b/Makefile
index 5ab8655c2f..2a78c907c0 100644
--- a/Makefile
+++ b/Makefile
@@ -25,26 +25,23 @@ COMMA := ,
 
 XGO_VERSION := go-1.22.x
 
-AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0
+AIR_PACKAGE ?= github.com/cosmtrek/air@v1
 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
-GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1
+GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2
 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1
-SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
+SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285
 XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
-GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
-GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.0.3
-ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.26
+GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
+GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
+ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
 
 DOCKER_IMAGE ?= gitea/gitea
 DOCKER_TAG ?= latest
 DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
 
 ifeq ($(HAS_GO), yes)
-	GOPATH ?= $(shell $(GO) env GOPATH)
-	export PATH := $(GOPATH)/bin:$(PATH)
-
 	CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
 	CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
 endif
@@ -113,7 +110,6 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G
 
 LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
 
-GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
 GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
 MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
 
@@ -122,7 +118,7 @@ FOMANTIC_WORK_DIR := web_src/fomantic
 WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
 WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
 WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
-WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack
+WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
 
 BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
 BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
@@ -147,7 +143,9 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
 GO_DIRS := build cmd models modules routers services tests
 WEB_DIRS := web_src/js web_src/css
 
-SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github
+ESLINT_FILES := web_src/js tools *.js tests/e2e
+STYLELINT_FILES := web_src/css web_src/js/components/*.vue
+SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.js *.md *.yml *.yaml *.toml))
 EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
 
 GO_SOURCES := $(wildcard *.go)
@@ -296,7 +294,7 @@ clean:
 
 .PHONY: fmt
 fmt:
-	GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
+	@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 '{{' or '(' and before '}}' or ')' unless there is only
 	@# whitespace before it
@@ -375,19 +373,19 @@ 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 tests/e2e
+	npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES)
 
 .PHONY: lint-js-fix
 lint-js-fix: node_modules
-	npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e --fix
+	npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) --fix
 
 .PHONY: lint-css
 lint-css: node_modules
-	npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue
+	npx stylelint --color --max-warnings=0 $(STYLELINT_FILES)
 
 .PHONY: lint-css-fix
 lint-css-fix: node_modules
-	npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix
+	npx stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix
 
 .PHONY: lint-swagger
 lint-swagger: node_modules
@@ -424,7 +422,7 @@ lint-go-windows:
 lint-go-vet:
 	@echo "Running go vet..."
 	@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
-	@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
+	@$(GO) vet -vettool=gitea-vet ./...
 
 .PHONY: lint-editorconfig
 lint-editorconfig:
@@ -435,7 +433,8 @@ lint-actions:
 	$(GO) run $(ACTIONLINT_PACKAGE)
 
 .PHONY: lint-templates
-lint-templates: .venv
+lint-templates: .venv node_modules
+	@node tools/lint-templates-svg.js
 	@poetry run djlint $(shell find templates -type f -iname '*.tmpl')
 
 .PHONY: lint-yaml
@@ -444,7 +443,7 @@ lint-yaml: .venv
 
 .PHONY: watch
 watch:
-	@bash build/watch.sh
+	@bash tools/watch.sh
 
 .PHONY: watch-frontend
 watch-frontend: node-check node_modules
@@ -779,7 +778,7 @@ generate-backend: $(TAGS_PREREQ) generate-go
 .PHONY: generate-go
 generate-go: $(TAGS_PREREQ)
 	@echo "Running go generate..."
-	@CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' $(GO_PACKAGES)
+	@CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' ./...
 
 .PHONY: security-check
 security-check:
@@ -839,10 +838,6 @@ release-sources: | $(DIST_DIRS)
 release-docs: | $(DIST_DIRS) docs
 	tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
 
-.PHONY: docs
-docs:
-	cd docs; bash scripts/trans-copy.sh;
-
 .PHONY: deps
 deps: deps-frontend deps-backend deps-tools deps-py
 
@@ -920,7 +915,7 @@ $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json
 .PHONY: svg
 svg: node-check | node_modules
 	rm -rf $(SVG_DEST_DIR)
-	node build/generate-svg.js
+	node tools/generate-svg.js
 
 .PHONY: svg-check
 svg-check: svg
@@ -963,8 +958,8 @@ generate-gitignore:
 
 .PHONY: generate-images
 generate-images: | node_modules
-	npm install --no-save fabric@6.0.0-beta19 imagemin-zopfli@7
-	node build/generate-images.js $(TAGS)
+	npm install --no-save fabric@6.0.0-beta20 imagemin-zopfli@7
+	node tools/generate-images.js $(TAGS)
 
 .PHONY: generate-manpage
 generate-manpage:
diff --git a/README.md b/README.md
index 94d7284c7c..f579449174 100644
--- a/README.md
+++ b/README.md
@@ -1,55 +1,18 @@
-

- - Gitea - -

-

Gitea - Git with a cup of tea

+# Gitea -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - Contribute with Gitpod - - - - - - - -

+[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly") +[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea") +[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card") +[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc") +[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release") +[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source") +[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea") +[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT") +[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/go-gitea/gitea) +[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin") +[![](https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main)](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs") -

- View this document in Chinese -

+[View this document in Chinese](./README_ZH.md) ## Purpose diff --git a/README_ZH.md b/README_ZH.md index adfeb9a8df..726c4273a6 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -1,55 +1,18 @@ -

- - Gitea - -

-

Gitea - Git with a cup of tea

+# Gitea -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - Contribute with Gitpod - - - - - - - -

+[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly") +[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea") +[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card") +[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc") +[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release") +[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source") +[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea") +[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT") +[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/go-gitea/gitea) +[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin") +[![](https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main)](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs") -

- View this document in English -

+[View this document in English](./README.md) ## 目标 diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 2aa60780c4..db94ea0d7d 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -24,11 +24,21 @@ "path": "codeberg.org/gusted/mcaptcha/LICENSE", "licenseText": "Copyright © 2022 William Zijl\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" }, + { + "name": "connectrpc.com/connect", + "path": "connectrpc.com/connect/LICENSE", + "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2021-2024 The Connect Authors\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" + }, { "name": "dario.cat/mergo", "path": "dario.cat/mergo/LICENSE", "licenseText": "Copyright (c) 2013 Dario Castañé. All rights reserved.\nCopyright (c) 2012 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": "filippo.io/edwards25519", + "path": "filippo.io/edwards25519/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": "git.sr.ht/~mariusor/go-xsd-duration", "path": "git.sr.ht/~mariusor/go-xsd-duration/LICENSE", @@ -89,11 +99,6 @@ "path": "github.com/DataDog/zstd/LICENSE", "licenseText": "Simplified BSD License\n\nCopyright (c) 2016, Datadog \u003cinfo@datadoghq.com\u003e\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n * Neither the name of the copyright holder nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (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": "github.com/NYTimes/gziphandler", - "path": "github.com/NYTimes/gziphandler/LICENSE", - "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2016-2017 The New York Times Company\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" - }, { "name": "github.com/ProtonMail/go-crypto", "path": "github.com/ProtonMail/go-crypto/LICENSE", @@ -234,11 +239,6 @@ "path": "github.com/bradfitz/gomemcache/memcache/LICENSE", "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, - { - "name": "github.com/bufbuild/connect-go", - "path": "github.com/bufbuild/connect-go/LICENSE", - "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2021-2022 Buf Technologies, Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" - }, { "name": "github.com/buildkite/terminal-to-html/v3", "path": "github.com/buildkite/terminal-to-html/v3/LICENSE", @@ -299,11 +299,6 @@ "path": "github.com/davecgh/go-spew/spew/LICENSE", "licenseText": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins \u003cdave@davec.name\u003e\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n" }, - { - "name": "github.com/denisenkom/go-mssqldb", - "path": "github.com/denisenkom/go-mssqldb/LICENSE.txt", - "licenseText": "Copyright (c) 2012 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": "github.com/dgryski/go-rendezvous", "path": "github.com/dgryski/go-rendezvous/LICENSE", @@ -535,8 +530,8 @@ "licenseText": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"[]\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, { - "name": "github.com/golang/protobuf", - "path": "github.com/golang/protobuf/LICENSE", + "name": "github.com/golang/protobuf/proto", + "path": "github.com/golang/protobuf/proto/LICENSE", "licenseText": "Copyright 2010 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\n" }, { @@ -669,6 +664,11 @@ "path": "github.com/klauspost/compress/LICENSE", "licenseText": "Copyright (c) 2012 The Go Authors. All rights reserved.\nCopyright (c) 2019 Klaus Post. 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\n------------------\n\nFiles: gzhttp/*\n\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2016-2017 The New York Times Company\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n------------------\n\nFiles: s2/cmd/internal/readahead/*\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 Klaus Post\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---------------------\nFiles: snappy/*\nFiles: internal/snapref/*\n\nCopyright (c) 2011 The Snappy-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\n-----------------\n\nFiles: s2/cmd/internal/filepathx/*\n\nCopyright 2016 The filepathx Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" }, + { + "name": "github.com/klauspost/compress/gzhttp", + "path": "github.com/klauspost/compress/gzhttp/LICENSE", + "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2016-2017 The New York Times Company\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" + }, { "name": "github.com/klauspost/compress/internal/snapref", "path": "github.com/klauspost/compress/internal/snapref/LICENSE", @@ -754,6 +754,16 @@ "path": "github.com/microcosm-cc/bluemonday/LICENSE.md", "licenseText": "SPDX short identifier: BSD-3-Clause\nhttps://opensource.org/licenses/BSD-3-Clause\n\nCopyright (c) 2014, David Kitchen \u003cdavid@buro9.com\u003e\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the organisation (Microcosm) nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (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": "github.com/microsoft/go-mssqldb", + "path": "github.com/microsoft/go-mssqldb/LICENSE.txt", + "licenseText": "Copyright (c) 2012 The Go Authors. All rights reserved.\nCopyright (c) Microsoft Corporation.\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": "github.com/microsoft/go-mssqldb/internal/github.com/swisscom/mssql-always-encrypted/pkg", + "path": "github.com/microsoft/go-mssqldb/internal/github.com/swisscom/mssql-always-encrypted/pkg/LICENSE.txt", + "licenseText": "Copyright (c) 2021 Swisscom (Switzerland) Ltd\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n" + }, { "name": "github.com/miekg/dns", "path": "github.com/miekg/dns/LICENSE", @@ -1066,7 +1076,7 @@ }, { "name": "go.uber.org/zap", - "path": "go.uber.org/zap/LICENSE.txt", + "path": "go.uber.org/zap/LICENSE", "licenseText": "Copyright (c) 2016-2017 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n" }, { diff --git a/build/code-batch-process.go b/build/code-batch-process.go index b3ee399420..cc2ab68026 100644 --- a/build/code-batch-process.go +++ b/build/code-batch-process.go @@ -69,6 +69,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error) co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`)) co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`)) + co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`\.pb\.go$`)) co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`)) co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`)) co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`)) @@ -203,17 +204,6 @@ Example: `, "file-batch-exec") } -func getGoVersion() string { - goModFile, err := os.ReadFile("go.mod") - if err != nil { - log.Fatalf(`Faild to read "go.mod": %v`, err) - os.Exit(1) - } - goModVersionRegex := regexp.MustCompile(`go \d+\.\d+`) - goModVersionLine := goModVersionRegex.Find(goModFile) - return string(goModVersionLine[3:]) -} - func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) { fileFilter := mainOptions["file-filter"] if fileFilter == "" { @@ -278,7 +268,8 @@ func main() { log.Print("the -d option is not supported by gitea-fmt") } cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w"))) - cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", getGoVersion()}, substArgs...))) + cmdErrors = append(cmdErrors, passThroughCmd("gofmt", append([]string{"-w", "-r", "interface{} -> any"}, substArgs...))) + cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra"}, substArgs...))) default: log.Fatalf("unknown cmd: %s %v", subCmd, subArgs) } diff --git a/cmd/admin_auth.go b/cmd/admin_auth.go index ec92e342d4..4777a92908 100644 --- a/cmd/admin_auth.go +++ b/cmd/admin_auth.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" "os" "text/tabwriter" @@ -91,7 +92,7 @@ func runListAuth(c *cli.Context) error { func runDeleteAuth(c *cli.Context) error { if !c.IsSet("id") { - return fmt.Errorf("--id flag is missing") + return errors.New("--id flag is missing") } ctx, cancel := installSignals() diff --git a/cmd/admin_auth_oauth.go b/cmd/admin_auth_oauth.go index c151c0af27..8e6239ac33 100644 --- a/cmd/admin_auth_oauth.go +++ b/cmd/admin_auth_oauth.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" "net/url" @@ -193,7 +194,7 @@ func runAddOauth(c *cli.Context) error { func runUpdateOauth(c *cli.Context) error { if !c.IsSet("id") { - return fmt.Errorf("--id flag is missing") + return errors.New("--id flag is missing") } ctx, cancel := installSignals() diff --git a/cmd/admin_auth_stmp.go b/cmd/admin_auth_stmp.go index 58a6e2ac22..d724746905 100644 --- a/cmd/admin_auth_stmp.go +++ b/cmd/admin_auth_stmp.go @@ -5,7 +5,6 @@ package cmd import ( "errors" - "fmt" "strings" auth_model "code.gitea.io/gitea/models/auth" @@ -166,7 +165,7 @@ func runAddSMTP(c *cli.Context) error { func runUpdateSMTP(c *cli.Context) error { if !c.IsSet("id") { - return fmt.Errorf("--id flag is missing") + return errors.New("--id flag is missing") } ctx, cancel := installSignals() diff --git a/cmd/admin_user_change_password.go b/cmd/admin_user_change_password.go index 824d66d112..bd9063a8e4 100644 --- a/cmd/admin_user_change_password.go +++ b/cmd/admin_user_change_password.go @@ -36,6 +36,7 @@ var microcmdUserChangePassword = &cli.Command{ &cli.BoolFlag{ Name: "must-change-password", Usage: "User must change password", + Value: true, }, }, } @@ -57,23 +58,18 @@ func runChangePassword(c *cli.Context) error { return err } - var mustChangePassword optional.Option[bool] - if c.IsSet("must-change-password") { - mustChangePassword = optional.Some(c.Bool("must-change-password")) - } - opts := &user_service.UpdateAuthOptions{ Password: optional.Some(c.String("password")), - MustChangePassword: mustChangePassword, + MustChangePassword: optional.Some(c.Bool("must-change-password")), } if err := user_service.UpdateAuth(ctx, user, opts); err != nil { switch { case errors.Is(err, password.ErrMinLength): - return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength) + return fmt.Errorf("password is not long enough, needs to be at least %d characters", setting.MinPasswordLength) case errors.Is(err, password.ErrComplexity): - return errors.New("Password does not meet complexity requirements") + return errors.New("password does not meet complexity requirements") case errors.Is(err, password.ErrIsPwned): - return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords") + return errors.New("the password is in a list of stolen passwords previously exposed in public data breaches, please try again with a different password, to see more details: https://haveibeenpwned.com/Passwords") default: return err } diff --git a/cmd/admin_user_create.go b/cmd/admin_user_create.go index a257ce21c8..403e3ee8d8 100644 --- a/cmd/admin_user_create.go +++ b/cmd/admin_user_create.go @@ -8,6 +8,7 @@ import ( "fmt" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" pwd "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/optional" @@ -46,8 +47,9 @@ var microcmdUserCreate = &cli.Command{ Usage: "Generate a random password for the user", }, &cli.BoolFlag{ - Name: "must-change-password", - Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)", + Name: "must-change-password", + Usage: "Set to false to prevent forcing the user to change their password after initial login", + DisableDefaultText: true, }, &cli.IntFlag{ Name: "random-password-length", @@ -71,10 +73,10 @@ func runCreateUser(c *cli.Context) error { } if c.IsSet("name") && c.IsSet("username") { - return errors.New("Cannot set both --name and --username flags") + return errors.New("cannot set both --name and --username flags") } if !c.IsSet("name") && !c.IsSet("username") { - return errors.New("One of --name or --username flags must be set") + return errors.New("one of --name or --username flags must be set") } if c.IsSet("password") && c.IsSet("random-password") { @@ -110,17 +112,21 @@ func runCreateUser(c *cli.Context) error { return errors.New("must set either password or random-password flag") } - // always default to true - changePassword := true - - // If this is the first user being created. - // Take it as the admin and don't force a password update. - if n := user_model.CountUsers(ctx, nil); n == 0 { - changePassword = false - } - + isAdmin := c.Bool("admin") + mustChangePassword := true // always default to true if c.IsSet("must-change-password") { - changePassword = c.Bool("must-change-password") + // if the flag is set, use the value provided by the user + mustChangePassword = c.Bool("must-change-password") + } else { + // check whether there are users in the database + hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{}) + if err != nil { + return fmt.Errorf("IsTableNotEmpty: %w", err) + } + if !hasUserRecord && isAdmin { + // if this is the first admin being created, don't force to change password (keep the old behavior) + mustChangePassword = false + } } restricted := optional.None[bool]() @@ -136,8 +142,8 @@ func runCreateUser(c *cli.Context) error { Name: username, Email: c.String("email"), Passwd: password, - IsAdmin: c.Bool("admin"), - MustChangePassword: changePassword, + IsAdmin: isAdmin, + MustChangePassword: mustChangePassword, Visibility: visibility, } diff --git a/cmd/admin_user_delete.go b/cmd/admin_user_delete.go index 1cbc6f7527..520557554a 100644 --- a/cmd/admin_user_delete.go +++ b/cmd/admin_user_delete.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" "strings" @@ -42,7 +43,7 @@ var microcmdUserDelete = &cli.Command{ func runDeleteUser(c *cli.Context) error { if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") { - return fmt.Errorf("You must provide the id, username or email of a user to delete") + return errors.New("You must provide the id, username or email of a user to delete") } ctx, cancel := installSignals() diff --git a/cmd/admin_user_generate_access_token.go b/cmd/admin_user_generate_access_token.go index 6e78939680..6c2c10494e 100644 --- a/cmd/admin_user_generate_access_token.go +++ b/cmd/admin_user_generate_access_token.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" auth_model "code.gitea.io/gitea/models/auth" @@ -42,7 +43,7 @@ var microcmdUserGenerateAccessToken = &cli.Command{ func runGenerateAccessToken(c *cli.Context) error { if !c.IsSet("username") { - return fmt.Errorf("You must provide a username to generate a token for") + return errors.New("You must provide a username to generate a token for") } ctx, cancel := installSignals() @@ -68,7 +69,7 @@ func runGenerateAccessToken(c *cli.Context) error { return err } if exist { - return fmt.Errorf("access token name has been used already") + return errors.New("access token name has been used already") } // make sure the scopes are valid diff --git a/cmd/dump.go b/cmd/dump.go index 69ecdcec12..ececc80f72 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -6,14 +6,13 @@ package cmd import ( "fmt" - "io" "os" "path" "path/filepath" "strings" - "time" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/dump" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -25,89 +24,17 @@ import ( "github.com/urfave/cli/v2" ) -func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error { - if verbose { - log.Info("Adding file %s", customName) - } - - return w.Write(archiver.File{ - FileInfo: archiver.FileInfo{ - FileInfo: info, - CustomName: customName, - }, - ReadCloser: r, - }) -} - -func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error { - file, err := os.Open(absPath) - if err != nil { - return err - } - defer file.Close() - fileInfo, err := file.Stat() - if err != nil { - return err - } - - return addReader(w, file, fileInfo, filePath, verbose) -} - -func isSubdir(upper, lower string) (bool, error) { - if relPath, err := filepath.Rel(upper, lower); err != nil { - return false, err - } else if relPath == "." || !strings.HasPrefix(relPath, ".") { - return true, nil - } - return false, nil -} - -type outputType struct { - Enum []string - Default string - selected string -} - -func (o outputType) Join() string { - return strings.Join(o.Enum, ", ") -} - -func (o *outputType) Set(value string) error { - for _, enum := range o.Enum { - if enum == value { - o.selected = value - return nil - } - } - - return fmt.Errorf("allowed values are %s", o.Join()) -} - -func (o outputType) String() string { - if o.selected == "" { - return o.Default - } - return o.selected -} - -var outputTypeEnum = &outputType{ - Enum: []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4", "tar.zst"}, - Default: "zip", -} - // CmdDump represents the available dump sub-command. var CmdDump = &cli.Command{ - Name: "dump", - Usage: "Dump Gitea files and database", - Description: `Dump compresses all related files and database into zip file. -It can be used for backup and capture Gitea server image to send to maintainer`, - Action: runDump, + Name: "dump", + Usage: "Dump Gitea files and database", + Description: `Dump compresses all related files and database into zip file. It can be used for backup and capture Gitea server image to send to maintainer`, + Action: runDump, Flags: []cli.Flag{ &cli.StringFlag{ Name: "file", Aliases: []string{"f"}, - Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()), - Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.", + Usage: `Name of the dump file which will be created, default to "gitea-dump-{time}.zip". Supply '-' for stdout. See type for available types.`, }, &cli.BoolFlag{ Name: "verbose", @@ -160,64 +87,56 @@ It can be used for backup and capture Gitea server image to send to maintainer`, Name: "skip-index", Usage: "Skip bleve index data", }, - &cli.GenericFlag{ + &cli.BoolFlag{ + Name: "skip-db", + Usage: "Skip database", + }, + &cli.StringFlag{ Name: "type", - Value: outputTypeEnum, - Usage: fmt.Sprintf("Dump output format: %s", outputTypeEnum.Join()), + Usage: fmt.Sprintf(`Dump output format, default to "zip", supported types: %s`, strings.Join(dump.SupportedOutputTypes, ", ")), }, }, } func fatal(format string, args ...any) { - fmt.Fprintf(os.Stderr, format+"\n", args...) log.Fatal(format, args...) } func runDump(ctx *cli.Context) error { - var file *os.File - fileName := ctx.String("file") - outType := ctx.String("type") - if fileName == "-" { - file = os.Stdout - setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr) - } else { - for _, suffix := range outputTypeEnum.Enum { - if strings.HasSuffix(fileName, "."+suffix) { - fileName = strings.TrimSuffix(fileName, "."+suffix) - break - } - } - fileName += "." + outType - } setting.MustInstalled() - // make sure we are logging to the console no matter what the configuration tells us do to - // FIXME: don't use CfgProvider directly - if _, err := setting.CfgProvider.Section("log").NewKey("MODE", "console"); err != nil { - fatal("Setting logging mode to console failed: %v", err) - } - if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil { - fatal("Setting console logger to stderr failed: %v", err) - } - - // Set loglevel to Warn if quiet-mode is requested - if ctx.Bool("quiet") { - if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil { - fatal("Setting console log-level failed: %v", err) - } - } - - if !setting.InstallLock { - log.Error("Is '%s' really the right config path?\n", setting.CustomConf) - return fmt.Errorf("gitea is not initialized") - } - setting.LoadSettings() // cannot access session settings otherwise - + quite := ctx.Bool("quiet") verbose := ctx.Bool("verbose") - if verbose && ctx.Bool("quiet") { - return fmt.Errorf("--quiet and --verbose cannot both be set") + if verbose && quite { + fatal("Option --quiet and --verbose cannot both be set") } + // outFileName is either "-" or a file name (will be made absolute) + outFileName, outType := dump.PrepareFileNameAndType(ctx.String("file"), ctx.String("type")) + if outType == "" { + fatal("Invalid output type") + } + + outFile := os.Stdout + if outFileName != "-" { + var err error + if outFileName, err = filepath.Abs(outFileName); err != nil { + fatal("Unable to get absolute path of dump file: %v", err) + } + if exist, _ := util.IsExist(outFileName); exist { + fatal("Dump file %q exists", outFileName) + } + if outFile, err = os.Create(outFileName); err != nil { + fatal("Unable to create dump file %q: %v", outFileName, err) + } + defer outFile.Close() + } + + setupConsoleLogger(util.Iif(quite, log.WARN, log.INFO), log.CanColorStderr, os.Stderr) + + setting.DisableLoggerInit() + setting.LoadSettings() // cannot access session settings otherwise + stdCtx, cancel := installSignals() defer cancel() @@ -226,44 +145,32 @@ func runDump(ctx *cli.Context) error { return err } - if err := storage.Init(); err != nil { + if err = storage.Init(); err != nil { return err } - if file == nil { - file, err = os.Create(fileName) - if err != nil { - fatal("Unable to open %s: %v", fileName, err) - } - } - defer file.Close() - - absFileName, err := filepath.Abs(fileName) - if err != nil { - return err - } - - var iface any - if fileName == "-" { - iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType)) - } else { - iface, err = archiver.ByExtension(fileName) - } + archiverGeneric, err := archiver.ByExtension("." + outType) if err != nil { fatal("Unable to get archiver for extension: %v", err) } - w, _ := iface.(archiver.Writer) - if err := w.Create(file); err != nil { + archiverWriter := archiverGeneric.(archiver.Writer) + if err := archiverWriter.Create(outFile); err != nil { fatal("Creating archiver.Writer failed: %v", err) } - defer w.Close() + defer archiverWriter.Close() + + dumper := &dump.Dumper{ + Writer: archiverWriter, + Verbose: verbose, + } + dumper.GlobalExcludeAbsPath(outFileName) if ctx.IsSet("skip-repository") && ctx.Bool("skip-repository") { log.Info("Skip dumping local repositories") } else { log.Info("Dumping local repositories... %s", setting.RepoRootPath) - if err := addRecursiveExclude(w, "repos", setting.RepoRootPath, []string{absFileName}, verbose); err != nil { + if err := dumper.AddRecursiveExclude("repos", setting.RepoRootPath, nil); err != nil { fatal("Failed to include repositories: %v", err) } @@ -276,49 +183,52 @@ func runDump(ctx *cli.Context) error { if err != nil { return err } - - return addReader(w, object, info, path.Join("data", "lfs", objPath), verbose) + return dumper.AddReader(object, info, path.Join("data", "lfs", objPath)) }); err != nil { fatal("Failed to dump LFS objects: %v", err) } } - tmpDir := ctx.String("tempdir") - if _, err := os.Stat(tmpDir); os.IsNotExist(err) { - fatal("Path does not exist: %s", tmpDir) - } - - dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql") - if err != nil { - fatal("Failed to create tmp file: %v", err) - } - defer func() { - _ = dbDump.Close() - if err := util.Remove(dbDump.Name()); err != nil { - log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err) - } - }() - - targetDBType := ctx.String("database") - if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() { - log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType) + if ctx.Bool("skip-db") { + // Ensure that we don't dump the database file that may reside in setting.AppDataPath or elsewhere. + dumper.GlobalExcludeAbsPath(setting.Database.Path) + log.Info("Skipping database") } else { - log.Info("Dumping database...") - } - - if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil { - fatal("Failed to dump database: %v", err) - } - - if err := addFile(w, "gitea-db.sql", dbDump.Name(), verbose); err != nil { - fatal("Failed to include gitea-db.sql: %v", err) - } - - if len(setting.CustomConf) > 0 { - log.Info("Adding custom configuration file from %s", setting.CustomConf) - if err := addFile(w, "app.ini", setting.CustomConf, verbose); err != nil { - fatal("Failed to include specified app.ini: %v", err) + tmpDir := ctx.String("tempdir") + if _, err := os.Stat(tmpDir); os.IsNotExist(err) { + fatal("Path does not exist: %s", tmpDir) } + + dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql") + if err != nil { + fatal("Failed to create tmp file: %v", err) + } + defer func() { + _ = dbDump.Close() + if err := util.Remove(dbDump.Name()); err != nil { + log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err) + } + }() + + targetDBType := ctx.String("database") + if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() { + log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType) + } else { + log.Info("Dumping database...") + } + + if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil { + fatal("Failed to dump database: %v", err) + } + + if err = dumper.AddFile("gitea-db.sql", dbDump.Name()); err != nil { + fatal("Failed to include gitea-db.sql: %v", err) + } + } + + log.Info("Adding custom configuration file from %s", setting.CustomConf) + if err = dumper.AddFile("app.ini", setting.CustomConf); err != nil { + fatal("Failed to include specified app.ini: %v", err) } if ctx.IsSet("skip-custom-dir") && ctx.Bool("skip-custom-dir") { @@ -326,8 +236,8 @@ func runDump(ctx *cli.Context) error { } else { customDir, err := os.Stat(setting.CustomPath) if err == nil && customDir.IsDir() { - if is, _ := isSubdir(setting.AppDataPath, setting.CustomPath); !is { - if err := addRecursiveExclude(w, "custom", setting.CustomPath, []string{absFileName}, verbose); err != nil { + if is, _ := dump.IsSubdir(setting.AppDataPath, setting.CustomPath); !is { + if err := dumper.AddRecursiveExclude("custom", setting.CustomPath, nil); err != nil { fatal("Failed to include custom: %v", err) } } else { @@ -364,8 +274,7 @@ func runDump(ctx *cli.Context) error { excludes = append(excludes, setting.Attachment.Storage.Path) excludes = append(excludes, setting.Packages.Storage.Path) excludes = append(excludes, setting.Log.RootPath) - excludes = append(excludes, absFileName) - if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil { + if err := dumper.AddRecursiveExclude("data", setting.AppDataPath, excludes); err != nil { fatal("Failed to include data directory: %v", err) } } @@ -377,8 +286,7 @@ func runDump(ctx *cli.Context) error { if err != nil { return err } - - return addReader(w, object, info, path.Join("data", "attachments", objPath), verbose) + return dumper.AddReader(object, info, path.Join("data", "attachments", objPath)) }); err != nil { fatal("Failed to dump attachments: %v", err) } @@ -392,8 +300,7 @@ func runDump(ctx *cli.Context) error { if err != nil { return err } - - return addReader(w, object, info, path.Join("data", "packages", objPath), verbose) + return dumper.AddReader(object, info, path.Join("data", "packages", objPath)) }); err != nil { fatal("Failed to dump packages: %v", err) } @@ -409,80 +316,23 @@ func runDump(ctx *cli.Context) error { log.Error("Unable to check if %s exists. Error: %v", setting.Log.RootPath, err) } if isExist { - if err := addRecursiveExclude(w, "log", setting.Log.RootPath, []string{absFileName}, verbose); err != nil { + if err := dumper.AddRecursiveExclude("log", setting.Log.RootPath, nil); err != nil { fatal("Failed to include log: %v", err) } } } - if fileName != "-" { - if err = w.Close(); err != nil { - _ = util.Remove(fileName) - fatal("Failed to save %s: %v", fileName, err) + if outFileName == "-" { + log.Info("Finish dumping to stdout") + } else { + if err = archiverWriter.Close(); err != nil { + _ = os.Remove(outFileName) + fatal("Failed to save %q: %v", outFileName, err) } - - if err := os.Chmod(fileName, 0o600); err != nil { + if err = os.Chmod(outFileName, 0o600); err != nil { log.Info("Can't change file access permissions mask to 0600: %v", err) } - } - - if fileName != "-" { - log.Info("Finish dumping in file %s", fileName) - } else { - log.Info("Finish dumping to stdout") - } - - return nil -} - -// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath -func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error { - absPath, err := filepath.Abs(absPath) - if err != nil { - return err - } - dir, err := os.Open(absPath) - if err != nil { - return err - } - defer dir.Close() - - files, err := dir.Readdir(0) - if err != nil { - return err - } - for _, file := range files { - currentAbsPath := filepath.Join(absPath, file.Name()) - currentInsidePath := path.Join(insidePath, file.Name()) - if file.IsDir() { - if !util.SliceContainsString(excludeAbsPath, currentAbsPath) { - if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil { - return err - } - if err = addRecursiveExclude(w, currentInsidePath, currentAbsPath, excludeAbsPath, verbose); err != nil { - return err - } - } - } else { - // only copy regular files and symlink regular files, skip non-regular files like socket/pipe/... - shouldAdd := file.Mode().IsRegular() - if !shouldAdd && file.Mode()&os.ModeSymlink == os.ModeSymlink { - target, err := filepath.EvalSymlinks(currentAbsPath) - if err != nil { - return err - } - targetStat, err := os.Stat(target) - if err != nil { - return err - } - shouldAdd = targetStat.Mode().IsRegular() - } - if shouldAdd { - if err = addFile(w, currentInsidePath, currentAbsPath, verbose); err != nil { - return err - } - } - } + log.Info("Finish dumping in file %s", outFileName) } return nil } diff --git a/cmd/embedded.go b/cmd/embedded.go index 71d483d11c..9f03f7be7c 100644 --- a/cmd/embedded.go +++ b/cmd/embedded.go @@ -157,9 +157,9 @@ func runViewDo(c *cli.Context) error { } if len(matchedAssetFiles) == 0 { - return fmt.Errorf("no files matched the given pattern") + return errors.New("no files matched the given pattern") } else if len(matchedAssetFiles) > 1 { - return fmt.Errorf("too many files matched the given pattern, try to be more specific") + return errors.New("too many files matched the given pattern, try to be more specific") } data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name) @@ -180,7 +180,7 @@ func runExtractDo(c *cli.Context) error { } if c.NArg() == 0 { - return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)") + return errors.New("a list of pattern of files to extract is mandatory (e.g. '**' for all)") } destdir := "." diff --git a/cmd/hook.go b/cmd/hook.go index 6a3358853d..2a9c25add5 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -448,23 +448,26 @@ Gitea or set your environment appropriately.`, "") func hookPrintResults(results []private.HookPostReceiveBranchResult) { for _, res := range results { - if !res.Message { - continue - } - - fmt.Fprintln(os.Stderr, "") - if res.Create { - fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res.Branch) - fmt.Fprintf(os.Stderr, " %s\n", res.URL) - } else { - fmt.Fprint(os.Stderr, "Visit the existing pull request:\n") - fmt.Fprintf(os.Stderr, " %s\n", res.URL) - } - fmt.Fprintln(os.Stderr, "") - os.Stderr.Sync() + hookPrintResult(res.Message, res.Create, res.Branch, res.URL) } } +func hookPrintResult(output, isCreate bool, branch, url string) { + if !output { + return + } + fmt.Fprintln(os.Stderr, "") + if isCreate { + fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch) + fmt.Fprintf(os.Stderr, " %s\n", url) + } else { + fmt.Fprint(os.Stderr, "Visit the existing pull request:\n") + fmt.Fprintf(os.Stderr, " %s\n", url) + } + fmt.Fprintln(os.Stderr, "") + _ = os.Stderr.Sync() +} + func pushOptions() map[string]string { opts := make(map[string]string) if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil { @@ -691,6 +694,12 @@ Gitea or set your environment appropriately.`, "") } err = writeFlushPktLine(ctx, os.Stdout) + if err == nil { + for _, res := range resp.Results { + hookPrintResult(res.ShouldShowMessage, res.IsCreatePR, res.HeadBranch, res.URL) + } + } + return err } diff --git a/cmd/manager_logging.go b/cmd/manager_logging.go index 7d34fc9ac2..c2ae25ec57 100644 --- a/cmd/manager_logging.go +++ b/cmd/manager_logging.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" "os" @@ -249,7 +250,7 @@ func runAddFileLogger(c *cli.Context) error { if c.IsSet("filename") { vals["filename"] = c.String("filename") } else { - return fmt.Errorf("filename must be set when creating a file logger") + return errors.New("filename must be set when creating a file logger") } if c.IsSet("rotate") { vals["rotate"] = c.Bool("rotate") diff --git a/cmd/web.go b/cmd/web.go index 01386251be..ef8a7426c1 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -114,7 +114,7 @@ func showWebStartupMessage(msg string) { log.Info("* WorkPath: %s", setting.AppWorkPath) log.Info("* CustomPath: %s", setting.CustomPath) log.Info("* ConfigFile: %s", setting.CustomConf) - log.Info("%s", msg) + log.Info("%s", msg) // show startup message } func serveInstall(ctx *cli.Context) error { diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000000..35a38d768c --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,12 @@ +project_id_env: CROWDIN_PROJECT_ID +api_token_env: CROWDIN_KEY +base_path: "." +base_url: "https://api.crowdin.com" +preserve_hierarchy: true +files: + - source: "/options/locale/locale_en-US.ini" + translation: "/options/locale/locale_%locale%.ini" + type: "ini" + skip_untranslated_strings: true + export_only_approved: true + update_option: "update_as_unapproved" diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 17d6cd3a35..62db26fb02 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -441,7 +441,7 @@ INTERNAL_TOKEN = ;INTERNAL_TOKEN_URI = file:/etc/gitea/internal_token ;; ;; How long to remember that a user is logged in before requiring relogin (in days) -;LOGIN_REMEMBER_DAYS = 7 +;LOGIN_REMEMBER_DAYS = 31 ;; ;; Name of the cookie used to store the current username. ;COOKIE_USERNAME = gitea_awesome @@ -1231,7 +1231,8 @@ LEVEL = Info ;DEFAULT_THEME = gitea-auto ;; ;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`. -;THEMES = gitea-auto,gitea-light,gitea-dark +;; Leave it empty to allow users to select any theme from "{CustomPath}/public/assets/css/theme-*.css" +;THEMES = ;; ;; All available reactions users can choose on issues/prs and comments. ;; Values can be emoji alias (:smile:) or a unicode emoji. @@ -1485,6 +1486,11 @@ LEVEL = Info ;; - manage_ssh_keys: a user cannot configure ssh keys ;; - manage_gpg_keys: a user cannot configure gpg keys ;USER_DISABLED_FEATURES = +;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior. +;; - deletion: a user cannot delete their own account +;; - manage_ssh_keys: a user cannot configure ssh keys +;; - manage_gpg_keys: a user cannot configure gpg keys +;;EXTERNAL_USER_DISABLE_FEATURES = ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1548,11 +1554,12 @@ LEVEL = Info ;; The source of the username for new oauth2 accounts: ;; userid = use the userid / sub attribute ;; nickname = use the nickname attribute +;; preferred_username = use the preferred_username attribute ;; email = use the username part of the email attribute -;; Note: `nickname` and `email` options will normalize input strings using the following criteria: +;; Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria: ;; - diacritics are removed -;; - the characters in the set `['´\x60]` are removed -;; - the characters in the set `[\s~+]` are replaced with `-` +;; - the characters in the set ['´`] are removed +;; - the characters in the set [\s~+] are replaced with "-" ;USERNAME = nickname ;; ;; Update avatar if available from oauth2 provider. @@ -2310,6 +2317,8 @@ LEVEL = Info ;SHOW_FOOTER_VERSION = true ;; Show template execution time in the footer ;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true +;; Show the "powered by" text in the footer +;SHOW_FOOTER_POWERED_BY = true ;; Generate sitemap. Defaults to `true`. ;ENABLE_SITEMAP = true ;; Enable/Disable RSS/Atom feed @@ -2369,22 +2378,6 @@ LEVEL = Info ;; Enable issue by repository metrics; default is false ;ENABLED_ISSUE_BY_REPOSITORY = false -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;[task] -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Task queue type, could be `channel` or `redis`. -;QUEUE_TYPE = channel -;; -;; Task queue length, available only when `QUEUE_TYPE` is `channel`. -;QUEUE_LENGTH = 1000 -;; -;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`. -;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for `redis-clsuter`. -;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s" - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;[migrations] @@ -2608,7 +2601,7 @@ LEVEL = Info ;ENDLESS_TASK_TIMEOUT = 3h ;; Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time ;ABANDONED_JOB_TIMEOUT = 24h -;; Strings committers can place inside a commit message to skip executing the corresponding actions workflow +;; Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow ;SKIP_WORKFLOW_STRINGS = [skip ci],[ci skip],[no ci],[skip actions],[actions skip] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/administration/cmd-embedded.zh-cn.md b/docs/content/administration/cmd-embedded.zh-cn.md index 4570bb58a3..a2df1aa2f5 100644 --- a/docs/content/administration/cmd-embedded.zh-cn.md +++ b/docs/content/administration/cmd-embedded.zh-cn.md @@ -37,7 +37,7 @@ gitea embedded list [--include-vendored] [patterns...] - 列出所有模板文件,无论在哪个虚拟目录下:`**.tmpl` - 列出所有邮件模板文件:`templates/mail/**.tmpl` -- 列出 `public/img` 目录下的所有文件:`public/img/**` +列出 `public/assets/img` 目录下的所有文件:`public/assets/img/**` 不要忘记为模式使用引号,因为空格、`*` 和其他字符可能对命令行解释器有特殊含义。 @@ -49,8 +49,8 @@ gitea embedded list [--include-vendored] [patterns...] ```sh $ gitea embedded list '**openid**' -public/img/auth/openid_connect.svg -public/img/openid-16x16.png +public/assets/img/auth/openid_connect.svg +public/assets/img/openid-16x16.png templates/user/auth/finalize_openid.tmpl templates/user/auth/signin_openid.tmpl templates/user/auth/signup_openid_connect.tmpl diff --git a/docs/content/administration/command-line.en-us.md b/docs/content/administration/command-line.en-us.md index 5049df35e0..752a8d4c6f 100644 --- a/docs/content/administration/command-line.en-us.md +++ b/docs/content/administration/command-line.en-us.md @@ -83,8 +83,7 @@ Admin operations: - `--email value`: Email. Required. - `--admin`: If provided, this makes the user an admin. Optional. - `--access-token`: If provided, an access token will be created for the user. Optional. (default: false). - - `--must-change-password`: If provided, the created user will be required to choose a newer password after the - initial login. Optional. (default: true). + - `--must-change-password`: The created user will be required to set a new password after the initial login, default: true. It could be disabled by `--must-change-password=false`. - `--random-password`: If provided, a randomly generated password will be used as the password of the created user. The value of `--password` will be discarded. Optional. - `--random-password-length`: If provided, it will be used to configure the length of the randomly generated @@ -95,7 +94,7 @@ Admin operations: - Options: - `--username value`, `-u value`: Username. Required. - `--password value`, `-p value`: New password. Required. - - `--must-change-password`: If provided, the user is required to choose a new password after the login. Optional. + - `--must-change-password`: The user is required to set a new password after the login, default: true. It could be disabled by `--must-change-password=false`. - Examples: - `gitea admin user change-password --username myname --password asecurepassword` - `must-change-password`: diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index 8a01711949..14f562fc21 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -214,10 +214,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `SITEMAP_PAGING_NUM`: **20**: Number of items that are displayed in a single subsitemap. - `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph. - `CODE_COMMENT_LINES`: **4**: Number of line of codes shown for a code comment. -- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: Set the default theme for the Gitea installation. +- `DEFAULT_THEME`: **gitea-auto**: Set the default theme for the Gitea installation, custom themes could be provided by "{CustomPath}/public/assets/css/theme-*.css". - `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page. -- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes. - regardless of the value of `DEFAULT_THEME`. +- `THEMES`: **_empty_**: All available themes by "{CustomPath}/public/assets/css/theme-*.css". Allow users select personalized themes. - `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB) - `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI - `REACTIONS`: All available reactions users can choose on issues/prs and comments @@ -522,13 +521,17 @@ And the following unique queues: - `deletion`: User cannot delete their own account. - `manage_ssh_keys`: User cannot configure ssh keys. - `manage_gpg_keys`: User cannot configure gpg keys. +- `EXTERNAL_USER_DISABLE_FEATURES`: **_empty_**: Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior. + - `deletion`: User cannot delete their own account. + - `manage_ssh_keys`: User cannot configure ssh keys. + - `manage_gpg_keys`: User cannot configure gpg keys. ## Security (`security`) - `INSTALL_LOCK`: **false**: Controls access to the installation page. When set to "true", the installation page is not accessible. - `SECRET_KEY`: **\**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore. - `SECRET_KEY_URI`: **_empty_**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY. -- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days. +- `LOGIN_REMEMBER_DAYS`: **31**: How long to remember that a user is logged in before requiring relogin (in days). - `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication information. - `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy @@ -590,7 +593,7 @@ And the following unique queues: ## OpenID (`openid`) -- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID. +- `ENABLE_OPENID_SIGNIN`: **true**: Allow authentication in via OpenID. - `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID. - `WHITELISTED_URIS`: **_empty_**: If non-empty, list of POSIX regex patterns matching OpenID URI's to permit. @@ -604,11 +607,12 @@ And the following unique queues: - `ENABLE_AUTO_REGISTRATION`: **false**: Automatically create user accounts for new oauth2 users. - `USERNAME`: **nickname**: The source of the username for new oauth2 accounts: - `userid` - use the userid / sub attribute - - `nickname` - use the nickname attribute + - `nickname` - use the nickname + - `preferred_username` - use the preferred_username - `email` - use the username part of the email attribute - - Note: `nickname` and `email` options will normalize input strings using the following criteria: + - Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria: - diacritics are removed - - the characters in the set `['´\x60]` are removed + - the characters in the set ```['´`]``` are removed - the characters in the set `[\s~+]` are replaced with `-` - `UPDATE_AVATAR`: **false**: Update avatar if available from oauth2 provider. Update will be performed on each login. - `ACCOUNT_LINKING`: **login**: How to handle if an account / email already exists: @@ -832,7 +836,7 @@ Default templates for project boards: ## Issue and pull request attachments (`attachment`) - `ENABLED`: **true**: Whether issue and pull request attachments are enabled. -- `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. +- `ALLOWED_TYPES`: **.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. - `MAX_SIZE`: **2048**: Maximum size (MB). - `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once. - `STORAGE_TYPE`: **local**: Storage type for attachments, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]` @@ -1193,14 +1197,6 @@ in this mapping or the filetype using heuristics. - `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai -## Task (`task`) - -Task queue configuration has been moved to `queue.task`. However, the below configuration values are kept for backwards compatibility: - -- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`. -- `QUEUE_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`. -- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0` or `redis+cluster://123@127.0.0.1:6379/0`. - ## Migrations (`migrations`) - `MAX_ATTEMPTS`: **3**: Max attempts per http/https request on migrations. @@ -1406,7 +1402,7 @@ PROXY_HOSTS = *.github.com - `ZOMBIE_TASK_TIMEOUT`: **10m**: Timeout to stop the task which have running status, but haven't been updated for a long time - `ENDLESS_TASK_TIMEOUT`: **3h**: Timeout to stop the tasks which have running status and continuous updates, but don't end for a long time - `ABANDONED_JOB_TIMEOUT`: **24h**: Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time -- `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: Strings committers can place inside a commit message to skip executing the corresponding actions workflow +- `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow `DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path. For example, `uses: actions/checkout@v4` means `https://github.com/actions/checkout@v4` since the value of `DEFAULT_ACTIONS_URL` is `github`. @@ -1425,5 +1421,6 @@ Like `uses: https://gitea.com/actions/checkout@v4` or `uses: http://your-git-ser - `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. +- `SHOW_FOOTER_POWERED_BY`: **true**: Show the "powered by" text in the footer. - `ENABLE_SITEMAP`: **true**: Generate sitemap. - `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed. diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index 7b102eda8e..0d08a5e51b 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -212,10 +212,9 @@ menu: - `SITEMAP_PAGING_NUM`: **20**: 在单个子SiteMap中显示的项数。 - `GRAPH_MAX_COMMIT_NUM`: **100**: 提交图中显示的最大commit数量。 - `CODE_COMMENT_LINES`: **4**: 在代码评论中能够显示的最大代码行数。 -- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: 在Gitea安装时候设置的默认主题。 +- `DEFAULT_THEME`: **gitea-auto**: 在Gitea安装时候设置的默认主题,自定义的主题可以通过 "{CustomPath}/public/assets/css/theme-*.css" 提供。 - `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。 -- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: 所有可用的主题。允许用户选择个性化的主题, - 而不受DEFAULT_THEME 值的影响。 +- `THEMES`: **_empty_**: 所有可用的主题(由 "{CustomPath}/public/assets/css/theme-*.css" 提供)。允许用户选择个性化的主题, - `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小(默认为8MiB)。 - `REACTIONS`: 用户可以在问题(Issue)、Pull Request(PR)以及评论中选择的所有可选的反应。 这些值可以是表情符号别名(例如::smile:)或Unicode表情符号。 @@ -507,7 +506,7 @@ Gitea 创建以下非唯一队列: - `INSTALL_LOCK`: **false**:控制是否能够访问安装向导页面,设置为 `true` 则禁止访问安装向导页面。 - `SECRET_KEY`: **\<每次安装时随机生成\>**:全局服务器安全密钥。这个密钥非常重要,如果丢失将无法解密加密的数据(例如 2FA)。 - `SECRET_KEY_URI`: **_empty_**:与定义 `SECRET_KEY` 不同,此选项可用于使用存储在文件中的密钥(示例值:`file:/etc/gitea/secret_key`)。它不应该像 `SECRET_KEY` 一样容易丢失。 -- `LOGIN_REMEMBER_DAYS`: **7**:Cookie 保存时间,单位为天。 +- `LOGIN_REMEMBER_DAYS`: **31**:在要求重新登录之前,记住用户的登录状态多长时间(以天为单位)。 - `COOKIE_REMEMBER_NAME`: **gitea\_incredible**:保存自动登录信息的 Cookie 名称。 - `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**:反向代理认证的 HTTP 头部名称,用于提供用户信息。 - `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**:反向代理认证的 HTTP 头部名称,用于提供邮箱信息。 @@ -562,7 +561,7 @@ Gitea 创建以下非唯一队列: ## OpenID (`openid`) -- `ENABLE_OPENID_SIGNIN`: **false**:允许通过OpenID进行身份验证。 +- `ENABLE_OPENID_SIGNIN`: **true**:允许通过OpenID进行身份验证。 - `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**:允许通过OpenID进行注册。 - `WHITELISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于允许访问。 - `BLACKLISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于阻止访问。 @@ -782,7 +781,7 @@ Gitea 创建以下非唯一队列: ## 工单和合并请求的附件 (`attachment`) - `ENABLED`: **true**: 是否允许用户上传附件。 -- `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 +- `ALLOWED_TYPES`: **.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 - `MAX_SIZE`: **2048**: 附件的最大限制(MB)。 - `MAX_FILES`: **5**: 一次最多上传的附件数量。 - `STORAGE_TYPE`: **local**: 附件的存储类型,`local` 表示本地磁盘,`minio` 表示兼容 S3 的对象存储服务,如果未设置将使用默认值 `local` 或其他在 `[storage.xxx]` 中定义的名称。 @@ -1128,15 +1127,6 @@ ALLOW_DATA_URI_IMAGES = true - `DEFAULT_UI_LOCATION`:在 UI 上的默认时间位置,以便我们可以在 UI 上显示正确的用户时间。例如:Asia/Shanghai -## 任务 (`task`) - -任务队列配置已移动到 `queue.task`。然而,以下配置值仍保留以确保向后兼容: - -- `QUEUE_TYPE`:**channel**:任务队列类型,可以是 `channel` 或 `redis`。 -- `QUEUE_LENGTH`:**1000**:任务队列长度,仅在 `QUEUE_TYPE` 为 `channel` 时可用。 -- `QUEUE_CONN_STR`:**redis://127.0.0.1:6379/0**:任务队列连接字符串,仅在 `QUEUE_TYPE` 为 `redis` 时可用。 - 如果 redis 需要密码,使用 `redis://123@127.0.0.1:6379/0` 或 `redis+cluster://123@127.0.0.1:6379/0`。 - ## 迁移 (`migrations`) - `MAX_ATTEMPTS`:**3**:每次 http/https 请求的最大尝试次数(用于迁移)。 @@ -1353,5 +1343,6 @@ PROXY_HOSTS = *.github.com - `SHOW_FOOTER_VERSION`: **true**: 在页面底部显示Gitea的版本。 - `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: 在页脚显示模板执行的时间。 +- `SHOW_FOOTER_POWERED_BY`: **true**: 在页脚显示“由...提供动力”的文本。 - `ENABLE_SITEMAP`: **true**: 生成sitemap. - `ENABLE_FEED`: **true**: 是否启用RSS/Atom diff --git a/docs/content/administration/customizing-gitea.en-us.md b/docs/content/administration/customizing-gitea.en-us.md index 7efddb2824..8475f6d131 100644 --- a/docs/content/administration/customizing-gitea.en-us.md +++ b/docs/content/administration/customizing-gitea.en-us.md @@ -381,7 +381,7 @@ To make a custom theme available to all users: 1. Add a CSS file to `$GITEA_CUSTOM/public/assets/css/theme-.css`. The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath". -2. Add `` to the comma-separated list of setting `THEMES` in `app.ini` +2. Add `` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes. Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes). diff --git a/docs/content/administration/mail-templates.en-us.md b/docs/content/administration/mail-templates.en-us.md index 4026b89975..8e4e416e8d 100644 --- a/docs/content/administration/mail-templates.en-us.md +++ b/docs/content/administration/mail-templates.en-us.md @@ -163,7 +163,7 @@ clients don't even support HTML, so they show the text version included in the g If the template fails to render, it will be noticed only at the moment the mail is sent. A default subject is used if the subject template fails, and whatever was rendered successfully -from the the _mail body_ is used, disregarding the rest. +from the _mail body_ is used, disregarding the rest. Please check [Gitea's logs](administration/logging-config.md) for error messages in case of trouble. diff --git a/docs/content/administration/repo-indexer.en-us.md b/docs/content/administration/repo-indexer.en-us.md index 6dec2d63fa..aa82222911 100644 --- a/docs/content/administration/repo-indexer.en-us.md +++ b/docs/content/administration/repo-indexer.en-us.md @@ -17,6 +17,12 @@ menu: # Repository indexer +## Builtin repository code search without indexer + +Users could do repository-level code search without setting up a repository indexer. +The builtin code search is based on the `git grep` command, which is fast and efficient for small repositories. +Better code search support could be achieved by setting up the repository indexer. + ## Setting up the repository indexer Gitea can search through the files of the repositories by enabling this function in your [`app.ini`](administration/config-cheat-sheet.md): diff --git a/docs/content/contributing/guidelines-frontend.en-us.md b/docs/content/contributing/guidelines-frontend.en-us.md index 2c0aaaed4a..efeaf38bb2 100644 --- a/docs/content/contributing/guidelines-frontend.en-us.md +++ b/docs/content/contributing/guidelines-frontend.en-us.md @@ -47,7 +47,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. Prefer using Tailwind CSS which is available via `tw-` prefix, e.g. `tw-relative`. Gitea's helper CSS classes use `gt-` prefix (`gt-df`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). +12. Prefer using Tailwind CSS which is available via `tw-` prefix, e.g. `tw-relative`. Gitea's helper CSS classes use `gt-` prefix (`gt-word-break`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). 13. Avoid inline scripts & styles as much as possible, it's recommended to put JS code into JS files and use CSS classes. If inline scripts & styles are unavoidable, explain the reason why it can't be avoided. ### Accessibility / ARIA @@ -118,7 +118,7 @@ However, there are still some special cases, so the current guideline is: ### Show/Hide Elements * Vue components are recommended to use `v-if` and `v-show` to show/hide elements. -* Go template code should use Gitea's `.gt-hidden` and `showElem()/hideElem()/toggleElem()`, see more details in `.gt-hidden`'s comment. +* Go template code should use `.tw-hidden` and `showElem()/hideElem()/toggleElem()`, see more details in `.tw-hidden`'s comment. ### Styles and Attributes in Go HTML Template diff --git a/docs/content/contributing/guidelines-frontend.zh-cn.md b/docs/content/contributing/guidelines-frontend.zh-cn.md index ace0d97f49..394097b259 100644 --- a/docs/content/contributing/guidelines-frontend.zh-cn.md +++ b/docs/content/contributing/guidelines-frontend.zh-cn.md @@ -47,13 +47,13 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。 9. 避免在 CSS 中使用不必要的`!important`,如果无法避免,添加注释解释为什么需要它。 10. 避免在一个事件监听器中混合不同的事件,优先为每个事件使用独立的事件监听器。 11. 推荐使用自定义事件名称前缀`ce-`。 -12. 建议使用 Tailwind CSS,它可以通过 `tw-` 前缀获得,例如 `tw-relative`. Gitea 自身的助手类 CSS 使用 `gt-` 前缀(`gt-df`),Gitea 自身的私有框架级 CSS 类使用 `g-` 前缀(`g-modal-confirm`)。 +12. 建议使用 Tailwind CSS,它可以通过 `tw-` 前缀获得,例如 `tw-relative`. Gitea 自身的助手类 CSS 使用 `gt-` 前缀(`gt-word-break`),Gitea 自身的私有框架级 CSS 类使用 `g-` 前缀(`g-modal-confirm`)。 13. 尽量避免内联脚本和样式,建议将JS代码放入JS文件中并使用CSS类。如果内联脚本和样式不可避免,请解释无法避免的原因。 ### 可访问性 / ARIA 在历史上,Gitea大量使用了可访问性不友好的框架 Fomantic UI。 -Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`aria.md`), +Gitea 使用一些补丁使 Fomantic UI 更具可访问性(参见 `aria.md`), 但仍然存在许多问题需要大量的工作和时间来修复。 ### 框架使用 @@ -117,7 +117,7 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari ### 显示/隐藏元素 * 推荐在Vue组件中使用`v-if`和`v-show`来显示/隐藏元素。 -* Go 模板代码应使用 Gitea 的 `.gt-hidden` 和 `showElem()/hideElem()/toggleElem()` 来显示/隐藏元素,请参阅`.gt-hidden`的注释以获取更多详细信息。 +* Go 模板代码应使用 `.tw-hidden` 和 `showElem()/hideElem()/toggleElem()` 来显示/隐藏元素,请参阅`.tw-hidden`的注释以获取更多详细信息。 ### Go HTML 模板中的样式和属性 diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md index df8a9047d6..004e803827 100644 --- a/docs/content/development/hacking-on-gitea.en-us.md +++ b/docs/content/development/hacking-on-gitea.en-us.md @@ -214,7 +214,7 @@ REPO_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200 ### Building and adding SVGs -SVG icons are built using the `make svg` target which compiles the icon sources defined in `build/generate-svg.js` into the output directory `public/assets/img/svg`. Custom icons can be added in the `web_src/svg` directory. +SVG icons are built using the `make svg` target which compiles the icon sources into the output directory `public/assets/img/svg`. Custom icons can be added in the `web_src/svg` directory. ### Building the Logo @@ -333,14 +333,9 @@ Documentation for the website is found in `docs/`. If you change this you can test your changes to ensure that they pass continuous integration using: ```bash -# from the docs directory within Gitea -make trans-copy clean build +make lint-md ``` -You will require a copy of [Hugo](https://gohugo.io/) to run this task. Please -note: this may generate a number of untracked Git objects, which will need to -be cleaned up. - ## Visual Studio Code A `launch.json` and `tasks.json` are provided within `contrib/ide/vscode` for diff --git a/docs/content/development/hacking-on-gitea.zh-cn.md b/docs/content/development/hacking-on-gitea.zh-cn.md index 2dba3c92b6..7dfea30538 100644 --- a/docs/content/development/hacking-on-gitea.zh-cn.md +++ b/docs/content/development/hacking-on-gitea.zh-cn.md @@ -201,7 +201,7 @@ REPO_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200 ### 构建和添加 SVGs -SVG 图标是使用 `make svg` 目标构建的,该目标将 `build/generate-svg.js` 中定义的图标源编译到输出目录 `public/img/svg` 中。可以在 `web_src/svg` 目录中添加自定义图标。 +SVG 图标是使用 `make svg` 命令构建的,该命令将图标资源编译到输出目录 `public/assets/img/svg` 中。可以在 `web_src/svg` 目录中添加自定义图标。 ### 构建 Logo @@ -307,13 +307,9 @@ TAGS="bindata sqlite sqlite_unlock_notify" make build test-sqlite 该网站的文档位于 `docs/` 中。如果你改变了文档内容,你可以使用以下测试方法进行持续集成: ```bash -# 来自 Gitea 中的 docs 目录 -make trans-copy clean build +make lint-md ``` -运行此任务依赖于 [Hugo](https://gohugo.io/)。请注意:这可能会生成一些未跟踪的 Git 对象, -需要被清理干净。 - ## Visual Studio Code `contrib/ide/vscode` 中为 Visual Studio Code 提供了 `launch.json` 和 `tasks.json`。查看 diff --git a/docs/content/help/faq.en-us.md b/docs/content/help/faq.en-us.md index b3b0980125..ba39ec83b0 100644 --- a/docs/content/help/faq.en-us.md +++ b/docs/content/help/faq.en-us.md @@ -178,17 +178,6 @@ At some point, a customer or third party needs access to a specific repo and onl Use [Fail2Ban](administration/fail2ban-setup.md) to monitor and stop automated login attempts or other malicious behavior based on log patterns -## How to add/use custom themes - -Gitea supports three official themes right now, `gitea-light`, `gitea-dark`, and `gitea-auto` (automatically switches between the previous two depending on operating system settings). -To add your own theme, currently the only way is to provide a complete theme (not just color overrides) - -As an example, let's say our theme is `arc-blue` (this is a real theme, and can be found [in this issue](https://github.com/go-gitea/gitea/issues/6011)) - -Name the `.css` file `theme-arc-blue.css` and add it to your custom folder in `custom/public/assets/css` - -Allow users to use it by adding `arc-blue` to the list of `THEMES` in your `app.ini` - ## SSHD vs built-in SSH SSHD is the built-in SSH server on most Unix systems. diff --git a/docs/content/help/faq.zh-cn.md b/docs/content/help/faq.zh-cn.md index 25230df70b..ef8a149ae2 100644 --- a/docs/content/help/faq.zh-cn.md +++ b/docs/content/help/faq.zh-cn.md @@ -182,17 +182,6 @@ Gitea不提供内置的Pages服务器。您需要一个专用的域名来提供 使用 [Fail2Ban](administration/fail2ban-setup.md) 监视并阻止基于日志模式的自动登录尝试或其他恶意行为。 -## 如何添加/使用自定义主题 - -Gitea 目前支持三个官方主题,分别是 `gitea-light`、`gitea-dark` 和 `gitea-auto`(根据操作系统设置自动切换前两个主题)。 -要添加自己的主题,目前唯一的方法是提供一个完整的主题(不仅仅是颜色覆盖)。 - -假设我们的主题是 `arc-blue`(这是一个真实的主题,可以在[此问题](https://github.com/go-gitea/gitea/issues/6011)中找到) - -将`.css`文件命名为`theme-arc-blue.css`并将其添加到`custom/public/assets/css`文件夹中 - -通过将`arc-blue`添加到`app.ini`中的`THEMES`列表中,允许用户使用该主题 - ## SSHD vs 内建SSH SSHD是大多数Unix系统上内建的SSH服务器。 diff --git a/docs/content/installation/comparison.en-us.md b/docs/content/installation/comparison.en-us.md index 1ba4f7ecc2..3fb6561f31 100644 --- a/docs/content/installation/comparison.en-us.md +++ b/docs/content/installation/comparison.en-us.md @@ -87,6 +87,9 @@ _Symbols used in table:_ | Git Blame | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Visual comparison of image changes | ✓ | ✘ | ✓ | ? | ? | ? | ✘ | ✘ | +- Gitea has builtin repository-level code search +- Better code search support could be achieved by [using a repository indexer](administration/repo-indexer.md) + ## Issue Tracker | Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | diff --git a/docs/content/installation/with-docker.en-us.md b/docs/content/installation/with-docker.en-us.md index e67f5bccb2..a16d4a8d60 100644 --- a/docs/content/installation/with-docker.en-us.md +++ b/docs/content/installation/with-docker.en-us.md @@ -304,7 +304,8 @@ services: - GITEA__mailer__ENABLED=true - GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set} - GITEA__mailer__PROTOCOL=smtps - - GITEA__mailer__HOST=${GITEA__mailer__HOST:?GITEA__mailer__HOST not set} + - GITEA__mailer__SMTP_ADDR=${GITEA__mailer__SMTP_ADDR:?GITEA__mailer__SMTP_ADDR not set} + - GITEA__mailer__SMTP_PORT=${GITEA__mailer__SMTP_PORT:?GITEA__mailer__SMTP_PORT not set} - GITEA__mailer__USER=${GITEA__mailer__USER:-apikey} - GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}""" ``` @@ -545,7 +546,7 @@ In this option, the idea is that the host SSH uses an `AuthorizedKeysCommand` in ```bash cat <<"EOF" | sudo tee /home/git/docker-shell #!/bin/sh - /usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@" + /usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@" EOF sudo chmod +x /home/git/docker-shell sudo usermod -s /home/git/docker-shell git @@ -560,7 +561,7 @@ Add the following block to `/etc/ssh/sshd_config`, on the host: ```bash Match User git AuthorizedKeysCommandUser git - AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k + AuthorizedKeysCommand /usr/bin/docker exec -i -u git gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k ``` (From 1.16.0 you will not need to set the `-c /data/gitea/conf/app.ini` option.) diff --git a/docs/content/usage/actions/act-runner.en-us.md b/docs/content/usage/actions/act-runner.en-us.md index b2806bf5dd..942d126919 100644 --- a/docs/content/usage/actions/act-runner.en-us.md +++ b/docs/content/usage/actions/act-runner.en-us.md @@ -303,34 +303,3 @@ sudo systemctl enable act_runner --now ``` If using Docker, the `act_runner` user should also be added to the `docker` group before starting the service. Keep in mind that this effectively gives `act_runner` root access to the system [[1]](https://docs.docker.com/engine/security/#docker-daemon-attack-surface). - -## Configuration variable - -You can create configuration variables on the user, organization and repository level. -The level of the variable depends on where you created it. - -### Naming conventions - -The following rules apply to variable names: - -- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed. - -- Variable names must not start with the `GITHUB_` and `GITEA_` prefix. - -- Variable names must not start with a number. - -- Variable names are case-insensitive. - -- Variable names must be unique at the level they are created at. - -- Variable names must not be `CI`. - -### Using variable - -After creating configuration variables, they will be automatically filled in the `vars` context. -They can be accessed through expressions like `{{ vars.VARIABLE_NAME }}` in the workflow. - -### Precedence - -If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence: -A repository variable will always be chosen over an organization/user variable. diff --git a/docs/content/usage/actions/act-runner.zh-cn.md b/docs/content/usage/actions/act-runner.zh-cn.md index 274b0f0692..e5ebff976d 100644 --- a/docs/content/usage/actions/act-runner.zh-cn.md +++ b/docs/content/usage/actions/act-runner.zh-cn.md @@ -258,32 +258,3 @@ Runner的标签用于确定Runner可以运行哪些Job以及如何运行它们 Runner将从Gitea实例获取Job并自动运行它们。 由于Act Runner仍处于开发中,建议定期检查最新版本并进行升级。 - -## 变量 - -您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。 - -### 命名规则 - -以下规则适用于变量名: - -- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。 - -- 变量名称不能以 `GITHUB_` 和 `GITEA_` 前缀开头。 - -- 变量名称不能以数字开头。 - -- 变量名称不区分大小写。 - -- 变量名称在创建它们的级别上必须是唯一的。 - -- 变量名称不能为 “CI”。 - -### 使用 - -创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `{{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。 - -### 优先级 - -如果同名变量存在于多个级别,则级别最低的变量优先。 -仓库级别的变量总是比组织或者用户级别的变量优先被选中。 diff --git a/docs/content/usage/actions/design.en-us.md b/docs/content/usage/actions/design.en-us.md index 29fa433e59..0d72c19dce 100644 --- a/docs/content/usage/actions/design.en-us.md +++ b/docs/content/usage/actions/design.en-us.md @@ -104,7 +104,7 @@ However, if a job container tries to fetch code from localhost, it will fail bec ### Connection 3, act runner to internet When you use some actions like `actions/checkout@v4`, the act runner downloads the scripts, not the job containers. -By default, it downloads from [gitea.com](http://gitea.com/), so it requires access to the internet. +By default, it downloads from [github.com](http://github.com/), so it requires access to the internet. If you configure the `DEFAULT_ACTIONS_URL` to `self`, then it will download from your Gitea instance by default. Then it will not connect to internet when downloading the action itself. It also downloads some docker images from Docker Hub by default, which also requires internet access. However, internet access is not strictly necessary. diff --git a/docs/content/usage/actions/design.zh-cn.md b/docs/content/usage/actions/design.zh-cn.md index 8add1cf7c5..f48576477f 100644 --- a/docs/content/usage/actions/design.zh-cn.md +++ b/docs/content/usage/actions/design.zh-cn.md @@ -105,7 +105,8 @@ act runner 必须能够连接到Gitea以接收任务并发送执行结果回来 ### 连接 3,act runner到互联网 当您使用诸如 `actions/checkout@v4` 的一些Actions时,act runner下载的是脚本,而不是Job容器。 -默认情况下,它从[gitea.com](http://gitea.com/)下载,因此需要访问互联网。 +默认情况下,它从[github.com](http://github.com/)下载,因此需要访问互联网。如果您设置的是 self, +那么默认将从您的当前Gitea实例下载,那么此步骤不需要连接到互联网。 它还默认从Docker Hub下载一些Docker镜像,这也需要互联网访问。 然而,互联网访问并不是绝对必需的。 diff --git a/docs/content/usage/actions/variables.en-us.md b/docs/content/usage/actions/variables.en-us.md new file mode 100644 index 0000000000..dee2e74234 --- /dev/null +++ b/docs/content/usage/actions/variables.en-us.md @@ -0,0 +1,41 @@ +--- +date: "2024-04-10T22:21:00+08:00" +title: "Variables" +slug: "actions-variables" +sidebar_position: 25 +draft: false +toc: false +menu: + sidebar: + parent: "actions" + name: "Variables" + sidebar_position: 25 + identifier: "actions-variables" +--- + +## Variables + +You can create configuration variables on the user, organization and repository level. +The level of the variable depends on where you created it. When creating a variable, the +key will be converted to uppercase. You need use uppercase on the yaml file. + +### Naming conventions + +The following rules apply to variable names: + +- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed. +- Variable names must not start with the `GITHUB_` and `GITEA_` prefix. +- Variable names must not start with a number. +- Variable names are case-insensitive. +- Variable names must be unique at the level they are created at. +- Variable names must not be `CI`. + +### Using variable + +After creating configuration variables, they will be automatically filled in the `vars` context. +They can be accessed through expressions like `${{ vars.VARIABLE_NAME }}` in the workflow. + +### Precedence + +If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence: +A repository variable will always be chosen over an organization/user variable. diff --git a/docs/content/usage/actions/variables.zh-cn.md b/docs/content/usage/actions/variables.zh-cn.md new file mode 100644 index 0000000000..77643408a1 --- /dev/null +++ b/docs/content/usage/actions/variables.zh-cn.md @@ -0,0 +1,39 @@ +--- +date: "2024-04-10T22:21:00+08:00" +title: "变量" +slug: "actions-variables" +sidebar_position: 25 +draft: false +toc: false +menu: + sidebar: + parent: "actions" + name: "变量" + sidebar_position: 25 + identifier: "actions-variables" +--- + +## 变量 + +您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。当创建变量时,变量的名称会被 +转换为大写,在yaml文件中引用时需要使用大写。 + +### 命名规则 + +以下规则适用于变量名: + +- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。 +- 变量名称不能以 `GITHUB_` 和 `GITEA_` 前缀开头。 +- 变量名称不能以数字开头。 +- 变量名称不区分大小写。 +- 变量名称在创建它们的级别上必须是唯一的。 +- 变量名称不能为 `CI`。 + +### 使用 + +创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `${{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。 + +### 优先级 + +如果同名变量存在于多个级别,则级别最低的变量优先。 +仓库级别的变量总是比组织或者用户级别的变量优先被选中。 diff --git a/docs/scripts/trans-copy.sh b/docs/scripts/trans-copy.sh deleted file mode 100755 index 7374ab9e73..0000000000 --- a/docs/scripts/trans-copy.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -set -e - -# -# This script is used to copy the en-US content to our available locales as a -# fallback to always show all pages when displaying a specific locale that is -# missing some documents to be translated. -# -# Just execute the script without any argument and you will get the missing -# files copied into the content folder. We are calling this script within the CI -# server simply by `make trans-copy`. -# - -declare -a LOCALES=( - "fr-fr" - "nl-nl" - "pt-br" - "zh-cn" - "zh-tw" -) - -ROOT=$(realpath $(dirname $0)/..) - -for SOURCE in $(find ${ROOT}/content -type f -iname *.en-us.md); do - for LOCALE in "${LOCALES[@]}"; do - DEST="${SOURCE%.en-us.md}.${LOCALE}.md" - - if [[ ! -f ${DEST} ]]; then - cp ${SOURCE} ${DEST} - sed -i.bak "s/en\-us/${LOCALE}/g" ${DEST} - rm ${DEST}.bak - fi - done -done diff --git a/go.mod b/go.mod index 9b70a191ce..1e88de3011 100644 --- a/go.mod +++ b/go.mod @@ -1,62 +1,60 @@ module code.gitea.io/gitea -go 1.21 +go 1.22 require ( - code.gitea.io/actions-proto-go v0.3.1 + code.gitea.io/actions-proto-go v0.4.0 code.gitea.io/gitea-vet v0.2.3 code.gitea.io/sdk/gitea v0.17.1 codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 - gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 + connectrpc.com/connect v1.15.0 + gitea.com/go-chi/binding v0.0.0-20240316035258-17450c5f3028 gitea.com/go-chi/cache v0.2.0 - gitea.com/go-chi/captcha v0.0.0-20230415143339-2c0754df4384 - gitea.com/go-chi/session v0.0.0-20230613035928-39541325faa3 + gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 + gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96 gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 - github.com/NYTimes/gziphandler v1.1.1 - github.com/PuerkitoBio/goquery v1.8.1 - github.com/alecthomas/chroma/v2 v2.12.0 + github.com/PuerkitoBio/goquery v1.9.1 + github.com/alecthomas/chroma/v2 v2.13.0 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/blevesearch/bleve/v2 v2.3.10 - github.com/bufbuild/connect-go v1.10.0 - github.com/buildkite/terminal-to-html/v3 v3.10.1 + github.com/buildkite/terminal-to-html/v3 v3.11.0 github.com/caddyserver/certmagic v0.20.0 github.com/chi-middleware/proxy v1.1.1 - github.com/denisenkom/go-mssqldb v0.12.3 github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 github.com/djherbis/buffer v1.2.0 github.com/djherbis/nio/v3 v3.0.1 github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 github.com/dustin/go-humanize v1.0.1 - github.com/editorconfig/editorconfig-core-go/v2 v2.6.0 + github.com/editorconfig/editorconfig-core-go/v2 v2.6.1 github.com/emersion/go-imap v1.2.1 github.com/emirpasic/gods v1.18.1 github.com/ethantkoenig/rupture v1.0.1 - github.com/felixge/fgprof v0.9.3 + github.com/felixge/fgprof v0.9.4 github.com/fsnotify/fsnotify v1.7.0 github.com/gliderlabs/ssh v0.3.6 - github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 + github.com/go-ap/activitypub v0.0.0-20240316125321-b61fd6a83225 github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 - github.com/go-chi/chi/v5 v5.0.11 + github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/cors v1.2.1 github.com/go-co-op/gocron v1.37.0 - github.com/go-enry/go-enry/v2 v2.8.6 + github.com/go-enry/go-enry/v2 v2.8.7 github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.11.0 github.com/go-ldap/ldap/v3 v3.4.6 - github.com/go-sql-driver/mysql v1.7.1 + github.com/go-sql-driver/mysql v1.8.0 github.com/go-swagger/go-swagger v0.30.5 github.com/go-testfixtures/testfixtures/v3 v3.10.0 - github.com/go-webauthn/webauthn v0.10.0 + github.com/go-webauthn/webauthn v0.10.2 github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 - github.com/golang-jwt/jwt/v5 v5.2.0 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/go-github/v57 v57.0.0 - github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 + github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.1.2 github.com/gorilla/sessions v1.2.2 @@ -64,55 +62,56 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/huandu/xstrings v1.4.0 github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 - github.com/jhillyerd/enmime v1.1.0 + github.com/jhillyerd/enmime v1.2.0 github.com/json-iterator/go v1.1.12 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 - github.com/klauspost/compress v1.17.4 - github.com/klauspost/cpuid/v2 v2.2.6 + github.com/klauspost/compress v1.17.8 + github.com/klauspost/cpuid/v2 v2.2.7 github.com/lib/pq v1.10.9 - github.com/markbates/goth v1.78.0 + github.com/markbates/goth v1.79.0 github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-sqlite3 v1.14.22 - github.com/meilisearch/meilisearch-go v0.26.1 + github.com/meilisearch/meilisearch-go v0.26.2 github.com/mholt/archiver/v3 v3.5.1 github.com/microcosm-cc/bluemonday v1.0.26 - github.com/minio/minio-go/v7 v7.0.66 + github.com/microsoft/go-mssqldb v1.7.0 + github.com/minio/minio-go/v7 v7.0.69 github.com/msteinert/pam v1.2.0 github.com/nektos/act v0.2.52 github.com/niklasfasching/go-org v1.7.0 github.com/olivere/elastic/v7 v7.0.32 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc6 + github.com/opencontainers/image-spec v1.1.0 github.com/pkg/errors v0.9.1 github.com/pquerna/otp v1.4.0 - github.com/prometheus/client_golang v1.18.0 + github.com/prometheus/client_golang v1.19.0 github.com/quasoft/websspi v1.1.2 - github.com/redis/go-redis/v9 v9.4.0 + github.com/redis/go-redis/v9 v9.5.1 github.com/robfig/cron/v3 v3.0.1 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 - github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd + github.com/sassoftware/go-rpmutils v0.3.0 github.com/sergi/go-diff v1.3.1 github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.0 github.com/tstranex/u2f v1.0.0 github.com/ulikunitz/xz v0.5.11 github.com/urfave/cli/v2 v2.27.1 - github.com/xanzy/go-gitlab v0.96.0 + github.com/xanzy/go-gitlab v0.100.0 github.com/xeipuuv/gojsonschema v1.2.0 github.com/yohcop/openid-go v1.0.1 - github.com/yuin/goldmark v1.6.0 + github.com/yuin/goldmark v1.7.0 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-meta v1.1.0 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.22.0 golang.org/x/image v0.15.0 - golang.org/x/net v0.20.0 - golang.org/x/oauth2 v0.16.0 - golang.org/x/sys v0.16.0 + golang.org/x/net v0.24.0 + golang.org/x/oauth2 v0.18.0 + golang.org/x/sys v0.19.0 golang.org/x/text v0.14.0 - golang.org/x/tools v0.17.0 - google.golang.org/grpc v1.60.1 + golang.org/x/tools v0.19.0 + google.golang.org/grpc v1.62.1 google.golang.org/protobuf v1.33.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/ini.v1 v1.67.0 @@ -120,23 +119,24 @@ require ( mvdan.cc/xurls/v2 v2.5.0 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 xorm.io/builder v0.3.13 - xorm.io/xorm v1.3.7 + xorm.io/xorm v1.3.8 ) require ( - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute v1.25.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect dario.cat/mergo v1.0.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect - github.com/ClickHouse/ch-go v0.61.1 // indirect - github.com/ClickHouse/clickhouse-go/v2 v2.18.0 // indirect + github.com/ClickHouse/ch-go v0.61.5 // indirect + github.com/ClickHouse/clickhouse-go/v2 v2.22.0 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect - github.com/RoaringBitmap/roaring v1.7.0 // indirect + github.com/RoaringBitmap/roaring v1.9.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect @@ -144,12 +144,12 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect - github.com/blevesearch/bleve_index_api v1.1.5 // indirect - github.com/blevesearch/geo v0.1.19 // indirect + github.com/blevesearch/bleve_index_api v1.1.6 // indirect + github.com/blevesearch/geo v0.1.20 // indirect github.com/blevesearch/go-porterstemmer v1.0.3 // indirect github.com/blevesearch/gtreap v0.1.1 // indirect github.com/blevesearch/mmap-go v1.0.4 // indirect - github.com/blevesearch/scorch_segment_api/v2 v2.2.6 // indirect + github.com/blevesearch/scorch_segment_api/v2 v2.2.8 // indirect github.com/blevesearch/segment v0.9.1 // indirect github.com/blevesearch/snowballstem v0.9.0 // indirect github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect @@ -165,43 +165,43 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/couchbase/go-couchbase v0.1.1 // indirect - github.com/couchbase/gomemcached v0.3.0 // indirect + github.com/couchbase/gomemcached v0.3.1 // indirect github.com/couchbase/goutils v0.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/dlclark/regexp2 v1.10.0 // indirect + github.com/dlclark/regexp2 v1.11.0 // indirect github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fxamacker/cbor/v2 v2.5.0 // indirect - github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect + github.com/fxamacker/cbor/v2 v2.6.0 // indirect + github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-enry/go-oniguruma v1.2.1 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.7.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-openapi/analysis v0.22.2 // indirect - github.com/go-openapi/errors v0.21.0 // indirect - github.com/go-openapi/inflect v0.19.0 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/loads v0.21.5 // indirect - github.com/go-openapi/runtime v0.26.2 // indirect - github.com/go-openapi/spec v0.20.14 // indirect - github.com/go-openapi/strfmt v0.22.0 // indirect - github.com/go-openapi/swag v0.22.7 // indirect - github.com/go-openapi/validate v0.22.6 // indirect - github.com/go-webauthn/x v0.1.6 // indirect + github.com/go-openapi/analysis v0.23.0 // indirect + github.com/go-openapi/errors v0.22.0 // indirect + github.com/go-openapi/inflect v0.21.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/loads v0.22.0 // indirect + github.com/go-openapi/runtime v0.28.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-webauthn/x v0.1.9 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect @@ -246,11 +246,11 @@ require ( github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.46.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/rhysd/actionlint v1.6.26 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.50.0 // indirect + github.com/prometheus/procfs v0.13.0 // indirect + github.com/rhysd/actionlint v1.6.27 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -260,7 +260,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skeema/knownhosts v1.2.1 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -271,28 +271,28 @@ require ( github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect github.com/zeebo/blake3 v0.2.3 // indirect - go.etcd.io/bbolt v1.3.8 // indirect - go.mongodb.org/mongo-driver v1.13.1 // indirect - go.opentelemetry.io/otel v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.etcd.io/bbolt v1.3.9 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/mod v0.14.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect + golang.org/x/mod v0.16.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index a44809dde5..cbf397b95c 100644 --- a/go.sum +++ b/go.sum @@ -1,64 +1,33 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.67.0/go.mod h1:YNan/mUhNZFrYUor0vqrsQ0Ffl7Xtm/ACOy/vsTS858= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -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= -code.gitea.io/actions-proto-go v0.3.1 h1:PMyiQtBKb8dNnpEO2R5rcZdXSis+UQZVo/SciMtR1aU= -code.gitea.io/actions-proto-go v0.3.1/go.mod h1:00ys5QDo1iHN1tHNvvddAcy2W/g+425hQya1cCSvq9A= +code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU= +code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas= code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI= code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY= codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM= +connectrpc.com/connect v1.15.0 h1:lFdeCbZrVVDydAqwr4xGV2y+ULn+0Z73s5JBj2LikWo= +connectrpc.com/connect v1.15.0/go.mod h1:bQmjpDY8xItMnttnurVgOkHUBMRT9cpsNi2O4AjKhmA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= 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.259.1 h1:8GG1o/xtUHl3qjn5f0h/2FXrT5ubBn05TJOM5ry+FBw= gitea.com/gitea/act v0.259.1/go.mod h1:UxZWRYqQG2Yj4+4OqfGWW5a3HELwejyWFQyU7F1jUD8= -gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo= -gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc= -gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0= +gitea.com/go-chi/binding v0.0.0-20240316035258-17450c5f3028 h1:6/QAx4+s0dyRwdaTFPTnhGppuiuu0OqxIH9szyTpvKw= +gitea.com/go-chi/binding v0.0.0-20240316035258-17450c5f3028/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw= gitea.com/go-chi/cache v0.2.0 h1:E0npuTfDW6CT1yD8NMDVc1SK6IeRjfmRL2zlEsCEd7w= gitea.com/go-chi/cache v0.2.0/go.mod h1:iQlVK2aKTZ/rE9UcHyz9pQWGvdP9i1eI2spOpzgCrtE= -gitea.com/go-chi/captcha v0.0.0-20230415143339-2c0754df4384 h1:klh0LjhH7l4CuJkxlCM//o3rWLvWqxUpFxEtoYg5TNY= -gitea.com/go-chi/captcha v0.0.0-20230415143339-2c0754df4384/go.mod h1:hQ9SYHKdOX968wJglb/NMQ+UqpOKwW4L+EYdvkWjHSo= -gitea.com/go-chi/session v0.0.0-20230613035928-39541325faa3 h1:4FuO+MahrkDjdjVIS8ExmY9FEHTZS8TPheEm4uU5xLI= -gitea.com/go-chi/session v0.0.0-20230613035928-39541325faa3/go.mod h1:fc/pjt5EqNKgqQXYzcas1Z5L5whkZHyOvTA7OzWVJck= +gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 h1:p2ki+WK0cIeNQuqjR98IP2KZQKRzJJiV7aTeMAFwaWo= +gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098/go.mod h1:LjzIOHlRemuUyO7WR12fmm18VZIlCAaOt9L3yKw40pk= +gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96 h1:IFDiMBObsP6CZIRaDLd54SR6zPYAffPXiXck5Xslu0Q= +gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96/go.mod h1:0iEpFKnwO5dG0aF98O4eq6FMsAiXkNBaDIlUOlq4BtM= gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:+wWBi6Qfruqu7xJgjOIrKVQGiLUZdpKYCZewJ4clqhw= gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:VyMQP6ue6MKHM8UsOXfNfuMKD0oSAWZdXVcpHIN2yaY= gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o= @@ -69,18 +38,25 @@ github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 h1:r3qt8PCHnfjOv9PN3H github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121/go.mod h1:Ock8XgA7pvULhIaHGAk/cDnRfNrF9Jey81nPcc403iU= github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U= github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ClickHouse/ch-go v0.61.1 h1:j5rx3qnvcnYjhnP1IdXE/vdIRQiqgwAzyqOaasA6QCw= -github.com/ClickHouse/ch-go v0.61.1/go.mod h1:myxt/JZgy2BYHFGQqzmaIpbfr5CMbs3YHVULaWQj5YU= -github.com/ClickHouse/clickhouse-go/v2 v2.18.0 h1:O1LicIeg2JS2V29fKRH4+yT3f6jvvcJBm506dpVQ4mQ= -github.com/ClickHouse/clickhouse-go/v2 v2.18.0/go.mod h1:ztQvX6wm7kAbhJslS87EXEhOVNY/TObXwyURnGju5FQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4= +github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg= +github.com/ClickHouse/clickhouse-go/v2 v2.22.0 h1:LAdk0qT125PpSPnYepFQs5X5z1EwpAtIX10SUELPgi0= +github.com/ClickHouse/clickhouse-go/v2 v2.22.0/go.mod h1:tBhdF3f3RdP7sS59+oBAtTyhWpy0024ZxDMhgxra0QE= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74= @@ -94,31 +70,28 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= -github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= +github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= +github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I= -github.com/RoaringBitmap/roaring v1.7.0 h1:OZF303tJCER1Tj3x+aArx/S5X7hrT186ri6JjrGvG68= -github.com/RoaringBitmap/roaring v1.7.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90= -github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= -github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/RoaringBitmap/roaring v1.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE= +github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90= +github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU= +github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw= -github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw= +github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI= +github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk= github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= -github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= -github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= @@ -143,10 +116,10 @@ github.com/blevesearch/bleve/v2 v2.0.5/go.mod h1:ZjWibgnbRX33c+vBRgla9QhPb4QOjD6 github.com/blevesearch/bleve/v2 v2.3.10 h1:z8V0wwGoL4rp7nG/O3qVVLYxUqCbEwskMt4iRJsPLgg= github.com/blevesearch/bleve/v2 v2.3.10/go.mod h1:RJzeoeHC+vNHsoLR54+crS1HmOWpnH87fL70HAUCzIA= github.com/blevesearch/bleve_index_api v1.0.0/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4= -github.com/blevesearch/bleve_index_api v1.1.5 h1:0q05mzu6GT/kebzqKywCpou/eUea9wTKa7kfqX7QX+k= -github.com/blevesearch/bleve_index_api v1.1.5/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= -github.com/blevesearch/geo v0.1.19 h1:hlX1YpBZ+X+xfjS8hEpmM/tdPUFbqBME3mdAWKHo2s0= -github.com/blevesearch/geo v0.1.19/go.mod h1:EPyr3iJCcESYa830PnkFhqzJkOP7/daHT/ocun43WRY= +github.com/blevesearch/bleve_index_api v1.1.6 h1:orkqDFCBuNU2oHW9hN2YEJmet+TE9orml3FCGbl1cKk= +github.com/blevesearch/bleve_index_api v1.1.6/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= +github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM= +github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w= github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= @@ -155,8 +128,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+ github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= github.com/blevesearch/scorch_segment_api/v2 v2.0.1/go.mod h1:lq7yK2jQy1yQjtjTfU931aVqz7pYxEudHaDwOt1tXfU= -github.com/blevesearch/scorch_segment_api/v2 v2.2.6 h1:rewrzgFaCEjjfWovAB9NubMAd4+aCLxD3RaQcPDaoNo= -github.com/blevesearch/scorch_segment_api/v2 v2.2.6/go.mod h1:0rv+k/OIjtYCT/g7Z45pCOVweFyta+0AdXO8keKfZxo= +github.com/blevesearch/scorch_segment_api/v2 v2.2.8 h1:+OLW38LuRKio6N6V0gIk1srwFz79FJ5v2sNqHz2HVAA= +github.com/blevesearch/scorch_segment_api/v2 v2.2.8/go.mod h1:ckbeb7knyOOvAdZinn/ASbB7EA3HoagnJkmEV3J7+sg= github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ= github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= @@ -194,40 +167,34 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= -github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg= -github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8= -github.com/buildkite/terminal-to-html/v3 v3.10.1 h1:znT9eD26LQ59dDJJEpMCwkP4wEptEAPi74hsTBuHdEo= -github.com/buildkite/terminal-to-html/v3 v3.10.1/go.mod h1:qtuRyYs6/Sw3FS9jUyVEaANHgHGqZsGqMknPLyau5cQ= +github.com/buildkite/terminal-to-html/v3 v3.11.0 h1:wMTpKgR61lqmxMz1FKjCaW5mq6DqeEgFZdJ+SU4hP30= +github.com/buildkite/terminal-to-html/v3 v3.11.0/go.mod h1:8JACDet3vmvWLsL4IBobweQYtf19W5J+EKM3LEE1c+4= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI= github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ= github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k= -github.com/couchbase/go-couchbase v0.0.0-20201026062457-7b3be89bbd89/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A= github.com/couchbase/go-couchbase v0.1.1 h1:ClFXELcKj/ojyoTYbsY34QUrrYCBi/1G749sXSCkdhk= github.com/couchbase/go-couchbase v0.1.1/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A= -github.com/couchbase/gomemcached v0.1.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo= -github.com/couchbase/gomemcached v0.3.0 h1:XkMDdP6w7rtvLijDE0/RhcccX+XvAk5cboyBv1YcI0U= -github.com/couchbase/gomemcached v0.3.0/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo= -github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= +github.com/couchbase/gomemcached v0.3.1 h1:jfspNuQIXgWy+5GUPQrsQ6yC5uJCfMmd/JKvK6C26r8= +github.com/couchbase/gomemcached v0.3.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo= github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9BCs= github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE= github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs= @@ -244,8 +211,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw= github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -260,17 +225,16 @@ github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmW github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= -github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/editorconfig/editorconfig-core-go/v2 v2.6.0 h1:5O8paxMLmi/5ONoKXzWNYxoSZU7+ITVbGcPga0IrzfE= -github.com/editorconfig/editorconfig-core-go/v2 v2.6.0/go.mod h1:hdTKe+hwa3mMnMn4JUQziT+yc3pF+6EVmK2LPbLZthE= +github.com/editorconfig/editorconfig-core-go/v2 v2.6.1 h1:iPCqofzMO41WVbcS/B5Ym7AwHQg9cyQ7Ie/R2XU5L3A= +github.com/editorconfig/editorconfig-core-go/v2 v2.6.1/go.mod h1:VY4oyqUnpULFB3SCRpl24GFDIN1PmfiQIvN/G4ScSNg= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= @@ -284,16 +248,12 @@ github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTe github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4= github.com/ethantkoenig/rupture v1.0.1/go.mod h1:Sjqo/nbffZp1pVVXNGhpugIjsWmuS9KiIB4GtpEBur4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= -github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88= +github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -304,30 +264,29 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= +github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gliderlabs/ssh v0.3.6 h1:ZzjlDa05TcFRICb3anf/dSPN3ewz1Zx6CMLPWgkm3b8= github.com/gliderlabs/ssh v0.3.6/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI= -github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI= -github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0= -github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI= +github.com/go-ap/activitypub v0.0.0-20240316125321-b61fd6a83225 h1:OoM81OclgRX7CUch4M7MmsH0NcmLWpFiSn7rhs6Y5ZU= +github.com/go-ap/activitypub v0.0.0-20240316125321-b61fd6a83225/go.mod h1:yRUfFCoZY6C1CWalauqEQ5xYgSckzEBEO/2MBC6BOME= +github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 h1:H9MGShwybHLSln6K8RxHPMHiLcD86Lru+5TVW2TcXHY= +github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI= github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw= github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= -github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= -github.com/go-enry/go-enry/v2 v2.8.6 h1:T6ljs5+qNiUTDqpfK5GUD5EvLNdDbf804u8iC30vw7U= -github.com/go-enry/go-enry/v2 v2.8.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= +github.com/go-enry/go-enry/v2 v2.8.7 h1:vbab0pcf5Yo1cHQLzbWZ+QomUh3EfEU8EiR5n7W0lnQ= +github.com/go-enry/go-enry/v2 v2.8.7/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= @@ -345,38 +304,34 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= -github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= -github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= -github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= -github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= -github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= -github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= -github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= -github.com/go-openapi/runtime v0.26.2 h1:elWyB9MacRzvIVgAZCBJmqTi7hBzU0hlKD4IvfX0Zl0= -github.com/go-openapi/runtime v0.26.2/go.mod h1:O034jyRZ557uJKzngbMDJXkcKJVzXJiymdSfgejrcRw= -github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= -github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= -github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI= -github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= -github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= -github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo= -github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM= +github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= +github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= +github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk= +github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= +github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= +github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= +github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4= +github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U= github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewetCdvEXqgPvbc/Q= github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= @@ -386,14 +341,15 @@ github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-testfixtures/testfixtures/v3 v3.10.0 h1:BrBwN7AuC+74g5qtk9D59TLGOaEa8Bw1WmIsf+SyzWc= github.com/go-testfixtures/testfixtures/v3 v3.10.0/go.mod h1:z8RoleoNtibi6Ar8ziCW7e6PQ+jWiqbUWvuv8AMe4lo= -github.com/go-webauthn/webauthn v0.10.0 h1:yuW2e1tXnRAwAvKrR4q4LQmc6XtCMH639/ypZGhZCwk= -github.com/go-webauthn/webauthn v0.10.0/go.mod h1:l0NiauXhL6usIKqNLCUM3Qir43GK7ORg8ggold0Uv/Y= -github.com/go-webauthn/x v0.1.6 h1:QNAX+AWeqRt9loE8mULeWJCqhVG5D/jvdmJ47fIWCkQ= -github.com/go-webauthn/x v0.1.6/go.mod h1:W8dFVZ79o4f+nY1eOUICy/uq5dhrRl7mxQkYhXTo0FA= +github.com/go-webauthn/webauthn v0.10.2 h1:OG7B+DyuTytrEPFmTX503K77fqs3HDK/0Iv+z8UYbq4= +github.com/go-webauthn/webauthn v0.10.2/go.mod h1:Gd1IDsGAybuvK1NkwUTLbGmeksxuRJjVN2PE/xsPxHs= +github.com/go-webauthn/x v0.1.9 h1:v1oeLmoaa+gPOaZqUdDentu6Rl7HkSSsmOT6gxEQHhE= +github.com/go-webauthn/x v0.1.9/go.mod h1:pJNMlIMP1SU7cN8HNlKJpLEnFHCygLCvaLZ8a1xeoQA= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -401,64 +357,40 @@ github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7w github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0= github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I= github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -471,27 +403,13 @@ github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw= @@ -502,7 +420,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= @@ -510,7 +427,6 @@ github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5 github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= -github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= @@ -521,8 +437,6 @@ github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+ github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -533,8 +447,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= @@ -555,23 +468,20 @@ github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= -github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhillyerd/enmime v1.1.0 h1:ubaIzg68VY7CMCe2YbHe6nkRvU9vujixTkNz3EBvZOw= -github.com/jhillyerd/enmime v1.1.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I= +github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk= +github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -585,17 +495,16 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -609,12 +518,9 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= -github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= -github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE= -github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= -github.com/lestrrat-go/jwx v1.2.21/go.mod h1:9cfxnOH7G1gN75CaJP2hKGcxFEx5sPh1abRIA/ZJVh4= -github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -629,11 +535,10 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE= github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o= -github.com/markbates/goth v1.78.0 h1:7VEIFDycJp9deyVv3YraGBPdD0ZYQW93Y3Aw1eVP3BY= -github.com/markbates/goth v1.78.0/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc= +github.com/markbates/goth v1.79.0 h1:fUYi9R6VubVEK2bpmXvIUp7xRcxA68i8ovfUQx/i5Qc= +github.com/markbates/goth v1.79.0/go.mod h1:RBD+tcFnXul2NnYuODhnIweOcuVPkBohLfEvutPekcU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -645,20 +550,22 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/meilisearch/meilisearch-go v0.26.1 h1:3bmo2uLijX7kvBmiZ9LupVfC95TFcRJDgrRTzbOoE4A= -github.com/meilisearch/meilisearch-go v0.26.1/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= +github.com/meilisearch/meilisearch-go v0.26.2 h1:3gTlmiV1dHHumVUhYdJbvh3camiNiyqQ1hNveVsU2OE= +github.com/meilisearch/meilisearch-go v0.26.2/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/microsoft/go-mssqldb v1.7.0 h1:sgMPW0HA6Ihd37Yx0MzHyKD726C2kY/8KJsQtXHNaAs= +github.com/microsoft/go-mssqldb v1.7.0/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.66 h1:bnTOXOHjOqv/gcMuiVbN9o2ngRItvqE774dG9nq0Dzw= -github.com/minio/minio-go/v7 v7.0.66/go.mod h1:DHAgmyQEGdW3Cif0UooKOyrT3Vxs82zNdV6tkKhRtbs= +github.com/minio/minio-go/v7 v7.0.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0= +github.com/minio/minio-go/v7 v7.0.69/go.mod h1:XAvOPJQ5Xlzk5o3o/ArO2NMbhSGkimC+bpW/ngRKDmQ= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -676,9 +583,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM= github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= @@ -704,20 +609,19 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= -github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU= github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= @@ -731,7 +635,8 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -740,31 +645,29 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= -github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ= +github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ= +github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= +github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw= github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= -github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rhysd/actionlint v1.6.26 h1:zi7jPZf3Ks14gCXYAAL47uBziyFlX7+Xwilqhexct9g= -github.com/rhysd/actionlint v1.6.26/go.mod h1:TIj1DlCgtYLOv5CH9wCK+WJTOr1qAdnFzkGi0IgSCO4= +github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw= +github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -781,8 +684,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd h1:KpbqRPDwcAQTyaP+L+YudTRb3CnJlQ64Hfn1SF/zHBA= -github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI= +github.com/sassoftware/go-rpmutils v0.3.0 h1:tE4TZ8KcOXay5iIP64P291s6Qxd9MQCYhI7DU+f3gFA= +github.com/sassoftware/go-rpmutils v0.3.0/go.mod h1:hM9wdxFsjUFR/tJ6SMsLrJuChcucCa0DsCzE9RMfwMo= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= @@ -800,8 +703,8 @@ github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= @@ -843,8 +746,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= @@ -868,23 +772,21 @@ github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6S github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= -github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= +github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= +github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xanzy/go-gitlab v0.96.0 h1:LGkZ+wSNMRtHIBaYE4Hq3dZVjprwHv3Y1+rhKU3WETs= -github.com/xanzy/go-gitlab v0.96.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= +github.com/xanzy/go-gitlab v0.100.0 h1:jaOtYj5nWI19+9oVVmgy233pax2oYqucwetogYU46ks= +github.com/xanzy/go-gitlab v0.100.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -895,8 +797,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI= -github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5 h1:3seWKGVhGoc66Ht5QlhQsr4xT2caDnFegsnh2NqvENU= github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js= @@ -904,12 +806,11 @@ github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBz github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= -github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA= +github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= @@ -921,39 +822,29 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -963,80 +854,31 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= -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/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw= +golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= -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= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1046,23 +888,13 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1070,43 +902,21 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1114,9 +924,9 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1129,9 +939,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1141,11 +950,9 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1158,153 +965,39 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -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= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200929141702-51c3e5b607fe/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -1322,7 +1015,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/ini.v1 v1.44.2/go.mod h1:M3Cogqpuv0QCi3ExAY5V4uOt4qb/R3xZubo9m8lK5wg= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -1337,16 +1029,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= @@ -1369,12 +1053,9 @@ modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs= strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo= xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= -xorm.io/xorm v1.3.7 h1:mLceAGu0b87r9pD4qXyxGHxifOXIIrAdVcA6k95/osw= -xorm.io/xorm v1.3.7/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw= +xorm.io/xorm v1.3.8 h1:CJmplmWqfSRpLWSPMmqz+so8toBp3m7ehuRehIWedZo= +xorm.io/xorm v1.3.8/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw= diff --git a/models/actions/run.go b/models/actions/run.go index 7b3125949b..d68710f46d 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -74,6 +74,13 @@ func (run *ActionRun) Link() string { return fmt.Sprintf("%s/actions/runs/%d", run.Repo.Link(), run.Index) } +func (run *ActionRun) WorkflowLink() string { + if run.Repo == nil { + return "" + } + return fmt.Sprintf("%s/actions/?workflow=%s", run.Repo.Link(), run.WorkflowID) +} + // RefLink return the url of run's ref func (run *ActionRun) RefLink() string { refName := git.RefName(run.Ref) @@ -98,13 +105,10 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error { return nil } - if run.Repo == nil { - repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) - if err != nil { - return err - } - run.Repo = repo + if err := run.LoadRepo(ctx); err != nil { + return err } + if err := run.Repo.LoadAttributes(ctx); err != nil { return err } @@ -120,6 +124,19 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error { return nil } +func (run *ActionRun) LoadRepo(ctx context.Context) error { + if run == nil || run.Repo != nil { + return nil + } + + repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) + if err != nil { + return err + } + run.Repo = repo + return nil +} + func (run *ActionRun) Duration() time.Duration { return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration } @@ -146,6 +163,10 @@ func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, err return nil, fmt.Errorf("event %s is not a pull request event", run.Event) } +func (run *ActionRun) IsSchedule() bool { + return run.ScheduleID > 0 +} + func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { _, err := db.GetEngine(ctx).ID(repo.ID). SetExpr("num_action_runs", @@ -170,15 +191,16 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err return err } -// CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. -func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { - // Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. +// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event. +// It's useful when a new run is triggered, and all previous runs needn't be continued anymore. +func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { + // Find all runs in the specified repository, reference, and workflow with non-final status runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{ RepoID: repoID, Ref: ref, WorkflowID: workflowID, TriggerEvent: event, - Status: []Status{StatusRunning, StatusWaiting}, + Status: []Status{StatusRunning, StatusWaiting, StatusBlocked}, }) if err != nil { return err diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index 6ea6cb9d3b..6c5d3b3252 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -16,14 +16,9 @@ import ( type ActionJobList []*ActionRunJob func (jobs ActionJobList) GetRunIDs() []int64 { - ids := make(container.Set[int64], len(jobs)) - for _, j := range jobs { - if j.RunID == 0 { - continue - } - ids.Add(j.RunID) - } - return ids.Values() + return container.FilterSlice(jobs, func(j *ActionRunJob) (int64, bool) { + return j.RunID, j.RunID != 0 + }) } func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error { diff --git a/models/actions/run_list.go b/models/actions/run_list.go index 388bfc4f86..4046c7d369 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -19,19 +19,15 @@ type RunList []*ActionRun // GetUserIDs returns a slice of user's id func (runs RunList) GetUserIDs() []int64 { - ids := make(container.Set[int64], len(runs)) - for _, run := range runs { - ids.Add(run.TriggerUserID) - } - return ids.Values() + return container.FilterSlice(runs, func(run *ActionRun) (int64, bool) { + return run.TriggerUserID, true + }) } func (runs RunList) GetRepoIDs() []int64 { - ids := make(container.Set[int64], len(runs)) - for _, run := range runs { - ids.Add(run.RepoID) - } - return ids.Values() + return container.FilterSlice(runs, func(run *ActionRun) (int64, bool) { + return run.RepoID, true + }) } func (runs RunList) LoadTriggerUser(ctx context.Context) error { diff --git a/models/actions/runner.go b/models/actions/runner.go index 67f003387b..9192925d5a 100644 --- a/models/actions/runner.go +++ b/models/actions/runner.go @@ -270,7 +270,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { // Only affect action runners were a owner ID is set, as actions runners // could also be created on a repository. return db.GetEngine(ctx).Table("action_runner"). - Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). + Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id"). Where("`action_runner`.owner_id != ?", 0). And(builder.IsNull{"`user`.id"}). Count(new(ActionRunner)) @@ -279,7 +279,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { subQuery := builder.Select("`action_runner`.id"). From("`action_runner`"). - Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). + Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id"). Where(builder.Neq{"`action_runner`.owner_id": 0}). And(builder.IsNull{"`user`.id"}) b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`") @@ -289,3 +289,25 @@ func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { } return res.RowsAffected() } + +func CountRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) { + return db.GetEngine(ctx).Table("action_runner"). + Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id"). + Where("`action_runner`.repo_id != ?", 0). + And(builder.IsNull{"`repository`.id"}). + Count(new(ActionRunner)) +} + +func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) { + subQuery := builder.Select("`action_runner`.id"). + From("`action_runner`"). + Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id"). + Where(builder.Neq{"`action_runner`.repo_id": 0}). + And(builder.IsNull{"`repository`.id"}) + b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`") + res, err := db.GetEngine(ctx).Exec(b) + if err != nil { + return 0, err + } + return res.RowsAffected() +} diff --git a/models/actions/runner_list.go b/models/actions/runner_list.go index 87f0886b47..3ef8ebb254 100644 --- a/models/actions/runner_list.go +++ b/models/actions/runner_list.go @@ -16,14 +16,9 @@ type RunnerList []*ActionRunner // GetUserIDs returns a slice of user's id func (runners RunnerList) GetUserIDs() []int64 { - ids := make(container.Set[int64], len(runners)) - for _, runner := range runners { - if runner.OwnerID == 0 { - continue - } - ids.Add(runner.OwnerID) - } - return ids.Values() + return container.FilterSlice(runners, func(runner *ActionRunner) (int64, bool) { + return runner.OwnerID, runner.OwnerID != 0 + }) } func (runners RunnerList) LoadOwners(ctx context.Context) error { @@ -41,16 +36,9 @@ func (runners RunnerList) LoadOwners(ctx context.Context) error { } func (runners RunnerList) getRepoIDs() []int64 { - repoIDs := make(container.Set[int64], len(runners)) - for _, runner := range runners { - if runner.RepoID == 0 { - continue - } - if _, ok := repoIDs[runner.RepoID]; !ok { - repoIDs[runner.RepoID] = struct{}{} - } - } - return repoIDs.Values() + return container.FilterSlice(runners, func(runner *ActionRunner) (int64, bool) { + return runner.RepoID, runner.RepoID > 0 + }) } func (runners RunnerList) LoadRepos(ctx context.Context) error { diff --git a/models/actions/schedule.go b/models/actions/schedule.go index d450e7aa07..3646a046a0 100644 --- a/models/actions/schedule.go +++ b/models/actions/schedule.go @@ -127,14 +127,14 @@ func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) er return fmt.Errorf("DeleteCronTaskByRepo: %v", err) } // cancel running cron jobs of this repository and delete old schedules - if err := CancelRunningJobs( + if err := CancelPreviousJobs( ctx, repo.ID, repo.DefaultBranch, "", webhook_module.HookEventSchedule, ); err != nil { - return fmt.Errorf("CancelRunningJobs: %v", err) + return fmt.Errorf("CancelPreviousJobs: %v", err) } return nil } diff --git a/models/actions/schedule_list.go b/models/actions/schedule_list.go index b806550b87..5361b94801 100644 --- a/models/actions/schedule_list.go +++ b/models/actions/schedule_list.go @@ -18,19 +18,15 @@ type ScheduleList []*ActionSchedule // GetUserIDs returns a slice of user's id func (schedules ScheduleList) GetUserIDs() []int64 { - ids := make(container.Set[int64], len(schedules)) - for _, schedule := range schedules { - ids.Add(schedule.TriggerUserID) - } - return ids.Values() + return container.FilterSlice(schedules, func(schedule *ActionSchedule) (int64, bool) { + return schedule.TriggerUserID, true + }) } func (schedules ScheduleList) GetRepoIDs() []int64 { - ids := make(container.Set[int64], len(schedules)) - for _, schedule := range schedules { - ids.Add(schedule.RepoID) - } - return ids.Values() + return container.FilterSlice(schedules, func(schedule *ActionSchedule) (int64, bool) { + return schedule.RepoID, true + }) } func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error { @@ -44,6 +40,9 @@ func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error { schedule.TriggerUser = user_model.NewActionsUser() } else { schedule.TriggerUser = users[schedule.TriggerUserID] + if schedule.TriggerUser == nil { + schedule.TriggerUser = user_model.NewGhostUser() + } } } return nil diff --git a/models/actions/schedule_spec_list.go b/models/actions/schedule_spec_list.go index e9ae268a6e..f7dac72f8b 100644 --- a/models/actions/schedule_spec_list.go +++ b/models/actions/schedule_spec_list.go @@ -16,11 +16,9 @@ import ( type SpecList []*ActionScheduleSpec func (specs SpecList) GetScheduleIDs() []int64 { - ids := make(container.Set[int64], len(specs)) - for _, spec := range specs { - ids.Add(spec.ScheduleID) - } - return ids.Values() + return container.FilterSlice(specs, func(spec *ActionScheduleSpec) (int64, bool) { + return spec.ScheduleID, true + }) } func (specs SpecList) LoadSchedules(ctx context.Context) error { @@ -46,11 +44,9 @@ func (specs SpecList) LoadSchedules(ctx context.Context) error { } func (specs SpecList) GetRepoIDs() []int64 { - ids := make(container.Set[int64], len(specs)) - for _, spec := range specs { - ids.Add(spec.RepoID) - } - return ids.Values() + return container.FilterSlice(specs, func(spec *ActionScheduleSpec) (int64, bool) { + return spec.RepoID, true + }) } func (specs SpecList) LoadRepos(ctx context.Context) error { diff --git a/models/actions/task.go b/models/actions/task.go index 96a6d2e80c..9946cf5233 100644 --- a/models/actions/task.go +++ b/models/actions/task.go @@ -11,6 +11,7 @@ import ( auth_model "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -227,7 +228,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask if runner.RepoID != 0 { jobCond = builder.Eq{"repo_id": runner.RepoID} } else if runner.OwnerID != 0 { - jobCond = builder.In("repo_id", builder.Select("id").From("repository").Where(builder.Eq{"owner_id": runner.OwnerID})) + jobCond = builder.In("repo_id", builder.Select("`repository`.id").From("repository"). + Join("INNER", "repo_unit", "`repository`.id = `repo_unit`.repo_id"). + Where(builder.Eq{"`repository`.owner_id": runner.OwnerID, "`repo_unit`.type": unit.TypeActions})) } if jobCond.IsValid() { jobCond = builder.In("run_id", builder.Select("id").From("action_run").Where(jobCond)) diff --git a/models/actions/task_list.go b/models/actions/task_list.go index b07d00b8db..5e17f91441 100644 --- a/models/actions/task_list.go +++ b/models/actions/task_list.go @@ -16,14 +16,9 @@ import ( type TaskList []*ActionTask func (tasks TaskList) GetJobIDs() []int64 { - ids := make(container.Set[int64], len(tasks)) - for _, t := range tasks { - if t.JobID == 0 { - continue - } - ids.Add(t.JobID) - } - return ids.Values() + return container.FilterSlice(tasks, func(t *ActionTask) (int64, bool) { + return t.JobID, t.JobID != 0 + }) } func (tasks TaskList) LoadJobs(ctx context.Context) error { diff --git a/models/actions/variable.go b/models/actions/variable.go index 14ded60fac..8aff844659 100644 --- a/models/actions/variable.go +++ b/models/actions/variable.go @@ -6,13 +6,11 @@ package actions import ( "context" "errors" - "fmt" "strings" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) @@ -55,24 +53,24 @@ type FindVariablesOpts struct { db.ListOptions OwnerID int64 RepoID int64 + Name string } func (opts FindVariablesOpts) ToConds() builder.Cond { cond := builder.NewCond() + // Since we now support instance-level variables, + // there is no need to check for null values for `owner_id` and `repo_id` cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) + + if opts.Name != "" { + cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)}) + } return cond } -func GetVariableByID(ctx context.Context, variableID int64) (*ActionVariable, error) { - var variable ActionVariable - has, err := db.GetEngine(ctx).Where("id=?", variableID).Get(&variable) - if err != nil { - return nil, err - } else if !has { - return nil, fmt.Errorf("variable with id %d: %w", variableID, util.ErrNotExist) - } - return &variable, nil +func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariable, error) { + return db.Find[ActionVariable](ctx, opts) } func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) { @@ -84,9 +82,21 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) return count != 0, err } +func DeleteVariable(ctx context.Context, id int64) error { + if _, err := db.DeleteByID[ActionVariable](ctx, id); err != nil { + return err + } + return nil +} + func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) { variables := map[string]string{} + if err := run.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) + return nil, err + } + // Global globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{}) if err != nil { diff --git a/models/activities/action.go b/models/activities/action.go index 36205eedd1..7e2ef4c9ae 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -148,6 +148,7 @@ type Action struct { Repo *repo_model.Repository `xorm:"-"` CommentID int64 `xorm:"INDEX"` Comment *issues_model.Comment `xorm:"-"` + Issue *issues_model.Issue `xorm:"-"` // get the issue id from content IsDeleted bool `xorm:"NOT NULL DEFAULT false"` RefName string IsPrivate bool `xorm:"NOT NULL DEFAULT false"` @@ -290,11 +291,6 @@ func (a *Action) GetRepoAbsoluteLink(ctx context.Context) string { return setting.AppURL + url.PathEscape(a.GetRepoUserName(ctx)) + "/" + url.PathEscape(a.GetRepoName(ctx)) } -// GetCommentHTMLURL returns link to action comment. -func (a *Action) GetCommentHTMLURL(ctx context.Context) string { - return a.getCommentHTMLURL(ctx) -} - func (a *Action) loadComment(ctx context.Context) (err error) { if a.CommentID == 0 || a.Comment != nil { return nil @@ -303,7 +299,8 @@ func (a *Action) loadComment(ctx context.Context) (err error) { return err } -func (a *Action) getCommentHTMLURL(ctx context.Context) string { +// GetCommentHTMLURL returns link to action comment. +func (a *Action) GetCommentHTMLURL(ctx context.Context) string { if a == nil { return "#" } @@ -311,34 +308,19 @@ func (a *Action) getCommentHTMLURL(ctx context.Context) string { if a.Comment != nil { return a.Comment.HTMLURL(ctx) } - if len(a.GetIssueInfos()) == 0 { + + if err := a.LoadIssue(ctx); err != nil || a.Issue == nil { return "#" } - // Return link to issue - issueIDString := a.GetIssueInfos()[0] - issueID, err := strconv.ParseInt(issueIDString, 10, 64) - if err != nil { + if err := a.Issue.LoadRepo(ctx); err != nil { return "#" } - issue, err := issues_model.GetIssueByID(ctx, issueID) - if err != nil { - return "#" - } - - if err = issue.LoadRepo(ctx); err != nil { - return "#" - } - - return issue.HTMLURL() + return a.Issue.HTMLURL() } // GetCommentLink returns link to action comment. func (a *Action) GetCommentLink(ctx context.Context) string { - return a.getCommentLink(ctx) -} - -func (a *Action) getCommentLink(ctx context.Context) string { if a == nil { return "#" } @@ -346,26 +328,15 @@ func (a *Action) getCommentLink(ctx context.Context) string { if a.Comment != nil { return a.Comment.Link(ctx) } - if len(a.GetIssueInfos()) == 0 { + + if err := a.LoadIssue(ctx); err != nil || a.Issue == nil { return "#" } - // Return link to issue - issueIDString := a.GetIssueInfos()[0] - issueID, err := strconv.ParseInt(issueIDString, 10, 64) - if err != nil { + if err := a.Issue.LoadRepo(ctx); err != nil { return "#" } - issue, err := issues_model.GetIssueByID(ctx, issueID) - if err != nil { - return "#" - } - - if err = issue.LoadRepo(ctx); err != nil { - return "#" - } - - return issue.Link() + return a.Issue.Link() } // GetBranch returns the action's repository branch. @@ -393,6 +364,10 @@ func (a *Action) GetCreate() time.Time { return a.CreatedUnix.AsTime() } +func (a *Action) IsIssueEvent() bool { + return a.OpType.InActions("comment_issue", "approve_pull_request", "reject_pull_request", "comment_pull", "merge_pull_request") +} + // GetIssueInfos returns a list of associated information with the action. func (a *Action) GetIssueInfos() []string { // make sure it always returns 3 elements, because there are some access to the a[1] and a[2] without checking the length @@ -403,27 +378,52 @@ func (a *Action) GetIssueInfos() []string { return ret } -// GetIssueTitle returns the title of first issue associated with the action. -func (a *Action) GetIssueTitle(ctx context.Context) string { - index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) - issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) - if err != nil { - log.Error("GetIssueByIndex: %v", err) - return "500 when get issue" +func (a *Action) getIssueIndex() int64 { + infos := a.GetIssueInfos() + if len(infos) == 0 { + return 0 } - return issue.Title + index, _ := strconv.ParseInt(infos[0], 10, 64) + return index } -// GetIssueContent returns the content of first issue associated with -// this action. -func (a *Action) GetIssueContent(ctx context.Context) string { - index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) - issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) - if err != nil { - log.Error("GetIssueByIndex: %v", err) - return "500 when get issue" +func (a *Action) LoadIssue(ctx context.Context) error { + if a.Issue != nil { + return nil } - return issue.Content + if index := a.getIssueIndex(); index > 0 { + issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) + if err != nil { + return err + } + a.Issue = issue + a.Issue.Repo = a.Repo + } + return nil +} + +// GetIssueTitle returns the title of first issue associated with the action. +func (a *Action) GetIssueTitle(ctx context.Context) string { + if err := a.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return "<500 when get issue>" + } + if a.Issue == nil { + return "" + } + return a.Issue.Title +} + +// GetIssueContent returns the content of first issue associated with this action. +func (a *Action) GetIssueContent(ctx context.Context) string { + if err := a.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return "<500 when get issue>" + } + if a.Issue == nil { + return "" + } + return a.Issue.Content } // GetFeedsOptions options for retrieving feeds @@ -463,7 +463,7 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err return nil, 0, fmt.Errorf("FindAndCount: %w", err) } - if err := ActionList(actions).loadAttributes(ctx); err != nil { + if err := ActionList(actions).LoadAttributes(ctx); err != nil { return nil, 0, fmt.Errorf("LoadAttributes: %w", err) } diff --git a/models/activities/action_list.go b/models/activities/action_list.go index 3d74397c69..aafb7f8a26 100644 --- a/models/activities/action_list.go +++ b/models/activities/action_list.go @@ -6,25 +6,28 @@ package activities import ( "context" "fmt" + "strconv" "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" ) // ActionList defines a list of actions type ActionList []*Action func (actions ActionList) getUserIDs() []int64 { - userIDs := make(container.Set[int64], len(actions)) - for _, action := range actions { - userIDs.Add(action.ActUserID) - } - return userIDs.Values() + return container.FilterSlice(actions, func(action *Action) (int64, bool) { + return action.ActUserID, true + }) } -func (actions ActionList) loadUsers(ctx context.Context) (map[int64]*user_model.User, error) { +func (actions ActionList) LoadActUsers(ctx context.Context) (map[int64]*user_model.User, error) { if len(actions) == 0 { return nil, nil } @@ -45,14 +48,12 @@ func (actions ActionList) loadUsers(ctx context.Context) (map[int64]*user_model. } func (actions ActionList) getRepoIDs() []int64 { - repoIDs := make(container.Set[int64], len(actions)) - for _, action := range actions { - repoIDs.Add(action.RepoID) - } - return repoIDs.Values() + return container.FilterSlice(actions, func(action *Action) (int64, bool) { + return action.RepoID, true + }) } -func (actions ActionList) loadRepositories(ctx context.Context) error { +func (actions ActionList) LoadRepositories(ctx context.Context) error { if len(actions) == 0 { return nil } @@ -63,11 +64,11 @@ func (actions ActionList) loadRepositories(ctx context.Context) error { if err != nil { return fmt.Errorf("find repository: %w", err) } - for _, action := range actions { action.Repo = repoMaps[action.RepoID] } - return nil + repos := repo_model.RepositoryList(util.ValuesOfMap(repoMaps)) + return repos.LoadUnits(ctx) } func (actions ActionList) loadRepoOwner(ctx context.Context, userMap map[int64]*user_model.User) (err error) { @@ -75,37 +76,128 @@ func (actions ActionList) loadRepoOwner(ctx context.Context, userMap map[int64]* userMap = make(map[int64]*user_model.User) } - for _, action := range actions { + missingUserIDs := container.FilterSlice(actions, func(action *Action) (int64, bool) { if action.Repo == nil { - continue + return 0, false } - repoOwner, ok := userMap[action.Repo.OwnerID] - if !ok { - repoOwner, err = user_model.GetUserByID(ctx, action.Repo.OwnerID) - if err != nil { - if user_model.IsErrUserNotExist(err) { - continue - } - return err - } - userMap[repoOwner.ID] = repoOwner + _, alreadyLoaded := userMap[action.Repo.OwnerID] + return action.Repo.OwnerID, !alreadyLoaded + }) + if len(missingUserIDs) == 0 { + return nil + } + + if err := db.GetEngine(ctx). + In("id", missingUserIDs). + Find(&userMap); err != nil { + return fmt.Errorf("find user: %w", err) + } + + for _, action := range actions { + if action.Repo != nil { + action.Repo.Owner = userMap[action.Repo.OwnerID] } - action.Repo.Owner = repoOwner } return nil } -// loadAttributes loads all attributes -func (actions ActionList) loadAttributes(ctx context.Context) error { - userMap, err := actions.loadUsers(ctx) +// LoadAttributes loads all attributes +func (actions ActionList) LoadAttributes(ctx context.Context) error { + // the load sequence cannot be changed because of the dependencies + userMap, err := actions.LoadActUsers(ctx) if err != nil { return err } - - if err := actions.loadRepositories(ctx); err != nil { + if err := actions.LoadRepositories(ctx); err != nil { return err } - - return actions.loadRepoOwner(ctx, userMap) + if err := actions.loadRepoOwner(ctx, userMap); err != nil { + return err + } + if err := actions.LoadIssues(ctx); err != nil { + return err + } + return actions.LoadComments(ctx) +} + +func (actions ActionList) LoadComments(ctx context.Context) error { + if len(actions) == 0 { + return nil + } + + commentIDs := make([]int64, 0, len(actions)) + for _, action := range actions { + if action.CommentID > 0 { + commentIDs = append(commentIDs, action.CommentID) + } + } + if len(commentIDs) == 0 { + return nil + } + + commentsMap := make(map[int64]*issues_model.Comment, len(commentIDs)) + if err := db.GetEngine(ctx).In("id", commentIDs).Find(&commentsMap); err != nil { + return fmt.Errorf("find comment: %w", err) + } + + for _, action := range actions { + if action.CommentID > 0 { + action.Comment = commentsMap[action.CommentID] + if action.Comment != nil { + action.Comment.Issue = action.Issue + } + } + } + return nil +} + +func (actions ActionList) LoadIssues(ctx context.Context) error { + if len(actions) == 0 { + return nil + } + + conditions := builder.NewCond() + issueNum := 0 + for _, action := range actions { + if action.IsIssueEvent() { + infos := action.GetIssueInfos() + if len(infos) == 0 { + continue + } + index, _ := strconv.ParseInt(infos[0], 10, 64) + if index > 0 { + conditions = conditions.Or(builder.Eq{ + "repo_id": action.RepoID, + "`index`": index, + }) + issueNum++ + } + } + } + if !conditions.IsValid() { + return nil + } + + issuesMap := make(map[string]*issues_model.Issue, issueNum) + issues := make([]*issues_model.Issue, 0, issueNum) + if err := db.GetEngine(ctx).Where(conditions).Find(&issues); err != nil { + return fmt.Errorf("find issue: %w", err) + } + for _, issue := range issues { + issuesMap[fmt.Sprintf("%d-%d", issue.RepoID, issue.Index)] = issue + } + + for _, action := range actions { + if !action.IsIssueEvent() { + continue + } + if index := action.getIssueIndex(); index > 0 { + if issue, ok := issuesMap[fmt.Sprintf("%d-%d", action.RepoID, index)]; ok { + action.Issue = issue + action.Issue.Repo = action.Repo + } + } + } + return nil } diff --git a/models/activities/notification.go b/models/activities/notification.go index 230bcdd6e8..dc1b8c6fae 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -12,12 +12,8 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" - access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/container" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" @@ -79,53 +75,6 @@ func init() { db.RegisterModel(new(Notification)) } -// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. -type FindNotificationOptions struct { - db.ListOptions - UserID int64 - RepoID int64 - IssueID int64 - Status []NotificationStatus - Source []NotificationSource - UpdatedAfterUnix int64 - UpdatedBeforeUnix int64 -} - -// ToCond will convert each condition into a xorm-Cond -func (opts FindNotificationOptions) ToConds() builder.Cond { - cond := builder.NewCond() - if opts.UserID != 0 { - cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) - } - if opts.RepoID != 0 { - cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) - } - if opts.IssueID != 0 { - cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) - } - if len(opts.Status) > 0 { - if len(opts.Status) == 1 { - cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) - } else { - cond = cond.And(builder.In("notification.status", opts.Status)) - } - } - if len(opts.Source) > 0 { - cond = cond.And(builder.In("notification.source", opts.Source)) - } - if opts.UpdatedAfterUnix != 0 { - cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) - } - if opts.UpdatedBeforeUnix != 0 { - cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) - } - return cond -} - -func (opts FindNotificationOptions) ToOrders() string { - return "notification.updated_unix DESC" -} - // CreateRepoTransferNotification creates notification for the user a repository was transferred to func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { return db.WithTx(ctx, func(ctx context.Context) error { @@ -159,109 +108,6 @@ func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_mo }) } -// CreateOrUpdateIssueNotifications creates an issue notification -// for each watcher, or updates it if already exists -// receiverID > 0 just send to receiver, else send to all watcher -func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if err := createOrUpdateIssueNotifications(ctx, issueID, commentID, notificationAuthorID, receiverID); err != nil { - return err - } - - return committer.Commit() -} - -func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { - // init - var toNotify container.Set[int64] - notifications, err := db.Find[Notification](ctx, FindNotificationOptions{ - IssueID: issueID, - }) - if err != nil { - return err - } - - issue, err := issues_model.GetIssueByID(ctx, issueID) - if err != nil { - return err - } - - if receiverID > 0 { - toNotify = make(container.Set[int64], 1) - toNotify.Add(receiverID) - } else { - toNotify = make(container.Set[int64], 32) - issueWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, true) - if err != nil { - return err - } - toNotify.AddMultiple(issueWatches...) - if !(issue.IsPull && issues_model.HasWorkInProgressPrefix(issue.Title)) { - repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID) - if err != nil { - return err - } - toNotify.AddMultiple(repoWatches...) - } - issueParticipants, err := issue.GetParticipantIDsByIssue(ctx) - if err != nil { - return err - } - toNotify.AddMultiple(issueParticipants...) - - // dont notify user who cause notification - delete(toNotify, notificationAuthorID) - // explicit unwatch on issue - issueUnWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, false) - if err != nil { - return err - } - for _, id := range issueUnWatches { - toNotify.Remove(id) - } - } - - err = issue.LoadRepo(ctx) - if err != nil { - return err - } - - // notify - for userID := range toNotify { - issue.Repo.Units = nil - user, err := user_model.GetUserByID(ctx, userID) - if err != nil { - if user_model.IsErrUserNotExist(err) { - continue - } - - return err - } - if issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) { - continue - } - if !issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) { - continue - } - - if notificationExists(notifications, issue.ID, userID) { - if err = updateIssueNotification(ctx, userID, issue.ID, commentID, notificationAuthorID); err != nil { - return err - } - continue - } - if err = createIssueNotification(ctx, userID, issue, commentID, notificationAuthorID); err != nil { - return err - } - } - return nil -} - func createIssueNotification(ctx context.Context, userID int64, issue *issues_model.Issue, commentID, updatedByID int64) error { notification := &Notification{ UserID: userID, @@ -449,309 +295,6 @@ func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.Tim return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) } -// NotificationList contains a list of notifications -type NotificationList []*Notification - -// LoadAttributes load Repo Issue User and Comment if not loaded -func (nl NotificationList) LoadAttributes(ctx context.Context) error { - if _, _, err := nl.LoadRepos(ctx); err != nil { - return err - } - if _, err := nl.LoadIssues(ctx); err != nil { - return err - } - if _, err := nl.LoadUsers(ctx); err != nil { - return err - } - if _, err := nl.LoadComments(ctx); err != nil { - return err - } - return nil -} - -func (nl NotificationList) getPendingRepoIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Repository != nil { - continue - } - ids.Add(notification.RepoID) - } - return ids.Values() -} - -// LoadRepos loads repositories from database -func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { - if len(nl) == 0 { - return repo_model.RepositoryList{}, []int{}, nil - } - - repoIDs := nl.getPendingRepoIDs() - repos := make(map[int64]*repo_model.Repository, len(repoIDs)) - left := len(repoIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", repoIDs[:limit]). - Rows(new(repo_model.Repository)) - if err != nil { - return nil, nil, err - } - - for rows.Next() { - var repo repo_model.Repository - err = rows.Scan(&repo) - if err != nil { - rows.Close() - return nil, nil, err - } - - repos[repo.ID] = &repo - } - _ = rows.Close() - - left -= limit - repoIDs = repoIDs[limit:] - } - - failed := []int{} - - reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) - for i, notification := range nl { - if notification.Repository == nil { - notification.Repository = repos[notification.RepoID] - } - if notification.Repository == nil { - log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) - failed = append(failed, i) - continue - } - var found bool - for _, r := range reposList { - if r.ID == notification.RepoID { - found = true - break - } - } - if !found { - reposList = append(reposList, notification.Repository) - } - } - return reposList, failed, nil -} - -func (nl NotificationList) getPendingIssueIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.Issue != nil { - continue - } - ids.Add(notification.IssueID) - } - return ids.Values() -} - -// LoadIssues loads issues from database -func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - issueIDs := nl.getPendingIssueIDs() - issues := make(map[int64]*issues_model.Issue, len(issueIDs)) - left := len(issueIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", issueIDs[:limit]). - Rows(new(issues_model.Issue)) - if err != nil { - return nil, err - } - - for rows.Next() { - var issue issues_model.Issue - err = rows.Scan(&issue) - if err != nil { - rows.Close() - return nil, err - } - - issues[issue.ID] = &issue - } - _ = rows.Close() - - left -= limit - issueIDs = issueIDs[limit:] - } - - failures := []int{} - - for i, notification := range nl { - if notification.Issue == nil { - notification.Issue = issues[notification.IssueID] - if notification.Issue == nil { - if notification.IssueID != 0 { - log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) - failures = append(failures, i) - } - continue - } - notification.Issue.Repo = notification.Repository - } - } - return failures, nil -} - -// Without returns the notification list without the failures -func (nl NotificationList) Without(failures []int) NotificationList { - if len(failures) == 0 { - return nl - } - remaining := make([]*Notification, 0, len(nl)) - last := -1 - var i int - for _, i = range failures { - remaining = append(remaining, nl[last+1:i]...) - last = i - } - if len(nl) > i { - remaining = append(remaining, nl[i+1:]...) - } - return remaining -} - -func (nl NotificationList) getPendingCommentIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.CommentID == 0 || notification.Comment != nil { - continue - } - ids.Add(notification.CommentID) - } - return ids.Values() -} - -func (nl NotificationList) getUserIDs() []int64 { - ids := make(container.Set[int64], len(nl)) - for _, notification := range nl { - if notification.UserID == 0 || notification.User != nil { - continue - } - ids.Add(notification.UserID) - } - return ids.Values() -} - -// LoadUsers loads users from database -func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - userIDs := nl.getUserIDs() - users := make(map[int64]*user_model.User, len(userIDs)) - left := len(userIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", userIDs[:limit]). - Rows(new(user_model.User)) - if err != nil { - return nil, err - } - - for rows.Next() { - var user user_model.User - err = rows.Scan(&user) - if err != nil { - rows.Close() - return nil, err - } - - users[user.ID] = &user - } - _ = rows.Close() - - left -= limit - userIDs = userIDs[limit:] - } - - failures := []int{} - for i, notification := range nl { - if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil { - notification.User = users[notification.UserID] - if notification.User == nil { - log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID) - failures = append(failures, i) - continue - } - } - } - return failures, nil -} - -// LoadComments loads comments from database -func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { - if len(nl) == 0 { - return []int{}, nil - } - - commentIDs := nl.getPendingCommentIDs() - comments := make(map[int64]*issues_model.Comment, len(commentIDs)) - left := len(commentIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", commentIDs[:limit]). - Rows(new(issues_model.Comment)) - if err != nil { - return nil, err - } - - for rows.Next() { - var comment issues_model.Comment - err = rows.Scan(&comment) - if err != nil { - rows.Close() - return nil, err - } - - comments[comment.ID] = &comment - } - _ = rows.Close() - - left -= limit - commentIDs = commentIDs[limit:] - } - - failures := []int{} - for i, notification := range nl { - if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { - notification.Comment = comments[notification.CommentID] - if notification.Comment == nil { - log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) - failures = append(failures, i) - continue - } - notification.Comment.Issue = notification.Issue - } - } - return failures, nil -} - // SetIssueReadBy sets issue to be read by given user. func SetIssueReadBy(ctx context.Context, issueID, userID int64) error { if err := issues_model.UpdateIssueUserByRead(ctx, userID, issueID); err != nil { diff --git a/models/activities/notification_list.go b/models/activities/notification_list.go new file mode 100644 index 0000000000..0cbb91df3c --- /dev/null +++ b/models/activities/notification_list.go @@ -0,0 +1,499 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package activities + +import ( + "context" + + "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" + access_model "code.gitea.io/gitea/models/perm/access" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" +) + +// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored. +type FindNotificationOptions struct { + db.ListOptions + UserID int64 + RepoID int64 + IssueID int64 + Status []NotificationStatus + Source []NotificationSource + UpdatedAfterUnix int64 + UpdatedBeforeUnix int64 +} + +// ToCond will convert each condition into a xorm-Cond +func (opts FindNotificationOptions) ToConds() builder.Cond { + cond := builder.NewCond() + if opts.UserID != 0 { + cond = cond.And(builder.Eq{"notification.user_id": opts.UserID}) + } + if opts.RepoID != 0 { + cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID}) + } + if opts.IssueID != 0 { + cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID}) + } + if len(opts.Status) > 0 { + if len(opts.Status) == 1 { + cond = cond.And(builder.Eq{"notification.status": opts.Status[0]}) + } else { + cond = cond.And(builder.In("notification.status", opts.Status)) + } + } + if len(opts.Source) > 0 { + cond = cond.And(builder.In("notification.source", opts.Source)) + } + if opts.UpdatedAfterUnix != 0 { + cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix}) + } + if opts.UpdatedBeforeUnix != 0 { + cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix}) + } + return cond +} + +func (opts FindNotificationOptions) ToOrders() string { + return "notification.updated_unix DESC" +} + +// CreateOrUpdateIssueNotifications creates an issue notification +// for each watcher, or updates it if already exists +// receiverID > 0 just send to receiver, else send to all watcher +func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { + ctx, committer, err := db.TxContext(ctx) + if err != nil { + return err + } + defer committer.Close() + + if err := createOrUpdateIssueNotifications(ctx, issueID, commentID, notificationAuthorID, receiverID); err != nil { + return err + } + + return committer.Commit() +} + +func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { + // init + var toNotify container.Set[int64] + notifications, err := db.Find[Notification](ctx, FindNotificationOptions{ + IssueID: issueID, + }) + if err != nil { + return err + } + + issue, err := issues_model.GetIssueByID(ctx, issueID) + if err != nil { + return err + } + + if receiverID > 0 { + toNotify = make(container.Set[int64], 1) + toNotify.Add(receiverID) + } else { + toNotify = make(container.Set[int64], 32) + issueWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, true) + if err != nil { + return err + } + toNotify.AddMultiple(issueWatches...) + if !(issue.IsPull && issues_model.HasWorkInProgressPrefix(issue.Title)) { + repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID) + if err != nil { + return err + } + toNotify.AddMultiple(repoWatches...) + } + issueParticipants, err := issue.GetParticipantIDsByIssue(ctx) + if err != nil { + return err + } + toNotify.AddMultiple(issueParticipants...) + + // dont notify user who cause notification + delete(toNotify, notificationAuthorID) + // explicit unwatch on issue + issueUnWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, false) + if err != nil { + return err + } + for _, id := range issueUnWatches { + toNotify.Remove(id) + } + } + + err = issue.LoadRepo(ctx) + if err != nil { + return err + } + + // notify + for userID := range toNotify { + issue.Repo.Units = nil + user, err := user_model.GetUserByID(ctx, userID) + if err != nil { + if user_model.IsErrUserNotExist(err) { + continue + } + + return err + } + if issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) { + continue + } + if !issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) { + continue + } + + if notificationExists(notifications, issue.ID, userID) { + if err = updateIssueNotification(ctx, userID, issue.ID, commentID, notificationAuthorID); err != nil { + return err + } + continue + } + if err = createIssueNotification(ctx, userID, issue, commentID, notificationAuthorID); err != nil { + return err + } + } + return nil +} + +// NotificationList contains a list of notifications +type NotificationList []*Notification + +// LoadAttributes load Repo Issue User and Comment if not loaded +func (nl NotificationList) LoadAttributes(ctx context.Context) error { + if _, _, err := nl.LoadRepos(ctx); err != nil { + return err + } + if _, err := nl.LoadIssues(ctx); err != nil { + return err + } + if _, err := nl.LoadUsers(ctx); err != nil { + return err + } + if _, err := nl.LoadComments(ctx); err != nil { + return err + } + return nil +} + +func (nl NotificationList) getPendingRepoIDs() []int64 { + return container.FilterSlice(nl, func(n *Notification) (int64, bool) { + if n.Repository != nil { + return 0, false + } + return n.RepoID, true + }) +} + +// LoadRepos loads repositories from database +func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { + if len(nl) == 0 { + return repo_model.RepositoryList{}, []int{}, nil + } + + repoIDs := nl.getPendingRepoIDs() + repos := make(map[int64]*repo_model.Repository, len(repoIDs)) + left := len(repoIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", repoIDs[:limit]). + Rows(new(repo_model.Repository)) + if err != nil { + return nil, nil, err + } + + for rows.Next() { + var repo repo_model.Repository + err = rows.Scan(&repo) + if err != nil { + rows.Close() + return nil, nil, err + } + + repos[repo.ID] = &repo + } + _ = rows.Close() + + left -= limit + repoIDs = repoIDs[limit:] + } + + failed := []int{} + + reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) + for i, notification := range nl { + if notification.Repository == nil { + notification.Repository = repos[notification.RepoID] + } + if notification.Repository == nil { + log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID) + failed = append(failed, i) + continue + } + var found bool + for _, r := range reposList { + if r.ID == notification.RepoID { + found = true + break + } + } + if !found { + reposList = append(reposList, notification.Repository) + } + } + return reposList, failed, nil +} + +func (nl NotificationList) getPendingIssueIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.Issue != nil { + continue + } + ids.Add(notification.IssueID) + } + return ids.Values() +} + +// LoadIssues loads issues from database +func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + issueIDs := nl.getPendingIssueIDs() + issues := make(map[int64]*issues_model.Issue, len(issueIDs)) + left := len(issueIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", issueIDs[:limit]). + Rows(new(issues_model.Issue)) + if err != nil { + return nil, err + } + + for rows.Next() { + var issue issues_model.Issue + err = rows.Scan(&issue) + if err != nil { + rows.Close() + return nil, err + } + + issues[issue.ID] = &issue + } + _ = rows.Close() + + left -= limit + issueIDs = issueIDs[limit:] + } + + failures := []int{} + + for i, notification := range nl { + if notification.Issue == nil { + notification.Issue = issues[notification.IssueID] + if notification.Issue == nil { + if notification.IssueID != 0 { + log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID) + failures = append(failures, i) + } + continue + } + notification.Issue.Repo = notification.Repository + } + } + return failures, nil +} + +// Without returns the notification list without the failures +func (nl NotificationList) Without(failures []int) NotificationList { + if len(failures) == 0 { + return nl + } + remaining := make([]*Notification, 0, len(nl)) + last := -1 + var i int + for _, i = range failures { + remaining = append(remaining, nl[last+1:i]...) + last = i + } + if len(nl) > i { + remaining = append(remaining, nl[i+1:]...) + } + return remaining +} + +func (nl NotificationList) getPendingCommentIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.CommentID == 0 || notification.Comment != nil { + continue + } + ids.Add(notification.CommentID) + } + return ids.Values() +} + +func (nl NotificationList) getUserIDs() []int64 { + ids := make(container.Set[int64], len(nl)) + for _, notification := range nl { + if notification.UserID == 0 || notification.User != nil { + continue + } + ids.Add(notification.UserID) + } + return ids.Values() +} + +// LoadUsers loads users from database +func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + userIDs := nl.getUserIDs() + users := make(map[int64]*user_model.User, len(userIDs)) + left := len(userIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", userIDs[:limit]). + Rows(new(user_model.User)) + if err != nil { + return nil, err + } + + for rows.Next() { + var user user_model.User + err = rows.Scan(&user) + if err != nil { + rows.Close() + return nil, err + } + + users[user.ID] = &user + } + _ = rows.Close() + + left -= limit + userIDs = userIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil { + notification.User = users[notification.UserID] + if notification.User == nil { + log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID) + failures = append(failures, i) + continue + } + } + } + return failures, nil +} + +// LoadComments loads comments from database +func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { + if len(nl) == 0 { + return []int{}, nil + } + + commentIDs := nl.getPendingCommentIDs() + comments := make(map[int64]*issues_model.Comment, len(commentIDs)) + left := len(commentIDs) + for left > 0 { + limit := db.DefaultMaxInSize + if left < limit { + limit = left + } + rows, err := db.GetEngine(ctx). + In("id", commentIDs[:limit]). + Rows(new(issues_model.Comment)) + if err != nil { + return nil, err + } + + for rows.Next() { + var comment issues_model.Comment + err = rows.Scan(&comment) + if err != nil { + rows.Close() + return nil, err + } + + comments[comment.ID] = &comment + } + _ = rows.Close() + + left -= limit + commentIDs = commentIDs[limit:] + } + + failures := []int{} + for i, notification := range nl { + if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil { + notification.Comment = comments[notification.CommentID] + if notification.Comment == nil { + log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID) + failures = append(failures, i) + continue + } + notification.Comment.Issue = notification.Issue + } + } + return failures, nil +} + +// LoadIssuePullRequests loads all issues' pull requests if possible +func (nl NotificationList) LoadIssuePullRequests(ctx context.Context) error { + issues := make(map[int64]*issues_model.Issue, len(nl)) + for _, notification := range nl { + if notification.Issue != nil && notification.Issue.IsPull && notification.Issue.PullRequest == nil { + issues[notification.Issue.ID] = notification.Issue + } + } + + if len(issues) == 0 { + return nil + } + + pulls, err := issues_model.GetPullRequestByIssueIDs(ctx, util.KeysOfMap(issues)) + if err != nil { + return err + } + + for _, pull := range pulls { + if issue := issues[pull.IssueID]; issue != nil { + issue.PullRequest = pull + issue.PullRequest.Issue = issue + } + } + + return nil +} diff --git a/models/activities/statistic.go b/models/activities/statistic.go index fe5f7d0872..d1a459d1b2 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -9,6 +9,7 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" @@ -29,7 +30,8 @@ type Statistic struct { Mirror, Release, AuthSource, Webhook, Milestone, Label, HookTask, Team, UpdateTask, Project, - ProjectBoard, Attachment int64 + ProjectBoard, Attachment, + Branches, Tags, CommitStatus int64 IssueByLabel []IssueByLabelCount IssueByRepository []IssueByRepositoryCount } @@ -58,6 +60,9 @@ func GetStatistic(ctx context.Context) (stats Statistic) { stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) stats.Counter.Star, _ = e.Count(new(repo_model.Star)) stats.Counter.Access, _ = e.Count(new(access_model.Access)) + stats.Counter.Branches, _ = e.Count(new(git_model.Branch)) + stats.Counter.Tags, _ = e.Where("is_draft=?", false).Count(new(repo_model.Release)) + stats.Counter.CommitStatus, _ = e.Count(new(git_model.CommitStatus)) type IssueCount struct { Count int64 diff --git a/models/asymkey/gpg_key_commit_verification.go b/models/asymkey/gpg_key_commit_verification.go index 83fbab5d36..26fad3bb3f 100644 --- a/models/asymkey/gpg_key_commit_verification.go +++ b/models/asymkey/gpg_key_commit_verification.go @@ -110,7 +110,6 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific Reason: "gpg.error.no_committer_account", } } - } } @@ -139,13 +138,7 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific } } - keyID := "" - if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 { - keyID = fmt.Sprintf("%X", *sig.IssuerKeyId) - } - if keyID == "" && sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 { - keyID = fmt.Sprintf("%X", sig.IssuerFingerprint[12:20]) - } + keyID := tryGetKeyIDFromSignature(sig) defaultReason := NoKeyFound // First check if the sig has a keyID and if so just look at that diff --git a/models/asymkey/gpg_key_common.go b/models/asymkey/gpg_key_common.go index b02be2851a..9c015582f1 100644 --- a/models/asymkey/gpg_key_common.go +++ b/models/asymkey/gpg_key_common.go @@ -134,3 +134,13 @@ func extractSignature(s string) (*packet.Signature, error) { } return sig, nil } + +func tryGetKeyIDFromSignature(sig *packet.Signature) string { + if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 { + return fmt.Sprintf("%016X", *sig.IssuerKeyId) + } + if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 { + return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20]) + } + return "" +} diff --git a/models/asymkey/gpg_key_test.go b/models/asymkey/gpg_key_test.go index dee74bc281..d3fbb01d82 100644 --- a/models/asymkey/gpg_key_test.go +++ b/models/asymkey/gpg_key_test.go @@ -11,7 +11,9 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" + "github.com/keybase/go-crypto/openpgp/packet" "github.com/stretchr/testify/assert" ) @@ -391,3 +393,13 @@ epiDVQ== assert.Equal(t, time.Unix(1586105389, 0), expire) } } + +func TestTryGetKeyIDFromSignature(t *testing.T) { + assert.Empty(t, tryGetKeyIDFromSignature(&packet.Signature{})) + assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{ + IssuerKeyId: util.ToPointer(uint64(0x38D1A3EADDBEA9C)), + })) + assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{ + IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c}, + })) +} diff --git a/models/asymkey/gpg_key_verify.go b/models/asymkey/gpg_key_verify.go index 4cf46ab556..01812a2d54 100644 --- a/models/asymkey/gpg_key_verify.go +++ b/models/asymkey/gpg_key_verify.go @@ -46,6 +46,10 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st return "", ErrGPGKeyNotExist{} } + if err := key.LoadSubKeys(ctx); err != nil { + return "", err + } + sig, err := extractSignature(signature) if err != nil { return "", ErrGPGInvalidTokenSignature{ diff --git a/models/asymkey/ssh_key_authorized_keys.go b/models/asymkey/ssh_key_authorized_keys.go index 9279db2020..2e4cd62e5c 100644 --- a/models/asymkey/ssh_key_authorized_keys.go +++ b/models/asymkey/ssh_key_authorized_keys.go @@ -139,6 +139,8 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { if err != nil { return err } + defer f.Close() + scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() @@ -148,11 +150,12 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { } _, err = t.WriteString(line + "\n") if err != nil { - f.Close() return err } } - f.Close() + if err = scanner.Err(); err != nil { + return fmt.Errorf("RegeneratePublicKeys scan: %w", err) + } } return nil } diff --git a/models/asymkey/ssh_key_fingerprint.go b/models/asymkey/ssh_key_fingerprint.go index b9cfb1b251..1ed3b5df2a 100644 --- a/models/asymkey/ssh_key_fingerprint.go +++ b/models/asymkey/ssh_key_fingerprint.go @@ -76,23 +76,14 @@ func calcFingerprintNative(publicKeyContent string) (string, error) { // CalcFingerprint calculate public key's fingerprint func CalcFingerprint(publicKeyContent string) (string, error) { // Call the method based on configuration - var ( - fnName, fp string - err error - ) - if len(setting.SSH.KeygenPath) == 0 { - fnName = "calcFingerprintNative" - fp, err = calcFingerprintNative(publicKeyContent) - } else { - fnName = "calcFingerprintSSHKeygen" - fp, err = calcFingerprintSSHKeygen(publicKeyContent) - } + useNative := setting.SSH.KeygenPath == "" + calcFn := util.Iif(useNative, calcFingerprintNative, calcFingerprintSSHKeygen) + fp, err := calcFn(publicKeyContent) if err != nil { if IsErrKeyUnableVerify(err) { - log.Info("%s", publicKeyContent) return "", err } - return "", fmt.Errorf("%s: %w", fnName, err) + return "", fmt.Errorf("CalcFingerprint(%s): %w", util.Iif(useNative, "native", "ssh-keygen"), err) } return fp, nil } diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index 9d53fffc78..7dca378e5d 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -8,6 +8,7 @@ import ( "crypto/sha256" "encoding/base32" "encoding/base64" + "errors" "fmt" "net" "net/url" @@ -137,6 +138,11 @@ func (app *OAuth2Application) TableName() string { // ContainsRedirectURI checks if redirectURI is allowed for app func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { + // OAuth2 requires the redirect URI to be an exact match, no dynamic parts are allowed. + // https://stackoverflow.com/questions/55524480/should-dynamic-query-parameters-be-present-in-the-redirection-uri-for-an-oauth2 + // https://www.rfc-editor.org/rfc/rfc6819#section-5.2.3.3 + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-12#section-3.1 contains := func(s string) bool { s = strings.TrimSuffix(strings.ToLower(s), "/") for _, u := range app.RedirectURIs { @@ -289,7 +295,7 @@ func UpdateOAuth2Application(ctx context.Context, opts UpdateOAuth2ApplicationOp return nil, err } if app.UID != opts.UserID { - return nil, fmt.Errorf("UID mismatch") + return nil, errors.New("UID mismatch") } builtinApps := BuiltinApplications() if _, builtin := builtinApps[app.ClientID]; builtin { diff --git a/models/auth/oauth2_test.go b/models/auth/oauth2_test.go index 122d43098c..0829d31d51 100644 --- a/models/auth/oauth2_test.go +++ b/models/auth/oauth2_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" ) -//////////////////// Application - func TestOAuth2Application_GenerateClientSecret(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index bbe16483bf..9c56e0f9a0 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -24,7 +24,7 @@ import ( const ( // DefaultAvatarClass is the default class of a rendered avatar - DefaultAvatarClass = "ui avatar gt-vm" + DefaultAvatarClass = "ui avatar tw-align-middle" // DefaultAvatarPixelSize is the default size in pixels of a rendered avatar DefaultAvatarPixelSize = 28 ) diff --git a/models/db/consistency.go b/models/db/consistency.go index d19732cf80..d0b0ab8315 100644 --- a/models/db/consistency.go +++ b/models/db/consistency.go @@ -10,21 +10,21 @@ import ( ) // CountOrphanedObjects count subjects with have no existing refobject anymore -func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) (int64, error) { +func CountOrphanedObjects(ctx context.Context, subject, refObject, joinCond string) (int64, error) { return GetEngine(ctx). Table("`"+subject+"`"). - Join("LEFT", "`"+refobject+"`", joinCond). - Where(builder.IsNull{"`" + refobject + "`.id"}). + Join("LEFT", "`"+refObject+"`", joinCond). + Where(builder.IsNull{"`" + refObject + "`.id"}). Select("COUNT(`" + subject + "`.`id`)"). Count() } // DeleteOrphanedObjects delete subjects with have no existing refobject anymore -func DeleteOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) error { +func DeleteOrphanedObjects(ctx context.Context, subject, refObject, joinCond string) error { subQuery := builder.Select("`"+subject+"`.id"). From("`"+subject+"`"). - Join("LEFT", "`"+refobject+"`", joinCond). - Where(builder.IsNull{"`" + refobject + "`.id"}) + Join("LEFT", "`"+refObject+"`", joinCond). + Where(builder.IsNull{"`" + refObject + "`.id"}) b := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`") _, err := GetEngine(ctx).Exec(b) return err diff --git a/models/db/context.go b/models/db/context.go index cda608af19..43f612518a 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -120,6 +120,16 @@ func (c *halfCommitter) Close() error { // TxContext represents a transaction Context, // it will reuse the existing transaction in the parent context or create a new one. +// Some tips to use: +// +// 1 It's always recommended to use `WithTx` in new code instead of `TxContext`, since `WithTx` will handle the transaction automatically. +// 2. To maintain the old code which uses `TxContext`: +// a. Always call `Close()` before returning regardless of whether `Commit()` has been called. +// b. Always call `Commit()` before returning if there are no errors, even if the code did not change any data. +// c. Remember the `Committer` will be a halfCommitter when a transaction is being reused. +// So calling `Commit()` will do nothing, but calling `Close()` without calling `Commit()` will rollback the transaction. +// And all operations submitted by the caller stack will be rollbacked as well, not only the operations in the current function. +// d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback. func TxContext(parentCtx context.Context) (*Context, Committer, error) { if sess, ok := inTransaction(parentCtx); ok { return newContext(parentCtx, sess, true), &halfCommitter{committer: sess}, nil diff --git a/models/db/engine.go b/models/db/engine.go index 2a2743e927..25f4066ea1 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -21,9 +21,9 @@ import ( "xorm.io/xorm/names" "xorm.io/xorm/schemas" - _ "github.com/denisenkom/go-mssqldb" // Needed for the MSSQL driver - _ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver - _ "github.com/lib/pq" // Needed for the Postgresql driver + _ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver + _ "github.com/lib/pq" // Needed for the Postgresql driver + _ "github.com/microsoft/go-mssqldb" // Needed for the MSSQL driver ) var ( @@ -227,7 +227,6 @@ func NamesToBean(names ...string) ([]any, error) { // Need to map provided names to beans... beanMap := make(map[string]any) for _, bean := range tables { - beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean beanMap[strings.ToLower(x.TableName(bean))] = bean beanMap[strings.ToLower(x.TableName(bean, true))] = bean @@ -284,8 +283,8 @@ func MaxBatchInsertSize(bean any) int { } // IsTableNotEmpty returns true if table has at least one record -func IsTableNotEmpty(tableName string) (bool, error) { - return x.Table(tableName).Exist() +func IsTableNotEmpty(beanOrTableName any) (bool, error) { + return x.Table(beanOrTableName).Exist() } // DeleteAllRecords will delete all the records of this table diff --git a/models/fixtures/comment.yml b/models/fixtures/comment.yml index 17586caa21..74fc716180 100644 --- a/models/fixtures/comment.yml +++ b/models/fixtures/comment.yml @@ -75,3 +75,11 @@ content: "comment in private pository" created_unix: 946684811 updated_unix: 946684811 + +- + id: 9 + type: 22 # review + poster_id: 2 + issue_id: 2 # in repo_id 1 + review_id: 20 + created_unix: 946684810 diff --git a/models/fixtures/project.yml b/models/fixtures/project.yml index 1bf8030f6a..44d87bce04 100644 --- a/models/fixtures/project.yml +++ b/models/fixtures/project.yml @@ -45,3 +45,27 @@ type: 2 created_unix: 1688973000 updated_unix: 1688973000 + +- + id: 5 + title: project without default column + owner_id: 2 + repo_id: 0 + is_closed: false + creator_id: 2 + board_type: 1 + type: 2 + created_unix: 1688973000 + updated_unix: 1688973000 + +- + id: 6 + title: project with multiple default columns + owner_id: 2 + repo_id: 0 + is_closed: false + creator_id: 2 + board_type: 1 + type: 2 + created_unix: 1688973000 + updated_unix: 1688973000 diff --git a/models/fixtures/project_board.yml b/models/fixtures/project_board.yml index dc4f9cf565..3293dea6ed 100644 --- a/models/fixtures/project_board.yml +++ b/models/fixtures/project_board.yml @@ -3,6 +3,7 @@ project_id: 1 title: To Do creator_id: 2 + default: true created_unix: 1588117528 updated_unix: 1588117528 @@ -29,3 +30,48 @@ creator_id: 2 created_unix: 1588117528 updated_unix: 1588117528 + +- + id: 5 + project_id: 2 + title: Backlog + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 6 + project_id: 4 + title: Backlog + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 7 + project_id: 5 + title: Done + creator_id: 2 + default: false + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 8 + project_id: 6 + title: Backlog + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 9 + project_id: 6 + title: Uncategorized + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 diff --git a/models/fixtures/review.yml b/models/fixtures/review.yml index 7a88080068..ac97e24c2b 100644 --- a/models/fixtures/review.yml +++ b/models/fixtures/review.yml @@ -170,3 +170,12 @@ content: "review request for user15" updated_unix: 946684835 created_unix: 946684835 + +- + id: 20 + type: 22 + reviewer_id: 1 + issue_id: 2 + content: "Review Comment" + updated_unix: 946684810 + created_unix: 946684810 diff --git a/models/git/branch.go b/models/git/branch.go index fa0781fed1..2979dff3d2 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -297,6 +297,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str sess := db.GetEngine(ctx) + // check whether from branch exist var branch Branch exist, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, from).Get(&branch) if err != nil { @@ -308,6 +309,24 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str } } + // check whether to branch exist or is_deleted + var dstBranch Branch + exist, err = db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, to).Get(&dstBranch) + if err != nil { + return err + } + if exist { + if !dstBranch.IsDeleted { + return ErrBranchAlreadyExists{ + BranchName: to, + } + } + + if _, err := db.GetEngine(ctx).ID(dstBranch.ID).NoAutoCondition().Delete(&dstBranch); err != nil { + return err + } + } + // 1. update branch in database if n, err := sess.Where("repo_id=? AND name=?", repo.ID, from).Update(&Branch{ Name: to, @@ -362,12 +381,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str return err } - // 5. do git action - if err = gitAction(ctx, isDefault); err != nil { - return err - } - - // 6. insert renamed branch record + // 5. insert renamed branch record renamedBranch := &RenamedBranch{ RepoID: repo.ID, From: from, @@ -378,6 +392,11 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str return err } + // 6. do git action + if err = gitAction(ctx, isDefault); err != nil { + return err + } + return committer.Commit() } diff --git a/models/git/branch_list.go b/models/git/branch_list.go index 8319e5ecd0..980bd7b4c9 100644 --- a/models/git/branch_list.go +++ b/models/git/branch_list.go @@ -17,15 +17,12 @@ import ( type BranchList []*Branch func (branches BranchList) LoadDeletedBy(ctx context.Context) error { - ids := container.Set[int64]{} - for _, branch := range branches { - if !branch.IsDeleted { - continue - } - ids.Add(branch.DeletedByID) - } + ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) { + return branch.DeletedByID, branch.IsDeleted + }) + usersMap := make(map[int64]*user_model.User, len(ids)) - if err := db.GetEngine(ctx).In("id", ids.Values()).Find(&usersMap); err != nil { + if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil { return err } for _, branch := range branches { @@ -41,14 +38,13 @@ func (branches BranchList) LoadDeletedBy(ctx context.Context) error { } func (branches BranchList) LoadPusher(ctx context.Context) error { - ids := container.Set[int64]{} - for _, branch := range branches { - if branch.PusherID > 0 { // pusher_id maybe zero because some branches are sync by backend with no pusher - ids.Add(branch.PusherID) - } - } + ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) { + // pusher_id maybe zero because some branches are sync by backend with no pusher + return branch.PusherID, branch.PusherID > 0 + }) + usersMap := make(map[int64]*user_model.User, len(ids)) - if err := db.GetEngine(ctx).In("id", ids.Values()).Find(&usersMap); err != nil { + if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil { return err } for _, branch := range branches { diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 2d1d1bcb06..c3cda7b73d 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/translation" "xorm.io/builder" + "xorm.io/xorm" ) // CommitStatus holds a single Status of a single Commit @@ -269,63 +270,70 @@ type CommitStatusIndex struct { // GetLatestCommitStatus returns all statuses with a unique context for a given commit. func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, int64, error) { - ids := make([]int64, 0, 10) - sess := db.GetEngine(ctx).Table(&CommitStatus{}). - Where("repo_id = ?", repoID).And("sha = ?", sha). - Select("max( id ) as id"). - GroupBy("context_hash").OrderBy("max( id ) desc") + getBase := func() *xorm.Session { + return db.GetEngine(ctx).Table(&CommitStatus{}). + Where("repo_id = ?", repoID).And("sha = ?", sha) + } + indices := make([]int64, 0, 10) + sess := getBase().Select("max( `index` ) as `index`"). + GroupBy("context_hash").OrderBy("max( `index` ) desc") if !listOptions.IsListAll() { sess = db.SetSessionPagination(sess, &listOptions) } - count, err := sess.FindAndCount(&ids) + count, err := sess.FindAndCount(&indices) if err != nil { return nil, count, err } - statuses := make([]*CommitStatus, 0, len(ids)) - if len(ids) == 0 { + statuses := make([]*CommitStatus, 0, len(indices)) + if len(indices) == 0 { return statuses, count, nil } - return statuses, count, db.GetEngine(ctx).In("id", ids).Find(&statuses) + return statuses, count, getBase().And(builder.In("`index`", indices)).Find(&statuses) } // GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs -func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHAs map[int64]string, listOptions db.ListOptions) (map[int64][]*CommitStatus, error) { +func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map[int64][]*CommitStatus, error) { type result struct { - ID int64 + Index int64 RepoID int64 + SHA string } - results := make([]result, 0, len(repoIDsToLatestCommitSHAs)) + results := make([]result, 0, len(repoSHAs)) - sess := db.GetEngine(ctx).Table(&CommitStatus{}) + getBase := func() *xorm.Session { + return db.GetEngine(ctx).Table(&CommitStatus{}) + } // Create a disjunction of conditions for each repoID and SHA pair - conds := make([]builder.Cond, 0, len(repoIDsToLatestCommitSHAs)) - for repoID, sha := range repoIDsToLatestCommitSHAs { - conds = append(conds, builder.Eq{"repo_id": repoID, "sha": sha}) - } - sess = sess.Where(builder.Or(conds...)). - Select("max( id ) as id, repo_id"). - GroupBy("context_hash, repo_id").OrderBy("max( id ) desc") - - if !listOptions.IsListAll() { - sess = db.SetSessionPagination(sess, &listOptions) + conds := make([]builder.Cond, 0, len(repoSHAs)) + for _, repoSHA := range repoSHAs { + conds = append(conds, builder.Eq{"repo_id": repoSHA.RepoID, "sha": repoSHA.SHA}) } + sess := getBase().Where(builder.Or(conds...)). + Select("max( `index` ) as `index`, repo_id, sha"). + GroupBy("context_hash, repo_id, sha").OrderBy("max( `index` ) desc") err := sess.Find(&results) if err != nil { return nil, err } - ids := make([]int64, 0, len(results)) repoStatuses := make(map[int64][]*CommitStatus) - for _, result := range results { - ids = append(ids, result.ID) - } - statuses := make([]*CommitStatus, 0, len(ids)) - if len(ids) > 0 { - err = db.GetEngine(ctx).In("id", ids).Find(&statuses) + if len(results) > 0 { + statuses := make([]*CommitStatus, 0, len(results)) + + conds = make([]builder.Cond, 0, len(results)) + for _, result := range results { + cond := builder.Eq{ + "`index`": result.Index, + "repo_id": result.RepoID, + "sha": result.SHA, + } + conds = append(conds, cond) + } + err = getBase().Where(builder.Or(conds...)).Find(&statuses) if err != nil { return nil, err } @@ -342,42 +350,43 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHA // GetLatestCommitStatusForRepoCommitIDs returns all statuses with a unique context for a given list of repo-sha pairs func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, commitIDs []string) (map[string][]*CommitStatus, error) { type result struct { - ID int64 - Sha string + Index int64 + SHA string } + getBase := func() *xorm.Session { + return db.GetEngine(ctx).Table(&CommitStatus{}).Where("repo_id = ?", repoID) + } results := make([]result, 0, len(commitIDs)) - sess := db.GetEngine(ctx).Table(&CommitStatus{}) - - // Create a disjunction of conditions for each repoID and SHA pair conds := make([]builder.Cond, 0, len(commitIDs)) for _, sha := range commitIDs { conds = append(conds, builder.Eq{"sha": sha}) } - sess = sess.Where(builder.Eq{"repo_id": repoID}.And(builder.Or(conds...))). - Select("max( id ) as id, sha"). - GroupBy("context_hash, sha").OrderBy("max( id ) desc") + sess := getBase().And(builder.Or(conds...)). + Select("max( `index` ) as `index`, sha"). + GroupBy("context_hash, sha").OrderBy("max( `index` ) desc") err := sess.Find(&results) if err != nil { return nil, err } - ids := make([]int64, 0, len(results)) repoStatuses := make(map[string][]*CommitStatus) - for _, result := range results { - ids = append(ids, result.ID) - } - statuses := make([]*CommitStatus, 0, len(ids)) - if len(ids) > 0 { - err = db.GetEngine(ctx).In("id", ids).Find(&statuses) + if len(results) > 0 { + statuses := make([]*CommitStatus, 0, len(results)) + + conds = make([]builder.Cond, 0, len(results)) + for _, result := range results { + conds = append(conds, builder.Eq{"`index`": result.Index, "sha": result.SHA}) + } + err = getBase().And(builder.Or(conds...)).Find(&statuses) if err != nil { return nil, err } - // Group the statuses by repo ID + // Group the statuses by commit for _, status := range statuses { repoStatuses[status.SHA] = append(repoStatuses[status.SHA], status) } @@ -388,22 +397,36 @@ func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, co // FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) { + type result struct { + Index int64 + SHA string + } + getBase := func() *xorm.Session { + return db.GetEngine(ctx).Table(&CommitStatus{}).Where("repo_id = ?", repoID) + } + start := timeutil.TimeStampNow().AddDuration(-before) - ids := make([]int64, 0, 10) - if err := db.GetEngine(ctx).Table("commit_status"). - Where("repo_id = ?", repoID). - And("updated_unix >= ?", start). - Select("max( id ) as id"). - GroupBy("context_hash").OrderBy("max( id ) desc"). - Find(&ids); err != nil { + results := make([]result, 0, 10) + + sess := getBase().And("updated_unix >= ?", start). + Select("max( `index` ) as `index`, sha"). + GroupBy("context_hash, sha").OrderBy("max( `index` ) desc") + + err := sess.Find(&results) + if err != nil { return nil, err } - contexts := make([]string, 0, len(ids)) - if len(ids) == 0 { + contexts := make([]string, 0, len(results)) + if len(results) == 0 { return contexts, nil } - return contexts, db.GetEngine(ctx).Select("context").Table("commit_status").In("id", ids).Find(&contexts) + + conds := make([]builder.Cond, 0, len(results)) + for _, result := range results { + conds = append(conds, builder.Eq{"`index`": result.Index, "sha": result.SHA}) + } + return contexts, getBase().And(builder.Or(conds...)).Select("context").Find(&contexts) } // NewCommitStatusOptions holds options for creating a CommitStatus diff --git a/models/git/commit_status_summary.go b/models/git/commit_status_summary.go new file mode 100644 index 0000000000..7603e7aa65 --- /dev/null +++ b/models/git/commit_status_summary.go @@ -0,0 +1,88 @@ +// Copyright 2024 Gitea. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +import ( + "context" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + + "xorm.io/builder" +) + +// CommitStatusSummary holds the latest commit Status of a single Commit +type CommitStatusSummary struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX UNIQUE(repo_id_sha)"` + SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_id_sha)"` + State api.CommitStatusState `xorm:"VARCHAR(7) NOT NULL"` + TargetURL string `xorm:"TEXT"` +} + +func init() { + db.RegisterModel(new(CommitStatusSummary)) +} + +type RepoSHA struct { + RepoID int64 + SHA string +} + +func GetLatestCommitStatusForRepoAndSHAs(ctx context.Context, repoSHAs []RepoSHA) ([]*CommitStatus, error) { + cond := builder.NewCond() + for _, rs := range repoSHAs { + cond = cond.Or(builder.Eq{"repo_id": rs.RepoID, "sha": rs.SHA}) + } + + var summaries []CommitStatusSummary + if err := db.GetEngine(ctx).Where(cond).Find(&summaries); err != nil { + return nil, err + } + + commitStatuses := make([]*CommitStatus, 0, len(repoSHAs)) + for _, summary := range summaries { + commitStatuses = append(commitStatuses, &CommitStatus{ + RepoID: summary.RepoID, + SHA: summary.SHA, + State: summary.State, + TargetURL: summary.TargetURL, + }) + } + return commitStatuses, nil +} + +func UpdateCommitStatusSummary(ctx context.Context, repoID int64, sha string) error { + commitStatuses, _, err := GetLatestCommitStatus(ctx, repoID, sha, db.ListOptionsAll) + if err != nil { + return err + } + state := CalcCommitStatus(commitStatuses) + // mysql will return 0 when update a record which state hasn't been changed which behaviour is different from other database, + // so we need to use insert in on duplicate + if setting.Database.Type.IsMySQL() { + _, err := db.GetEngine(ctx).Exec("INSERT INTO commit_status_summary (repo_id,sha,state,target_url) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE state=?", + repoID, sha, state.State, state.TargetURL, state.State) + return err + } + + if cnt, err := db.GetEngine(ctx).Where("repo_id=? AND sha=?", repoID, sha). + Cols("state, target_url"). + Update(&CommitStatusSummary{ + State: state.State, + TargetURL: state.TargetURL, + }); err != nil { + return err + } else if cnt == 0 { + _, err = db.GetEngine(ctx).Insert(&CommitStatusSummary{ + RepoID: repoID, + SHA: sha, + State: state.State, + TargetURL: state.TargetURL, + }) + return err + } + return nil +} diff --git a/models/git/lfs_lock.go b/models/git/lfs_lock.go index 261c73032a..2f65833fe3 100644 --- a/models/git/lfs_lock.go +++ b/models/git/lfs_lock.go @@ -5,7 +5,7 @@ package git import ( "context" - "fmt" + "errors" "strings" "time" @@ -148,7 +148,7 @@ func DeleteLFSLockByID(ctx context.Context, id int64, repo *repo_model.Repositor } if !force && u.ID != lock.OwnerID { - return nil, fmt.Errorf("user doesn't own lock and force flag is not set") + return nil, errors.New("user doesn't own lock and force flag is not set") } if _, err := db.GetEngine(dbCtx).ID(id).Delete(new(LFSLock)); err != nil { diff --git a/models/issues/comment.go b/models/issues/comment.go index 8f5a868b64..810115f64e 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -674,7 +674,8 @@ func (c *Comment) LoadTime(ctx context.Context) error { return err } -func (c *Comment) loadReactions(ctx context.Context, repo *repo_model.Repository) (err error) { +// LoadReactions loads comment reactions +func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository) (err error) { if c.Reactions != nil { return nil } @@ -692,11 +693,6 @@ func (c *Comment) loadReactions(ctx context.Context, repo *repo_model.Repository return nil } -// LoadReactions loads comment reactions -func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository) error { - return c.loadReactions(ctx, repo) -} - func (c *Comment) loadReview(ctx context.Context) (err error) { if c.ReviewID == 0 { return nil @@ -1277,10 +1273,9 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error { return nil } - issueIDs := make(container.Set[int64]) - for _, comment := range comments { - issueIDs.Add(comment.IssueID) - } + issueIDs := container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.IssueID, true + }) ctx, committer, err := db.TxContext(ctx) if err != nil { @@ -1303,7 +1298,7 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error { } } - for issueID := range issueIDs { + for _, issueID := range issueIDs { if _, err := db.Exec(ctx, "UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ? AND `type`=?) WHERE id = ?", issueID, CommentTypeComment, issueID); err != nil { return err diff --git a/models/issues/comment_code.go b/models/issues/comment_code.go index 384a595dd9..f860dacfac 100644 --- a/models/issues/comment_code.go +++ b/models/issues/comment_code.go @@ -74,6 +74,10 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu return nil, err } + if err := comments.LoadAttachments(ctx); err != nil { + return nil, err + } + // Find all reviews by ReviewID reviews := make(map[int64]*Review) ids := make([]int64, 0, len(comments)) @@ -122,7 +126,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu } // FetchCodeCommentsByLine fetches the code comments for a given treePath and line number -func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64, showOutdatedComments bool) ([]*Comment, error) { +func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64, showOutdatedComments bool) (CommentList, error) { opts := FindCommentsOptions{ Type: CommentTypeCode, IssueID: issue.ID, diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 30a437ea50..370b5396e0 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -17,11 +17,9 @@ import ( type CommentList []*Comment func (comments CommentList) getPosterIDs() []int64 { - posterIDs := make(container.Set[int64], len(comments)) - for _, comment := range comments { - posterIDs.Add(comment.PosterID) - } - return posterIDs.Values() + return container.FilterSlice(comments, func(c *Comment) (int64, bool) { + return c.PosterID, c.PosterID > 0 + }) } // LoadPosters loads posters @@ -41,20 +39,10 @@ func (comments CommentList) LoadPosters(ctx context.Context) error { return nil } -func (comments CommentList) getCommentIDs() []int64 { - ids := make([]int64, 0, len(comments)) - for _, comment := range comments { - ids = append(ids, comment.ID) - } - return ids -} - func (comments CommentList) getLabelIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - ids.Add(comment.LabelID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.LabelID, comment.LabelID > 0 + }) } func (comments CommentList) loadLabels(ctx context.Context) error { @@ -98,11 +86,9 @@ func (comments CommentList) loadLabels(ctx context.Context) error { } func (comments CommentList) getMilestoneIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - ids.Add(comment.MilestoneID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.MilestoneID, comment.MilestoneID > 0 + }) } func (comments CommentList) loadMilestones(ctx context.Context) error { @@ -139,11 +125,9 @@ func (comments CommentList) loadMilestones(ctx context.Context) error { } func (comments CommentList) getOldMilestoneIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - ids.Add(comment.OldMilestoneID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.OldMilestoneID, comment.OldMilestoneID > 0 + }) } func (comments CommentList) loadOldMilestones(ctx context.Context) error { @@ -180,11 +164,9 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error { } func (comments CommentList) getAssigneeIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - ids.Add(comment.AssigneeID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.AssigneeID, comment.AssigneeID > 0 + }) } func (comments CommentList) loadAssignees(ctx context.Context) error { @@ -235,14 +217,9 @@ func (comments CommentList) loadAssignees(ctx context.Context) error { // getIssueIDs returns all the issue ids on this comment list which issue hasn't been loaded func (comments CommentList) getIssueIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - if comment.Issue != nil { - continue - } - ids.Add(comment.IssueID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.IssueID, comment.Issue == nil + }) } // Issues returns all the issues of comments @@ -309,14 +286,12 @@ func (comments CommentList) LoadIssues(ctx context.Context) error { } func (comments CommentList) getDependentIssueIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { if comment.DependentIssue != nil { - continue + return 0, false } - ids.Add(comment.DependentIssueID) - } - return ids.Values() + return comment.DependentIssueID, comment.DependentIssueID > 0 + }) } func (comments CommentList) loadDependentIssues(ctx context.Context) error { @@ -369,6 +344,35 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error { return nil } +// getAttachmentCommentIDs only return the comment ids which possibly has attachments +func (comments CommentList) getAttachmentCommentIDs() []int64 { + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.ID, comment.Type.HasAttachmentSupport() + }) +} + +// LoadAttachmentsByIssue loads attachments by issue id +func (comments CommentList) LoadAttachmentsByIssue(ctx context.Context) error { + if len(comments) == 0 { + return nil + } + + attachments := make([]*repo_model.Attachment, 0, len(comments)/2) + if err := db.GetEngine(ctx).Where("issue_id=? AND comment_id>0", comments[0].IssueID).Find(&attachments); err != nil { + return err + } + + commentAttachmentsMap := make(map[int64][]*repo_model.Attachment, len(comments)) + for _, attach := range attachments { + commentAttachmentsMap[attach.CommentID] = append(commentAttachmentsMap[attach.CommentID], attach) + } + + for _, comment := range comments { + comment.Attachments = commentAttachmentsMap[comment.ID] + } + return nil +} + // LoadAttachments loads attachments func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { if len(comments) == 0 { @@ -376,16 +380,15 @@ func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { } attachments := make(map[int64][]*repo_model.Attachment, len(comments)) - commentsIDs := comments.getCommentIDs() + commentsIDs := comments.getAttachmentCommentIDs() left := len(commentsIDs) for left > 0 { limit := db.DefaultMaxInSize if left < limit { limit = left } - rows, err := db.GetEngine(ctx).Table("attachment"). - Join("INNER", "comment", "comment.id = attachment.comment_id"). - In("comment.id", commentsIDs[:limit]). + rows, err := db.GetEngine(ctx). + In("comment_id", commentsIDs[:limit]). Rows(new(repo_model.Attachment)) if err != nil { return err @@ -413,11 +416,9 @@ func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { } func (comments CommentList) getReviewIDs() []int64 { - ids := make(container.Set[int64], len(comments)) - for _, comment := range comments { - ids.Add(comment.ReviewID) - } - return ids.Values() + return container.FilterSlice(comments, func(comment *Comment) (int64, bool) { + return comment.ReviewID, comment.ReviewID > 0 + }) } func (comments CommentList) loadReviews(ctx context.Context) error { diff --git a/models/issues/issue.go b/models/issues/issue.go index dec37ed833..a3214410e1 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -193,20 +193,6 @@ func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool { return issue.Repo.IsTimetrackerEnabled(ctx) } -// GetPullRequest returns the issue pull request -func (issue *Issue) GetPullRequest(ctx context.Context) (pr *PullRequest, err error) { - if !issue.IsPull { - return nil, fmt.Errorf("Issue is not a pull request") - } - - pr, err = GetPullRequestByIssueID(ctx, issue.ID) - if err != nil { - return nil, err - } - pr.Issue = issue - return pr, err -} - // LoadPoster loads poster func (issue *Issue) LoadPoster(ctx context.Context) (err error) { if issue.Poster == nil && issue.PosterID != 0 { diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index a932ac2554..f8ee271a6b 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -21,16 +21,15 @@ type IssueList []*Issue // get the repo IDs to be loaded later, these IDs are for issue.Repo and issue.PullRequest.HeadRepo func (issues IssueList) getRepoIDs() []int64 { - repoIDs := make(container.Set[int64], len(issues)) - for _, issue := range issues { + return container.FilterSlice(issues, func(issue *Issue) (int64, bool) { if issue.Repo == nil { - repoIDs.Add(issue.RepoID) + return issue.RepoID, true } if issue.PullRequest != nil && issue.PullRequest.HeadRepo == nil { - repoIDs.Add(issue.PullRequest.HeadRepoID) + return issue.PullRequest.HeadRepoID, true } - } - return repoIDs.Values() + return 0, false + }) } // LoadRepositories loads issues' all repositories @@ -74,11 +73,9 @@ func (issues IssueList) LoadRepositories(ctx context.Context) (repo_model.Reposi } func (issues IssueList) getPosterIDs() []int64 { - posterIDs := make(container.Set[int64], len(issues)) - for _, issue := range issues { - posterIDs.Add(issue.PosterID) - } - return posterIDs.Values() + return container.FilterSlice(issues, func(issue *Issue) (int64, bool) { + return issue.PosterID, true + }) } func (issues IssueList) loadPosters(ctx context.Context) error { @@ -193,11 +190,9 @@ func (issues IssueList) loadLabels(ctx context.Context) error { } func (issues IssueList) getMilestoneIDs() []int64 { - ids := make(container.Set[int64], len(issues)) - for _, issue := range issues { - ids.Add(issue.MilestoneID) - } - return ids.Values() + return container.FilterSlice(issues, func(issue *Issue) (int64, bool) { + return issue.MilestoneID, true + }) } func (issues IssueList) loadMilestones(ctx context.Context) error { @@ -370,6 +365,9 @@ func (issues IssueList) LoadPullRequests(ctx context.Context) error { for _, issue := range issues { issue.PullRequest = pullRequestMaps[issue.ID] + if issue.PullRequest != nil { + issue.PullRequest.Issue = issue + } } return nil } @@ -388,9 +386,8 @@ func (issues IssueList) LoadAttachments(ctx context.Context) (err error) { if left < limit { limit = left } - rows, err := db.GetEngine(ctx).Table("attachment"). - Join("INNER", "issue", "issue.id = attachment.issue_id"). - In("issue.id", issuesIDs[:limit]). + rows, err := db.GetEngine(ctx). + In("issue_id", issuesIDs[:limit]). Rows(new(repo_model.Attachment)) if err != nil { return err @@ -476,6 +473,16 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) { } trackedTimes := make(map[int64]int64, len(issues)) + reposMap := make(map[int64]*repo_model.Repository, len(issues)) + for _, issue := range issues { + reposMap[issue.RepoID] = issue.Repo + } + repos := repo_model.RepositoryListOfMap(reposMap) + + if err := repos.LoadUnits(ctx); err != nil { + return err + } + ids := make([]int64, 0, len(issues)) for _, issue := range issues { if issue.Repo.IsTimetrackerEnabled(ctx) { @@ -599,3 +606,23 @@ func (issues IssueList) GetApprovalCounts(ctx context.Context) (map[int64][]*Rev return approvalCountMap, nil } + +func (issues IssueList) LoadIsRead(ctx context.Context, userID int64) error { + issueIDs := issues.getIssueIDs() + issueUsers := make([]*IssueUser, 0, len(issueIDs)) + if err := db.GetEngine(ctx).Where("uid =?", userID). + In("issue_id"). + Find(&issueUsers); err != nil { + return err + } + + for _, issueUser := range issueUsers { + for _, issue := range issues { + if issue.ID == issueUser.IssueID { + issue.IsRead = issueUser.IsRead + } + } + } + + return nil +} diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index cc7ffb356a..907a5a17b9 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -49,18 +49,13 @@ func (issue *Issue) ProjectBoardID(ctx context.Context) int64 { // LoadIssuesFromBoard load issues assigned to this board func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) { - issueList := make(IssueList, 0, 10) - - if b.ID > 0 { - issues, err := Issues(ctx, &IssuesOptions{ - ProjectBoardID: b.ID, - ProjectID: b.ProjectID, - SortType: "project-column-sorting", - }) - if err != nil { - return nil, err - } - issueList = issues + issueList, err := Issues(ctx, &IssuesOptions{ + ProjectBoardID: b.ID, + ProjectID: b.ProjectID, + SortType: "project-column-sorting", + }) + if err != nil { + return nil, err } if b.Default { diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go index c5c9cecdb9..921dd9973e 100644 --- a/models/issues/issue_search.go +++ b/models/issues/issue_search.go @@ -21,7 +21,7 @@ import ( // IssuesOptions represents options of an issue. type IssuesOptions struct { //nolint - db.Paginator + Paginator *db.ListOptions RepoIDs []int64 // overwrites RepoCond if the length is not 0 AllPublic bool // include also all public repositories RepoCond builder.Cond @@ -104,23 +104,11 @@ func applyLimit(sess *xorm.Session, opts *IssuesOptions) *xorm.Session { return sess } - // Warning: Do not use GetSkipTake() for *db.ListOptions - // Its implementation could reset the page size with setting.API.MaxResponseItems - if listOptions, ok := opts.Paginator.(*db.ListOptions); ok { - if listOptions.Page >= 0 && listOptions.PageSize > 0 { - var start int - if listOptions.Page == 0 { - start = 0 - } else { - start = (listOptions.Page - 1) * listOptions.PageSize - } - sess.Limit(listOptions.PageSize, start) - } - return sess + start := 0 + if opts.Paginator.Page > 1 { + start = (opts.Paginator.Page - 1) * opts.Paginator.PageSize } - - start, limit := opts.Paginator.GetSkipTake() - sess.Limit(limit, start) + sess.Limit(opts.Paginator.PageSize, start) return sess } @@ -393,7 +381,7 @@ func applyReviewRequestedCondition(sess *xorm.Session, reviewRequestedID int64) func applyReviewedCondition(sess *xorm.Session, reviewedID int64) *xorm.Session { // Query for pull requests where you are a reviewer or commenter, excluding - // any pull requests already returned by the the review requested filter. + // any pull requests already returned by the review requested filter. notPoster := builder.Neq{"issue.poster_id": reviewedID} reviewed := builder.In("issue.id", builder. Select("issue_id"). diff --git a/models/issues/issue_stats.go b/models/issues/issue_stats.go index 32c5674fc9..39326616f8 100644 --- a/models/issues/issue_stats.go +++ b/models/issues/issue_stats.go @@ -68,13 +68,17 @@ func CountIssuesByRepo(ctx context.Context, opts *IssuesOptions) (map[int64]int6 } // CountIssues number return of issues by given conditions. -func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) { +func CountIssues(ctx context.Context, opts *IssuesOptions, otherConds ...builder.Cond) (int64, error) { sess := db.GetEngine(ctx). Select("COUNT(issue.id) AS count"). Table("issue"). Join("INNER", "repository", "`issue`.repo_id = `repository`.id") applyConditions(sess, opts) + for _, cond := range otherConds { + sess.And(cond) + } + return sess.Count() } diff --git a/models/issues/label.go b/models/issues/label.go index a79c22575b..565e4ea06d 100644 --- a/models/issues/label.go +++ b/models/issues/label.go @@ -118,12 +118,17 @@ func (l *Label) CalOpenIssues() { func (l *Label) SetArchived(isArchived bool) { if !isArchived { l.ArchivedUnix = timeutil.TimeStamp(0) - } else if isArchived && l.ArchivedUnix.IsZero() { + } else if isArchived && !l.IsArchived() { // Only change the date when it is newly archived. l.ArchivedUnix = timeutil.TimeStampNow() } } +// IsArchived returns true if label is an archived +func (l *Label) IsArchived() bool { + return !l.ArchivedUnix.IsZero() +} + // CalOpenOrgIssues calculates the open issues of a label for a specific repo func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) { counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ @@ -168,11 +173,6 @@ func (l *Label) BelongsToOrg() bool { return l.OrgID > 0 } -// IsArchived returns true if label is an archived -func (l *Label) IsArchived() bool { - return l.ArchivedUnix > 0 -} - // BelongsToRepo returns true if label is a repository label func (l *Label) BelongsToRepo() bool { return l.RepoID > 0 diff --git a/models/issues/pull.go b/models/issues/pull.go index 4021e10b7b..4ea439b8b9 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -19,7 +19,6 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" @@ -884,77 +883,6 @@ func MergeBlockedByOutdatedBranch(protectBranch *git_model.ProtectedBranch, pr * return protectBranch.BlockOnOutdatedBranch && pr.CommitsBehind > 0 } -func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error { - files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} - - if pr.IsWorkInProgress(ctx) { - return nil - } - - if err := pr.LoadBaseRepo(ctx); err != nil { - return err - } - - repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) - if err != nil { - return err - } - defer repo.Close() - - commit, err := repo.GetBranchCommit(pr.BaseRepo.DefaultBranch) - if err != nil { - return err - } - - var data string - for _, file := range files { - if blob, err := commit.GetBlobByPath(file); err == nil { - data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) - if err == nil { - break - } - } - } - - rules, _ := GetCodeOwnersFromContent(ctx, data) - changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName()) - if err != nil { - return err - } - - uniqUsers := make(map[int64]*user_model.User) - uniqTeams := make(map[string]*org_model.Team) - for _, rule := range rules { - for _, f := range changedFiles { - if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) { - for _, u := range rule.Users { - uniqUsers[u.ID] = u - } - for _, t := range rule.Teams { - uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t - } - } - } - } - - for _, u := range uniqUsers { - if u.ID != pull.Poster.ID { - if _, err := AddReviewRequest(ctx, pull, u, pull.Poster); err != nil { - log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - } - for _, t := range uniqTeams { - if _, err := AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil { - log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - - return nil -} - // GetCodeOwnersFromContent returns the code owners configuration // Return empty slice if files missing // Return warning messages on parsing errors diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index c209386e2e..b5557cad06 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -11,7 +11,6 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" @@ -23,7 +22,7 @@ type PullRequestsOptions struct { db.ListOptions State string SortType string - Labels []string + Labels []int64 MilestoneID int64 } @@ -36,11 +35,9 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR sess.And("issue.is_closed=?", opts.State == "closed") } - if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil { - return nil, err - } else if len(labelIDs) > 0 { + if len(opts.Labels) > 0 { sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id"). - In("issue_label.label_id", labelIDs) + In("issue_label.label_id", opts.Labels) } if opts.MilestoneID > 0 { @@ -65,11 +62,13 @@ func CanMaintainerWriteToBranch(ctx context.Context, p access_model.Permission, return true } - if len(p.Units) < 1 { + // the code below depends on units to get the repository ID, not ideal but just keep it for now + firstUnitRepoID := p.GetFirstUnitRepoID() + if firstUnitRepoID == 0 { return false } - prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, p.Units[0].RepoID, branch) + prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, firstUnitRepoID, branch) if err != nil { return false } @@ -212,3 +211,12 @@ func HasMergedPullRequestInRepo(ctx context.Context, repoID, posterID int64) (bo Limit(1). Get(new(Issue)) } + +// GetPullRequestByIssueIDs returns all pull requests by issue ids +func GetPullRequestByIssueIDs(ctx context.Context, issueIDs []int64) (PullRequestList, error) { + prs := make([]*PullRequest, 0, len(issueIDs)) + return prs, db.GetEngine(ctx). + Where("issue_id > 0"). + In("issue_id", issueIDs). + Find(&prs) +} diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go index 3a30b2f3de..675c90527d 100644 --- a/models/issues/pull_test.go +++ b/models/issues/pull_test.go @@ -66,7 +66,6 @@ func TestPullRequestsNewest(t *testing.T) { }, State: "open", SortType: "newest", - Labels: []string{}, }) assert.NoError(t, err) assert.EqualValues(t, 3, count) @@ -113,7 +112,6 @@ func TestPullRequestsOldest(t *testing.T) { }, State: "open", SortType: "oldest", - Labels: []string{}, }) assert.NoError(t, err) assert.EqualValues(t, 3, count) diff --git a/models/issues/reaction.go b/models/issues/reaction.go index d5448636fe..eb7faefc79 100644 --- a/models/issues/reaction.go +++ b/models/issues/reaction.go @@ -305,14 +305,12 @@ func (list ReactionList) GroupByType() map[string]ReactionList { } func (list ReactionList) getUserIDs() []int64 { - userIDs := make(container.Set[int64], len(list)) - for _, reaction := range list { + return container.FilterSlice(list, func(reaction *Reaction) (int64, bool) { if reaction.OriginalAuthor != "" { - continue + return 0, false } - userIDs.Add(reaction.UserID) - } - return userIDs.Values() + return reaction.UserID, true + }) } func valuesUser(m map[int64]*user_model.User) []*user_model.User { diff --git a/models/issues/review.go b/models/issues/review.go index 049cbf0062..480c08a25e 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -66,6 +66,23 @@ func (err ErrNotValidReviewRequest) Unwrap() error { return util.ErrInvalidArgument } +// ErrReviewRequestOnClosedPR represents an error when an user tries to request a re-review on a closed or merged PR. +type ErrReviewRequestOnClosedPR struct{} + +// IsErrReviewRequestOnClosedPR checks if an error is an ErrReviewRequestOnClosedPR. +func IsErrReviewRequestOnClosedPR(err error) bool { + _, ok := err.(ErrReviewRequestOnClosedPR) + return ok +} + +func (err ErrReviewRequestOnClosedPR) Error() string { + return "cannot request a re-review on a closed or merged PR" +} + +func (err ErrReviewRequestOnClosedPR) Unwrap() error { + return util.ErrPermissionDenied +} + // ReviewType defines the sort of feedback a review gives type ReviewType int @@ -240,11 +257,11 @@ type CreateReviewOptions struct { // IsOfficialReviewer check if at least one of the provided reviewers can make official reviews in issue (counts towards required approvals) func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewer *user_model.User) (bool, error) { - pr, err := GetPullRequestByIssueID(ctx, issue.ID) - if err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { return false, err } + pr := issue.PullRequest rule, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch) if err != nil { return false, err @@ -272,11 +289,10 @@ func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewer *user_model. // IsOfficialReviewerTeam check if reviewer in this team can make official reviews in issue (counts towards required approvals) func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organization.Team) (bool, error) { - pr, err := GetPullRequestByIssueID(ctx, issue.ID) - if err != nil { + if err := issue.LoadPullRequest(ctx); err != nil { return false, err } - pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch) + pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, issue.PullRequest.BaseRepoID, issue.PullRequest.BaseBranch) if err != nil { return false, err } @@ -330,11 +346,9 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error return nil, err } } - } else if opts.ReviewerTeam != nil { review.Type = ReviewTypeRequest review.ReviewerTeamID = opts.ReviewerTeam.ID - } else { return nil, fmt.Errorf("provide either reviewer or reviewer team") } @@ -713,9 +727,24 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo return nil, err } - // skip it when reviewer hase been request to review - if review != nil && review.Type == ReviewTypeRequest { - return nil, nil + if review != nil { + // skip it when reviewer hase been request to review + if review.Type == ReviewTypeRequest { + return nil, committer.Commit() // still commit the transaction, or committer.Close() will rollback it, even if it's a reused transaction. + } + + if issue.IsClosed { + return nil, ErrReviewRequestOnClosedPR{} + } + + if issue.IsPull { + if err := issue.LoadPullRequest(ctx); err != nil { + return nil, err + } + if issue.PullRequest.HasMerged { + return nil, ErrReviewRequestOnClosedPR{} + } + } } // if the reviewer is an official reviewer, diff --git a/models/issues/review_list.go b/models/issues/review_list.go index ec6cb07988..7b8c3d319c 100644 --- a/models/issues/review_list.go +++ b/models/issues/review_list.go @@ -38,12 +38,11 @@ func (reviews ReviewList) LoadReviewers(ctx context.Context) error { } func (reviews ReviewList) LoadIssues(ctx context.Context) error { - issueIDs := container.Set[int64]{} - for i := 0; i < len(reviews); i++ { - issueIDs.Add(reviews[i].IssueID) - } + issueIDs := container.FilterSlice(reviews, func(review *Review) (int64, bool) { + return review.IssueID, true + }) - issues, err := GetIssuesByIDs(ctx, issueIDs.Values()) + issues, err := GetIssuesByIDs(ctx, issueIDs) if err != nil { return err } diff --git a/models/issues/review_test.go b/models/issues/review_test.go index 1868cb1bfa..ac1b84adeb 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -288,3 +288,33 @@ func TestDeleteDismissedReview(t *testing.T) { assert.NoError(t, issues_model.DeleteReview(db.DefaultContext, review)) unittest.AssertNotExistsBean(t, &issues_model.Comment{ID: comment.ID}) } + +func TestAddReviewRequest(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) + assert.NoError(t, pull.LoadIssue(db.DefaultContext)) + issue := pull.Issue + assert.NoError(t, issue.LoadRepo(db.DefaultContext)) + reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + _, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + Issue: issue, + Reviewer: reviewer, + Type: issues_model.ReviewTypeReject, + }) + + assert.NoError(t, err) + pull.HasMerged = false + assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) + issue.IsClosed = true + _, err = issues_model.AddReviewRequest(db.DefaultContext, issue, reviewer, &user_model.User{}) + assert.Error(t, err) + assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err)) + + pull.HasMerged = true + assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) + issue.IsClosed = false + _, err = issues_model.AddReviewRequest(db.DefaultContext, issue, reviewer, &user_model.User{}) + assert.Error(t, err) + assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err)) +} diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go index 51351cc7d3..eb1c44a79e 100644 --- a/models/migrations/base/db.go +++ b/models/migrations/base/db.go @@ -177,7 +177,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err) return err } - case setting.Database.Type.IsMySQL(): // MySQL will drop all the constraints on the old table if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { @@ -228,7 +227,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { return err } sequenceMap[sequence] = sequenceData - } // CASCADE causes postgres to drop all the constraints on the old table @@ -293,9 +291,7 @@ func RecreateTable(sess *xorm.Session, bean any) error { return err } } - } - case setting.Database.Type.IsMSSQL(): // MSSQL will drop all the constraints on the old table if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { @@ -308,7 +304,6 @@ func RecreateTable(sess *xorm.Session, bean any) error { log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) return err } - default: log.Fatal("Unrecognized DB") } diff --git a/models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/o_auth2_application.yml b/models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml similarity index 100% rename from models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/o_auth2_application.yml rename to models/migrations/fixtures/Test_AddConfidentialClientColumnToOAuth2ApplicationTable/oauth2_application.yml diff --git a/models/migrations/fixtures/Test_AddUniqueIndexForProjectIssue/project_issue.yml b/models/migrations/fixtures/Test_AddUniqueIndexForProjectIssue/project_issue.yml new file mode 100644 index 0000000000..6feaeb39f0 --- /dev/null +++ b/models/migrations/fixtures/Test_AddUniqueIndexForProjectIssue/project_issue.yml @@ -0,0 +1,9 @@ +- + id: 1 + project_id: 1 + issue_id: 1 + +- + id: 2 + project_id: 1 + issue_id: 1 diff --git a/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project.yml b/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project.yml new file mode 100644 index 0000000000..2450d20beb --- /dev/null +++ b/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project.yml @@ -0,0 +1,23 @@ +- + id: 1 + title: project without default column + owner_id: 2 + repo_id: 0 + is_closed: false + creator_id: 2 + board_type: 1 + type: 2 + created_unix: 1688973000 + updated_unix: 1688973000 + +- + id: 2 + title: project with multiple default columns + owner_id: 2 + repo_id: 0 + is_closed: false + creator_id: 2 + board_type: 1 + type: 2 + created_unix: 1688973000 + updated_unix: 1688973000 diff --git a/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project_board.yml b/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project_board.yml new file mode 100644 index 0000000000..2e1b1c7eee --- /dev/null +++ b/models/migrations/fixtures/Test_CheckProjectColumnsConsistency/project_board.yml @@ -0,0 +1,26 @@ +- + id: 1 + project_id: 1 + title: Done + creator_id: 2 + default: false + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 2 + project_id: 2 + title: Backlog + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 + +- + id: 3 + project_id: 2 + title: Uncategorized + creator_id: 2 + default: true + created_unix: 1588117528 + updated_unix: 1588117528 diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index ce77432db4..220d8c2331 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/models/migrations/v1_20" "code.gitea.io/gitea/models/migrations/v1_21" "code.gitea.io/gitea/models/migrations/v1_22" + "code.gitea.io/gitea/models/migrations/v1_23" "code.gitea.io/gitea/models/migrations/v1_6" "code.gitea.io/gitea/models/migrations/v1_7" "code.gitea.io/gitea/models/migrations/v1_8" @@ -566,6 +567,25 @@ var migrations = []Migration{ NewMigration("Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch), // v290 -> v291 NewMigration("Add PayloadVersion to HookTask", v1_22.AddPayloadVersionToHookTaskTable), + // v291 -> v292 + NewMigration("Add Index to attachment.comment_id", v1_22.AddCommentIDIndexofAttachment), + // v292 -> v293 + NewMigration("Ensure every project has exactly one default column - No Op", noopMigration), + // v293 -> v294 + NewMigration("Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency), + + // Gitea 1.22.0 ends at 294 + + // v294 -> v295 + NewMigration("Add unique index for project issue table", v1_23.AddUniqueIndexForProjectIssue), + // v295 -> v296 + NewMigration("Add commit status summary table", v1_23.AddCommitStatusSummary), + // v296 -> v297 + NewMigration("Add missing field of commit status summary table", v1_23.AddCommitStatusSummary2), + // v297 -> v298 + NewMigration("Add everyone_access_mode for repo_unit", v1_23.AddRepoUnitEveryoneAccessMode), + // v298 -> v299 + NewMigration("Drop wrongly created table o_auth2_application", v1_23.DropWronglyCreatedTable), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_11/v111.go b/models/migrations/v1_11/v111.go index d757acb7d2..ff108479a9 100644 --- a/models/migrations/v1_11/v111.go +++ b/models/migrations/v1_11/v111.go @@ -262,7 +262,6 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { for _, u := range units { var found bool for _, team := range teams { - var teamU []*TeamUnit var unitEnabled bool err = sess.Where("team_id = ?", team.ID).Find(&teamU) @@ -331,12 +330,11 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { } if !protectedBranch.EnableApprovalsWhitelist { - perm, err := getUserRepoPermission(sess, baseRepo, reviewer) if err != nil { return false, err } - if perm.UnitsMode == nil { + if len(perm.UnitsMode) == 0 { for _, u := range perm.Units { if u.Type == UnitTypeCode { return AccessModeWrite <= perm.AccessMode, nil diff --git a/models/migrations/v1_16/v210.go b/models/migrations/v1_16/v210.go index 533bb4bf80..51b7d81e99 100644 --- a/models/migrations/v1_16/v210.go +++ b/models/migrations/v1_16/v210.go @@ -43,11 +43,6 @@ func RemigrateU2FCredentials(x *xorm.Engine) error { if err != nil { return err } - case schemas.ORACLE: - _, err := x.Exec("ALTER TABLE webauthn_credential MODIFY credential_id VARCHAR(410)") - if err != nil { - return err - } case schemas.MSSQL: // This column has an index on it. I could write all of the code to attempt to change the index OR // I could just use recreate table. diff --git a/models/migrations/v1_18/v230.go b/models/migrations/v1_18/v230.go index cf94926be1..ea5b4d02e1 100644 --- a/models/migrations/v1_18/v230.go +++ b/models/migrations/v1_18/v230.go @@ -9,9 +9,9 @@ import ( // AddConfidentialColumnToOAuth2ApplicationTable: add ConfidentialClient column, setting existing rows to true func AddConfidentialClientColumnToOAuth2ApplicationTable(x *xorm.Engine) error { - type OAuth2Application struct { + type oauth2Application struct { + ID int64 ConfidentialClient bool `xorm:"NOT NULL DEFAULT TRUE"` } - - return x.Sync(new(OAuth2Application)) + return x.Sync(new(oauth2Application)) } diff --git a/models/migrations/v1_18/v230_test.go b/models/migrations/v1_18/v230_test.go index 308f3a5023..40db4c2ffe 100644 --- a/models/migrations/v1_18/v230_test.go +++ b/models/migrations/v1_18/v230_test.go @@ -13,12 +13,12 @@ import ( func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { // premigration - type OAuth2Application struct { + type oauth2Application struct { ID int64 } // Prepare and load the testing database - x, deferable := base.PrepareTestEnv(t, 0, new(OAuth2Application)) + x, deferable := base.PrepareTestEnv(t, 0, new(oauth2Application)) defer deferable() if x == nil || t.Failed() { return @@ -36,7 +36,7 @@ func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) { } got := []ExpectedOAuth2Application{} - if err := x.Table("o_auth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) { + if err := x.Table("oauth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) { return } diff --git a/models/migrations/v1_20/v250.go b/models/migrations/v1_20/v250.go index a09957b291..86388ef0b8 100644 --- a/models/migrations/v1_20/v250.go +++ b/models/migrations/v1_20/v250.go @@ -104,7 +104,7 @@ func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { // Convert to new metadata format - new := &MetadataNew{ + newMetadata := &MetadataNew{ Type: old.Type, IsTagged: old.IsTagged, Platform: old.Platform, @@ -119,7 +119,7 @@ func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { Manifests: manifests, } - metadataJSON, err := json.Marshal(new) + metadataJSON, err := json.Marshal(newMetadata) if err != nil { return err } diff --git a/models/migrations/v1_22/v286.go b/models/migrations/v1_22/v286.go index fbbd87344f..f46d494dfe 100644 --- a/models/migrations/v1_22/v286.go +++ b/models/migrations/v1_22/v286.go @@ -53,7 +53,7 @@ func expandHashReferencesToSha256(x *xorm.Engine) error { if setting.Database.Type.IsMySQL() { _, err = db.Exec(fmt.Sprintf("ALTER TABLE `%s` MODIFY COLUMN `%s` VARCHAR(64)", alts[0], alts[1])) } else if setting.Database.Type.IsMSSQL() { - _, err = db.Exec(fmt.Sprintf("ALTER TABLE [%s] ALTER COLUMN [%s] VARCHAR(64)", alts[0], alts[1])) + _, err = db.Exec(fmt.Sprintf("ALTER TABLE [%s] ALTER COLUMN [%s] NVARCHAR(64)", alts[0], alts[1])) } else { _, err = db.Exec(fmt.Sprintf("ALTER TABLE `%s` ALTER COLUMN `%s` TYPE VARCHAR(64)", alts[0], alts[1])) } diff --git a/models/migrations/v1_22/v291.go b/models/migrations/v1_22/v291.go new file mode 100644 index 0000000000..0bfffe5d05 --- /dev/null +++ b/models/migrations/v1_22/v291.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import "xorm.io/xorm" + +func AddCommentIDIndexofAttachment(x *xorm.Engine) error { + type Attachment struct { + CommentID int64 `xorm:"INDEX"` + } + + return x.Sync(&Attachment{}) +} diff --git a/models/migrations/v1_22/v292.go b/models/migrations/v1_22/v292.go new file mode 100644 index 0000000000..beca556aee --- /dev/null +++ b/models/migrations/v1_22/v292.go @@ -0,0 +1,9 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +// NOTE: noop the original migration has bug which some projects will be skip, so +// these projects will have no default board. +// So that this migration will be skipped and go to v293.go +// This file is a placeholder so that readers can know what happened diff --git a/models/migrations/v1_22/v293.go b/models/migrations/v1_22/v293.go new file mode 100644 index 0000000000..53cc719294 --- /dev/null +++ b/models/migrations/v1_22/v293.go @@ -0,0 +1,108 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/xorm" +) + +// CheckProjectColumnsConsistency ensures there is exactly one default board per project present +func CheckProjectColumnsConsistency(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + + limit := setting.Database.IterateBufferSize + if limit <= 0 { + limit = 50 + } + + type Project struct { + ID int64 + CreatorID int64 + BoardID int64 + } + + type ProjectBoard struct { + ID int64 `xorm:"pk autoincr"` + Title string + Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board + Sorting int8 `xorm:"NOT NULL DEFAULT 0"` + Color string `xorm:"VARCHAR(7)"` + + ProjectID int64 `xorm:"INDEX NOT NULL"` + CreatorID int64 `xorm:"NOT NULL"` + + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + } + + for { + if err := sess.Begin(); err != nil { + return err + } + + // all these projects without defaults will be fixed in the same loop, so + // we just need to always get projects without defaults until no such project + var projects []*Project + if err := sess.Select("project.id as id, project.creator_id, project_board.id as board_id"). + Join("LEFT", "project_board", "project_board.project_id = project.id AND project_board.`default`=?", true). + Where("project_board.id is NULL OR project_board.id = 0"). + Limit(limit). + Find(&projects); err != nil { + return err + } + + for _, p := range projects { + if _, err := sess.Insert(ProjectBoard{ + ProjectID: p.ID, + Default: true, + Title: "Uncategorized", + CreatorID: p.CreatorID, + }); err != nil { + return err + } + } + if err := sess.Commit(); err != nil { + return err + } + + if len(projects) == 0 { + break + } + } + sess.Close() + + return removeDuplicatedBoardDefault(x) +} + +func removeDuplicatedBoardDefault(x *xorm.Engine) error { + type ProjectInfo struct { + ProjectID int64 + DefaultNum int + } + var projects []ProjectInfo + if err := x.Select("project_id, count(*) AS default_num"). + Table("project_board"). + Where("`default` = ?", true). + GroupBy("project_id"). + Having("count(*) > 1"). + Find(&projects); err != nil { + return err + } + + for _, project := range projects { + if _, err := x.Where("project_id=?", project.ProjectID). + Table("project_board"). + Limit(project.DefaultNum - 1). + Update(map[string]bool{ + "`default`": false, + }); err != nil { + return err + } + } + return nil +} diff --git a/models/migrations/v1_22/v293_test.go b/models/migrations/v1_22/v293_test.go new file mode 100644 index 0000000000..ccc92f39a6 --- /dev/null +++ b/models/migrations/v1_22/v293_test.go @@ -0,0 +1,44 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/migrations/base" + "code.gitea.io/gitea/models/project" + + "github.com/stretchr/testify/assert" +) + +func Test_CheckProjectColumnsConsistency(t *testing.T) { + // Prepare and load the testing database + x, deferable := base.PrepareTestEnv(t, 0, new(project.Project), new(project.Board)) + defer deferable() + if x == nil || t.Failed() { + return + } + + assert.NoError(t, CheckProjectColumnsConsistency(x)) + + // check if default board was added + var defaultBoard project.Board + has, err := x.Where("project_id=? AND `default` = ?", 1, true).Get(&defaultBoard) + assert.NoError(t, err) + assert.True(t, has) + assert.Equal(t, int64(1), defaultBoard.ProjectID) + assert.True(t, defaultBoard.Default) + + // check if multiple defaults, previous were removed and last will be kept + expectDefaultBoard, err := project.GetBoard(db.DefaultContext, 2) + assert.NoError(t, err) + assert.Equal(t, int64(2), expectDefaultBoard.ProjectID) + assert.False(t, expectDefaultBoard.Default) + + expectNonDefaultBoard, err := project.GetBoard(db.DefaultContext, 3) + assert.NoError(t, err) + assert.Equal(t, int64(2), expectNonDefaultBoard.ProjectID) + assert.True(t, expectNonDefaultBoard.Default) +} diff --git a/models/migrations/v1_23/main_test.go b/models/migrations/v1_23/main_test.go new file mode 100644 index 0000000000..b7948bd4dd --- /dev/null +++ b/models/migrations/v1_23/main_test.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v1_23/v294.go b/models/migrations/v1_23/v294.go new file mode 100644 index 0000000000..f2a54f6d23 --- /dev/null +++ b/models/migrations/v1_23/v294.go @@ -0,0 +1,53 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import ( + "fmt" + + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +// AddUniqueIndexForProjectIssue adds unique indexes for project issue table +func AddUniqueIndexForProjectIssue(x *xorm.Engine) error { + // remove possible duplicated records in table project_issue + type result struct { + IssueID int64 + ProjectID int64 + Cnt int + } + var results []result + if err := x.Select("issue_id, project_id, count(*) as cnt"). + Table("project_issue"). + GroupBy("issue_id, project_id"). + Having("count(*) > 1"). + Find(&results); err != nil { + return err + } + for _, r := range results { + if x.Dialect().URI().DBType == schemas.MSSQL { + if _, err := x.Exec(fmt.Sprintf("delete from project_issue where id in (SELECT top %d id FROM project_issue WHERE issue_id = ? and project_id = ?)", r.Cnt-1), r.IssueID, r.ProjectID); err != nil { + return err + } + } else { + var ids []int64 + if err := x.SQL("SELECT id FROM project_issue WHERE issue_id = ? and project_id = ? limit ?", r.IssueID, r.ProjectID, r.Cnt-1).Find(&ids); err != nil { + return err + } + if _, err := x.Table("project_issue").In("id", ids).Delete(); err != nil { + return err + } + } + } + + // add unique index for project_issue table + type ProjectIssue struct { //revive:disable-line:exported + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"INDEX unique(s)"` + ProjectID int64 `xorm:"INDEX unique(s)"` + } + + return x.Sync(new(ProjectIssue)) +} diff --git a/models/migrations/v1_23/v294_test.go b/models/migrations/v1_23/v294_test.go new file mode 100644 index 0000000000..d9a44ad866 --- /dev/null +++ b/models/migrations/v1_23/v294_test.go @@ -0,0 +1,52 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import ( + "slices" + "testing" + + "code.gitea.io/gitea/models/migrations/base" + + "github.com/stretchr/testify/assert" + "xorm.io/xorm/schemas" +) + +func Test_AddUniqueIndexForProjectIssue(t *testing.T) { + type ProjectIssue struct { //revive:disable-line:exported + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"INDEX"` + ProjectID int64 `xorm:"INDEX"` + } + + // Prepare and load the testing database + x, deferable := base.PrepareTestEnv(t, 0, new(ProjectIssue)) + defer deferable() + if x == nil || t.Failed() { + return + } + + cnt, err := x.Table("project_issue").Where("project_id=1 AND issue_id=1").Count() + assert.NoError(t, err) + assert.EqualValues(t, 2, cnt) + + assert.NoError(t, AddUniqueIndexForProjectIssue(x)) + + cnt, err = x.Table("project_issue").Where("project_id=1 AND issue_id=1").Count() + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) + + tables, err := x.DBMetas() + assert.NoError(t, err) + assert.EqualValues(t, 1, len(tables)) + found := false + for _, index := range tables[0].Indexes { + if index.Type == schemas.UniqueType { + found = true + slices.Equal(index.Cols, []string{"project_id", "issue_id"}) + break + } + } + assert.True(t, found) +} diff --git a/models/migrations/v1_23/v295.go b/models/migrations/v1_23/v295.go new file mode 100644 index 0000000000..9a2003cfc1 --- /dev/null +++ b/models/migrations/v1_23/v295.go @@ -0,0 +1,18 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import "xorm.io/xorm" + +func AddCommitStatusSummary(x *xorm.Engine) error { + type CommitStatusSummary struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX UNIQUE(repo_id_sha)"` + SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_id_sha)"` + State string `xorm:"VARCHAR(7) NOT NULL"` + } + // there is no migrations because if there is no data on this table, it will fall back to get data + // from commit status + return x.Sync2(new(CommitStatusSummary)) +} diff --git a/models/migrations/v1_23/v296.go b/models/migrations/v1_23/v296.go new file mode 100644 index 0000000000..495ae2ab23 --- /dev/null +++ b/models/migrations/v1_23/v296.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import "xorm.io/xorm" + +func AddCommitStatusSummary2(x *xorm.Engine) error { + type CommitStatusSummary struct { + ID int64 `xorm:"pk autoincr"` + TargetURL string `xorm:"TEXT"` + } + // there is no migrations because if there is no data on this table, it will fall back to get data + // from commit status + return x.Sync(new(CommitStatusSummary)) +} diff --git a/models/migrations/v1_23/v297.go b/models/migrations/v1_23/v297.go new file mode 100644 index 0000000000..e79f04cf9c --- /dev/null +++ b/models/migrations/v1_23/v297.go @@ -0,0 +1,17 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import ( + "code.gitea.io/gitea/models/perm" + + "xorm.io/xorm" +) + +func AddRepoUnitEveryoneAccessMode(x *xorm.Engine) error { + type RepoUnit struct { //revive:disable-line:exported + EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"` + } + return x.Sync(&RepoUnit{}) +} diff --git a/models/migrations/v1_23/v298.go b/models/migrations/v1_23/v298.go new file mode 100644 index 0000000000..8761a05d3d --- /dev/null +++ b/models/migrations/v1_23/v298.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import "xorm.io/xorm" + +func DropWronglyCreatedTable(x *xorm.Engine) error { + return x.DropTables("o_auth2_application") +} diff --git a/models/migrations/v1_6/v71.go b/models/migrations/v1_6/v71.go index 4e50ca9219..586187228b 100644 --- a/models/migrations/v1_6/v71.go +++ b/models/migrations/v1_6/v71.go @@ -61,7 +61,6 @@ func AddScratchHash(x *xorm.Engine) error { if _, err := sess.ID(tfa.ID).Cols("scratch_salt, scratch_hash").Update(tfa); err != nil { return fmt.Errorf("couldn't add in scratch_hash and scratch_salt: %w", err) } - } } diff --git a/models/migrations/v1_9/v85.go b/models/migrations/v1_9/v85.go index 9419ee1aae..a23d7c5d6e 100644 --- a/models/migrations/v1_9/v85.go +++ b/models/migrations/v1_9/v85.go @@ -81,7 +81,6 @@ func HashAppToken(x *xorm.Engine) error { if _, err := sess.ID(token.ID).Cols("token_hash, token_salt, token_last_eight, sha1").Update(token); err != nil { return fmt.Errorf("couldn't add in sha1, token_hash, token_salt and token_last_eight: %w", err) } - } } diff --git a/models/org_team.go b/models/org_team.go index aecf0d80fd..b6908478c7 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -118,7 +118,7 @@ func removeAllRepositories(ctx context.Context, t *organization.Team) (err error // Remove watches from all users and now unaccessible repos for _, user := range t.Members { - has, err := access_model.HasAccess(ctx, user.ID, repo) + has, err := access_model.HasAnyUnitAccess(ctx, user.ID, repo) if err != nil { return err } else if has { @@ -544,7 +544,7 @@ func ReconsiderRepoIssuesAssignee(ctx context.Context, repo *repo_model.Reposito } func ReconsiderWatches(ctx context.Context, repo *repo_model.Repository, user *user_model.User) error { - if has, err := access_model.HasAccess(ctx, user.ID, repo); err != nil || has { + if has, err := access_model.HasAnyUnitAccess(ctx, user.ID, repo); err != nil || has { return err } if err := repo_model.WatchRepo(ctx, user, repo, false); err != nil { diff --git a/models/organization/org.go b/models/organization/org.go index a3082e9ac7..b33d15d29c 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -9,6 +9,7 @@ import ( "fmt" "strings" + actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" @@ -319,8 +320,9 @@ func CreateOrganization(ctx context.Context, org *Organization, owner *user_mode // Add initial creator to organization and owner team. if err = db.Insert(ctx, &OrgUser{ - UID: owner.ID, - OrgID: org.ID, + UID: owner.ID, + OrgID: org.ID, + IsPublic: setting.Service.DefaultOrgMemberVisible, }); err != nil { return fmt.Errorf("insert org-user relation: %w", err) } @@ -401,6 +403,8 @@ func DeleteOrganization(ctx context.Context, org *Organization) error { &TeamInvite{OrgID: org.ID}, &secret_model.Secret{OwnerID: org.ID}, &user_model.Blocking{BlockerID: org.ID}, + &actions_model.ActionRunner{OwnerID: org.ID}, + &actions_model.ActionRunnerToken{OwnerID: org.ID}, ); err != nil { return fmt.Errorf("DeleteBeans: %w", err) } diff --git a/models/organization/team.go b/models/organization/team.go index 17db11c42d..fb7f0c0493 100644 --- a/models/organization/team.go +++ b/models/organization/team.go @@ -130,11 +130,11 @@ func (t *Team) GetUnitsMap() map[string]string { m := make(map[string]string) if t.AccessMode >= perm.AccessModeAdmin { for _, u := range unit.Units { - m[u.NameKey] = t.AccessMode.String() + m[u.NameKey] = t.AccessMode.ToString() } } else { for _, u := range t.Units { - m[u.Unit().NameKey] = u.AccessMode.String() + m[u.Unit().NameKey] = u.AccessMode.ToString() } } return m @@ -174,23 +174,27 @@ func (t *Team) LoadMembers(ctx context.Context) (err error) { return err } -// UnitEnabled returns if the team has the given unit type enabled +// UnitEnabled returns true if the team has the given unit type enabled func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool { return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone } -// UnitAccessMode returns if the team has the given unit type enabled +// UnitAccessMode returns the access mode for the given unit type, "none" for non-existent units func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode { + accessMode, _ := t.UnitAccessModeEx(ctx, tp) + return accessMode +} + +func (t *Team) UnitAccessModeEx(ctx context.Context, tp unit.Type) (accessMode perm.AccessMode, exist bool) { if err := t.LoadUnits(ctx); err != nil { log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error()) } - - for _, unit := range t.Units { - if unit.Type == tp { - return unit.AccessMode + for _, u := range t.Units { + if u.Type == tp { + return u.AccessMode, true } } - return perm.AccessModeNone + return perm.AccessModeNone, false } // IsUsableTeamName tests if a name could be as team name @@ -222,9 +226,8 @@ func GetTeamIDsByNames(ctx context.Context, orgID int64, names []string, ignoreN if err != nil { if ignoreNonExistent { continue - } else { - return nil, err } + return nil, err } ids = append(ids, u.ID) } diff --git a/models/packages/package_version.go b/models/packages/package_version.go index 505dbaa0a5..278e8e3a86 100644 --- a/models/packages/package_version.go +++ b/models/packages/package_version.go @@ -287,9 +287,10 @@ func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) { // SearchVersions gets all versions of packages matching the search options func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) { sess := db.GetEngine(ctx). - Where(opts.ToConds()). + Select("package_version.*"). Table("package_version"). - Join("INNER", "package", "package.id = package_version.package_id") + Join("INNER", "package", "package.id = package_version.package_id"). + Where(opts.ToConds()) opts.configureOrderBy(sess) @@ -304,19 +305,18 @@ func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*Package // SearchLatestVersions gets the latest version of every package matching the search options func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) { - cond := opts.ToConds(). - And(builder.Expr("pv2.id IS NULL")) - - joinCond := builder.Expr("package_version.package_id = pv2.package_id AND (package_version.created_unix < pv2.created_unix OR (package_version.created_unix = pv2.created_unix AND package_version.id < pv2.id))") - if opts.IsInternal.Has() { - joinCond = joinCond.And(builder.Eq{"pv2.is_internal": opts.IsInternal.Value()}) - } + in := builder. + Select("MAX(package_version.id)"). + From("package_version"). + InnerJoin("package", "package.id = package_version.package_id"). + Where(opts.ToConds()). + GroupBy("package_version.package_id") sess := db.GetEngine(ctx). + Select("package_version.*"). Table("package_version"). - Join("LEFT", "package_version pv2", joinCond). Join("INNER", "package", "package.id = package_version.package_id"). - Where(cond) + Where(builder.In("package_version.id", in)) opts.configureOrderBy(sess) diff --git a/models/perm/access/access.go b/models/perm/access/access.go index b422a08614..6a0a901f71 100644 --- a/models/perm/access/access.go +++ b/models/perm/access/access.go @@ -63,13 +63,11 @@ func accessLevel(ctx context.Context, user *user_model.User, repo *repo_model.Re } func maxAccessMode(modes ...perm.AccessMode) perm.AccessMode { - max := perm.AccessModeNone + maxMode := perm.AccessModeNone for _, mode := range modes { - if mode > max { - max = mode - } + maxMode = max(maxMode, mode) } - return max + return maxMode } type userAccess struct { diff --git a/models/perm/access/access_test.go b/models/perm/access/access_test.go index 79b131fe89..51d625707c 100644 --- a/models/perm/access/access_test.go +++ b/models/perm/access/access_test.go @@ -79,17 +79,17 @@ func TestHasAccess(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) assert.True(t, repo2.IsPrivate) - has, err := access_model.HasAccess(db.DefaultContext, user1.ID, repo1) + has, err := access_model.HasAnyUnitAccess(db.DefaultContext, user1.ID, repo1) assert.NoError(t, err) assert.True(t, has) - _, err = access_model.HasAccess(db.DefaultContext, user1.ID, repo2) + _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user1.ID, repo2) assert.NoError(t, err) - _, err = access_model.HasAccess(db.DefaultContext, user2.ID, repo1) + _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user2.ID, repo1) assert.NoError(t, err) - _, err = access_model.HasAccess(db.DefaultContext, user2.ID, repo2) + _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user2.ID, repo2) assert.NoError(t, err) } diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 4175cb9b92..0ed116a132 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -6,6 +6,7 @@ package access import ( "context" "fmt" + "slices" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" @@ -14,13 +15,17 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" ) // Permission contains all the permissions related variables to a repository for a user type Permission struct { AccessMode perm_model.AccessMode - Units []*repo_model.RepoUnit - UnitsMode map[unit.Type]perm_model.AccessMode + + units []*repo_model.RepoUnit + unitsMode map[unit.Type]perm_model.AccessMode + + everyoneAccessMode map[unit.Type]perm_model.AccessMode } // IsOwner returns true if current user is the owner of repository. @@ -33,25 +38,59 @@ func (p *Permission) IsAdmin() bool { return p.AccessMode >= perm_model.AccessModeAdmin } -// HasAccess returns true if the current user has at least read access to any unit of this repository -func (p *Permission) HasAccess() bool { - if p.UnitsMode == nil { - return p.AccessMode >= perm_model.AccessModeRead +// HasAnyUnitAccess returns true if the user might have at least one access mode to any unit of this repository. +// It doesn't count the "everyone access mode". +func (p *Permission) HasAnyUnitAccess() bool { + for _, v := range p.unitsMode { + if v >= perm_model.AccessModeRead { + return true + } } - return len(p.UnitsMode) > 0 + return p.AccessMode >= perm_model.AccessModeRead } -// UnitAccessMode returns current user accessmode to the specify unit of the repository -func (p *Permission) UnitAccessMode(unitType unit.Type) perm_model.AccessMode { - if p.UnitsMode == nil { - for _, u := range p.Units { - if u.Type == unitType { - return p.AccessMode - } +func (p *Permission) HasAnyUnitAccessOrEveryoneAccess() bool { + for _, v := range p.everyoneAccessMode { + if v >= perm_model.AccessModeRead { + return true } - return perm_model.AccessModeNone } - return p.UnitsMode[unitType] + return p.HasAnyUnitAccess() +} + +// HasUnits returns true if the permission contains attached units +func (p *Permission) HasUnits() bool { + return len(p.units) > 0 +} + +// GetFirstUnitRepoID returns the repo ID of the first unit, it is a fragile design and should NOT be used anymore +// deprecated +func (p *Permission) GetFirstUnitRepoID() int64 { + if len(p.units) > 0 { + return p.units[0].RepoID + } + return 0 +} + +// UnitAccessMode returns current user access mode to the specify unit of the repository +// It also considers "everyone access mode" +func (p *Permission) UnitAccessMode(unitType unit.Type) perm_model.AccessMode { + // if the units map contains the access mode, use it, but admin/owner mode could override it + if m, ok := p.unitsMode[unitType]; ok { + return util.Iif(p.AccessMode >= perm_model.AccessModeAdmin, p.AccessMode, m) + } + // if the units map does not contain the access mode, return the default access mode if the unit exists + unitDefaultAccessMode := max(p.AccessMode, p.everyoneAccessMode[unitType]) + hasUnit := slices.ContainsFunc(p.units, func(u *repo_model.RepoUnit) bool { return u.Type == unitType }) + return util.Iif(hasUnit, unitDefaultAccessMode, perm_model.AccessModeNone) +} + +func (p *Permission) SetUnitsWithDefaultAccessMode(units []*repo_model.RepoUnit, mode perm_model.AccessMode) { + p.units = units + p.unitsMode = make(map[unit.Type]perm_model.AccessMode) + for _, u := range p.units { + p.unitsMode[u.Type] = mode + } } // CanAccess returns true if user has mode access to the unit of the repository @@ -102,23 +141,33 @@ func (p *Permission) CanWriteIssuesOrPulls(isPull bool) bool { return p.CanWrite(unit.TypeIssues) } +func (p *Permission) ReadableUnitTypes() []unit.Type { + types := make([]unit.Type, 0, len(p.units)) + for _, u := range p.units { + if p.CanRead(u.Type) { + types = append(types, u.Type) + } + } + return types +} + func (p *Permission) LogString() string { format := "= perm_model.AccessModeRead && u.EveryoneAccessMode > perm.everyoneAccessMode[u.Type] { + if perm.everyoneAccessMode == nil { + perm.everyoneAccessMode = make(map[unit.Type]perm_model.AccessMode) + } + perm.everyoneAccessMode[u.Type] = u.EveryoneAccessMode + } + } +} + +// GetUserRepoPermission returns the user permissions to the repository +func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (perm Permission, err error) { + defer func() { + if err == nil { + applyEveryoneRepoPermission(user, &perm) + } + if log.IsTrace() { + log.Trace("Permission Loaded for user %-v in repo %-v, permissions: %-+v", user, repo, perm) + } + }() + + if err = repo.LoadUnits(ctx); err != nil { + return perm, err + } + perm.units = repo.Units // anonymous user visit private repo. // TODO: anonymous user visit public unit of private repo??? @@ -152,7 +213,6 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use } var isCollaborator bool - var err error if user != nil { isCollaborator, err = repo_model.IsCollaborator(ctx, repo.ID, user.ID) if err != nil { @@ -160,7 +220,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use } } - if err := repo.LoadOwner(ctx); err != nil { + if err = repo.LoadOwner(ctx); err != nil { return perm, err } @@ -171,12 +231,6 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use return perm, nil } - if err := repo.LoadUnits(ctx); err != nil { - return perm, err - } - - perm.Units = repo.Units - // anonymous visit public repo if user == nil { perm.AccessMode = perm_model.AccessModeRead @@ -195,19 +249,16 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use return perm, err } - if err := repo.LoadOwner(ctx); err != nil { - return perm, err - } if !repo.Owner.IsOrganization() { return perm, nil } - perm.UnitsMode = make(map[unit.Type]perm_model.AccessMode) + perm.unitsMode = make(map[unit.Type]perm_model.AccessMode) // Collaborators on organization if isCollaborator { for _, u := range repo.Units { - perm.UnitsMode[u.Type] = perm.AccessMode + perm.unitsMode[u.Type] = perm.AccessMode } } @@ -221,7 +272,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use for _, team := range teams { if team.AccessMode >= perm_model.AccessModeAdmin { perm.AccessMode = perm_model.AccessModeOwner - perm.UnitsMode = nil + perm.unitsMode = nil return perm, nil } } @@ -229,30 +280,26 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use for _, u := range repo.Units { var found bool for _, team := range teams { - teamMode := team.UnitAccessMode(ctx, u.Type) - if teamMode > perm_model.AccessModeNone { - m := perm.UnitsMode[u.Type] - if m < teamMode { - perm.UnitsMode[u.Type] = teamMode - } + if teamMode, exist := team.UnitAccessModeEx(ctx, u.Type); exist { + perm.unitsMode[u.Type] = max(perm.unitsMode[u.Type], teamMode) found = true } } // for a public repo on an organization, a non-restricted user has read permission on non-team defined units. if !found && !repo.IsPrivate && !user.IsRestricted { - if _, ok := perm.UnitsMode[u.Type]; !ok { - perm.UnitsMode[u.Type] = perm_model.AccessModeRead + if _, ok := perm.unitsMode[u.Type]; !ok { + perm.unitsMode[u.Type] = perm_model.AccessModeRead } } } // remove no permission units - perm.Units = make([]*repo_model.RepoUnit, 0, len(repo.Units)) - for t := range perm.UnitsMode { + perm.units = make([]*repo_model.RepoUnit, 0, len(repo.Units)) + for t := range perm.unitsMode { for _, u := range repo.Units { if u.Type == t { - perm.Units = append(perm.Units, u) + perm.units = append(perm.units, u) } } } @@ -334,7 +381,7 @@ func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model. // Currently any write access (code, issues or pr's) is assignable, to match assignee list in user interface. func CanBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model.Repository, _ bool) (bool, error) { if user.IsOrganization() { - return false, fmt.Errorf("Organization can't be added as assignee [user_id: %d, repo_id: %d]", user.ID, repo.ID) + return false, fmt.Errorf("organization can't be added as assignee [user_id: %d, repo_id: %d]", user.ID, repo.ID) } perm, err := GetUserRepoPermission(ctx, repo, user) if err != nil { @@ -344,8 +391,8 @@ func CanBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model. perm.CanAccessAny(perm_model.AccessModeRead, unit.TypePullRequests), nil } -// HasAccess returns true if user has access to repo -func HasAccess(ctx context.Context, userID int64, repo *repo_model.Repository) (bool, error) { +// HasAnyUnitAccess see the comment of "perm.HasAnyUnitAccess" +func HasAnyUnitAccess(ctx context.Context, userID int64, repo *repo_model.Repository) (bool, error) { var user *user_model.User var err error if userID > 0 { @@ -358,7 +405,7 @@ func HasAccess(ctx context.Context, userID int64, repo *repo_model.Repository) ( if err != nil { return false, err } - return perm.HasAccess(), nil + return perm.HasAnyUnitAccess(), nil } // getUsersWithAccessMode returns users that have at least given access mode to the repository. diff --git a/models/perm/access/repo_permission_test.go b/models/perm/access/repo_permission_test.go new file mode 100644 index 0000000000..50070c4368 --- /dev/null +++ b/models/perm/access/repo_permission_test.go @@ -0,0 +1,136 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package access + +import ( + "testing" + + perm_model "code.gitea.io/gitea/models/perm" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + user_model "code.gitea.io/gitea/models/user" + + "github.com/stretchr/testify/assert" +) + +func TestHasAnyUnitAccess(t *testing.T) { + perm := Permission{} + assert.False(t, perm.HasAnyUnitAccess()) + + perm = Permission{ + units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}}, + } + assert.False(t, perm.HasAnyUnitAccess()) + assert.False(t, perm.HasAnyUnitAccessOrEveryoneAccess()) + + perm = Permission{ + units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}}, + everyoneAccessMode: map[unit.Type]perm_model.AccessMode{unit.TypeIssues: perm_model.AccessModeRead}, + } + assert.False(t, perm.HasAnyUnitAccess()) + assert.True(t, perm.HasAnyUnitAccessOrEveryoneAccess()) + + perm = Permission{ + AccessMode: perm_model.AccessModeRead, + units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}}, + } + assert.True(t, perm.HasAnyUnitAccess()) + + perm = Permission{ + unitsMode: map[unit.Type]perm_model.AccessMode{unit.TypeWiki: perm_model.AccessModeRead}, + } + assert.True(t, perm.HasAnyUnitAccess()) +} + +func TestApplyEveryoneRepoPermission(t *testing.T) { + perm := Permission{ + AccessMode: perm_model.AccessModeNone, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead}, + }, + } + applyEveryoneRepoPermission(nil, &perm) + assert.False(t, perm.CanRead(unit.TypeWiki)) + + perm = Permission{ + AccessMode: perm_model.AccessModeNone, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead}, + }, + } + applyEveryoneRepoPermission(&user_model.User{ID: 0}, &perm) + assert.False(t, perm.CanRead(unit.TypeWiki)) + + perm = Permission{ + AccessMode: perm_model.AccessModeNone, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead}, + }, + } + applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm) + assert.True(t, perm.CanRead(unit.TypeWiki)) + + perm = Permission{ + AccessMode: perm_model.AccessModeWrite, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead}, + }, + } + applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm) + // it should work the same as "EveryoneAccessMode: none" because the default AccessMode should be applied to units + assert.True(t, perm.CanWrite(unit.TypeWiki)) + + perm = Permission{ + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead}, + }, + unitsMode: map[unit.Type]perm_model.AccessMode{ + unit.TypeWiki: perm_model.AccessModeWrite, + }, + } + applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm) + assert.True(t, perm.CanWrite(unit.TypeWiki)) +} + +func TestUnitAccessMode(t *testing.T) { + perm := Permission{ + AccessMode: perm_model.AccessModeNone, + } + assert.Equal(t, perm_model.AccessModeNone, perm.UnitAccessMode(unit.TypeWiki), "no unit, no map, use AccessMode") + + perm = Permission{ + AccessMode: perm_model.AccessModeRead, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki}, + }, + } + assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "only unit, no map, use AccessMode") + + perm = Permission{ + AccessMode: perm_model.AccessModeAdmin, + unitsMode: map[unit.Type]perm_model.AccessMode{ + unit.TypeWiki: perm_model.AccessModeRead, + }, + } + assert.Equal(t, perm_model.AccessModeAdmin, perm.UnitAccessMode(unit.TypeWiki), "no unit, only map, admin overrides map") + + perm = Permission{ + AccessMode: perm_model.AccessModeNone, + unitsMode: map[unit.Type]perm_model.AccessMode{ + unit.TypeWiki: perm_model.AccessModeRead, + }, + } + assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "no unit, only map, use map") + + perm = Permission{ + AccessMode: perm_model.AccessModeNone, + units: []*repo_model.RepoUnit{ + {Type: unit.TypeWiki}, + }, + unitsMode: map[unit.Type]perm_model.AccessMode{ + unit.TypeWiki: perm_model.AccessModeRead, + }, + } + assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "has unit, and map, use map") +} diff --git a/models/perm/access_mode.go b/models/perm/access_mode.go index a37bc1f0e1..0364191e2e 100644 --- a/models/perm/access_mode.go +++ b/models/perm/access_mode.go @@ -5,25 +5,25 @@ package perm import ( "fmt" + "slices" + + "code.gitea.io/gitea/modules/util" ) // AccessMode specifies the users access mode type AccessMode int const ( - // AccessModeNone no access - AccessModeNone AccessMode = iota // 0 - // AccessModeRead read access - AccessModeRead // 1 - // AccessModeWrite write access - AccessModeWrite // 2 - // AccessModeAdmin admin access - AccessModeAdmin // 3 - // AccessModeOwner owner access - AccessModeOwner // 4 + AccessModeNone AccessMode = iota // 0: no access + + AccessModeRead // 1: read access + AccessModeWrite // 2: write access + AccessModeAdmin // 3: admin access + AccessModeOwner // 4: owner access ) -func (mode AccessMode) String() string { +// ToString returns the string representation of the access mode, do not make it a Stringer, otherwise it's difficult to render in templates +func (mode AccessMode) ToString() string { switch mode { case AccessModeRead: return "read" @@ -39,19 +39,24 @@ func (mode AccessMode) String() string { } func (mode AccessMode) LogString() string { - return fmt.Sprintf("", mode, mode.String()) + return fmt.Sprintf("", mode, mode.ToString()) } // ParseAccessMode returns corresponding access mode to given permission string. -func ParseAccessMode(permission string) AccessMode { +func ParseAccessMode(permission string, allowed ...AccessMode) AccessMode { + m := AccessModeNone switch permission { case "read": - return AccessModeRead + m = AccessModeRead case "write": - return AccessModeWrite + m = AccessModeWrite case "admin": - return AccessModeAdmin + m = AccessModeAdmin default: - return AccessModeNone + // the "owner" access is not really used for user input, it's mainly for checking access level in code, so don't parse it } + if len(allowed) == 0 { + return m + } + return util.Iif(slices.Contains(allowed, m), m, AccessModeNone) } diff --git a/models/perm/access_mode_test.go b/models/perm/access_mode_test.go new file mode 100644 index 0000000000..982fceee5a --- /dev/null +++ b/models/perm/access_mode_test.go @@ -0,0 +1,22 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package perm + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAccessMode(t *testing.T) { + names := []string{"none", "read", "write", "admin"} + for i, name := range names { + m := ParseAccessMode(name) + assert.Equal(t, AccessMode(i), m) + } + assert.Equal(t, AccessMode(4), AccessModeOwner) + assert.Equal(t, "owner", AccessModeOwner.ToString()) + assert.Equal(t, AccessModeNone, ParseAccessMode("owner")) + assert.Equal(t, AccessModeNone, ParseAccessMode("invalid")) +} diff --git a/models/project/board.go b/models/project/board.go index c0e6529880..7faabc52c5 100644 --- a/models/project/board.go +++ b/models/project/board.go @@ -110,19 +110,28 @@ func createBoardsForProjectsType(ctx context.Context, project *Project) error { var items []string switch project.BoardType { - case BoardTypeBugTriage: items = setting.Project.ProjectBoardBugTriageType case BoardTypeBasicKanban: items = setting.Project.ProjectBoardBasicKanbanType - case BoardTypeNone: fallthrough default: return nil } + board := Board{ + CreatedUnix: timeutil.TimeStampNow(), + CreatorID: project.CreatorID, + Title: "Backlog", + ProjectID: project.ID, + Default: true, + } + if err := db.Insert(ctx, board); err != nil { + return err + } + if len(items) == 0 { return nil } @@ -176,6 +185,10 @@ func deleteBoardByID(ctx context.Context, boardID int64) error { return err } + if board.Default { + return fmt.Errorf("deleteBoardByID: cannot delete default board") + } + if err = board.removeIssues(ctx); err != nil { return err } @@ -194,7 +207,6 @@ func deleteBoardByProjectID(ctx context.Context, projectID int64) error { // GetBoard fetches the current board of a project func GetBoard(ctx context.Context, boardID int64) (*Board, error) { board := new(Board) - has, err := db.GetEngine(ctx).ID(boardID).Get(board) if err != nil { return nil, err @@ -228,7 +240,6 @@ func UpdateBoard(ctx context.Context, board *Board) error { } // GetBoards fetches all boards related to a project -// if no default board set, first board is a temporary "Uncategorized" board func (p *Project) GetBoards(ctx context.Context) (BoardList, error) { boards := make([]*Board, 0, 5) @@ -244,53 +255,64 @@ func (p *Project) GetBoards(ctx context.Context) (BoardList, error) { return append([]*Board{defaultB}, boards...), nil } -// getDefaultBoard return default board and create a dummy if none exist +// getDefaultBoard return default board and ensure only one exists func (p *Project) getDefaultBoard(ctx context.Context) (*Board, error) { var board Board - exist, err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", p.ID, true).Get(&board) + has, err := db.GetEngine(ctx). + Where("project_id=? AND `default` = ?", p.ID, true). + Desc("id").Get(&board) if err != nil { return nil, err } - if exist { + + if has { return &board, nil } - // represents a board for issues not assigned to one - return &Board{ + // create a default board if none is found + board = Board{ ProjectID: p.ID, - Title: "Uncategorized", Default: true, - }, nil + Title: "Uncategorized", + CreatorID: p.CreatorID, + } + if _, err := db.GetEngine(ctx).Insert(&board); err != nil { + return nil, err + } + return &board, nil } // SetDefaultBoard represents a board for issues not assigned to one -// if boardID is 0 unset default func SetDefaultBoard(ctx context.Context, projectID, boardID int64) error { - _, err := db.GetEngine(ctx).Where(builder.Eq{ - "project_id": projectID, - "`default`": true, - }).Cols("`default`").Update(&Board{Default: false}) - if err != nil { - return err - } + return db.WithTx(ctx, func(ctx context.Context) error { + if _, err := GetBoard(ctx, boardID); err != nil { + return err + } - if boardID > 0 { - _, err = db.GetEngine(ctx).ID(boardID).Where(builder.Eq{"project_id": projectID}). + if _, err := db.GetEngine(ctx).Where(builder.Eq{ + "project_id": projectID, + "`default`": true, + }).Cols("`default`").Update(&Board{Default: false}); err != nil { + return err + } + + _, err := db.GetEngine(ctx).ID(boardID). + Where(builder.Eq{"project_id": projectID}). Cols("`default`").Update(&Board{Default: true}) - } - - return err + return err + }) } // UpdateBoardSorting update project board sorting func UpdateBoardSorting(ctx context.Context, bs BoardList) error { - for i := range bs { - _, err := db.GetEngine(ctx).ID(bs[i].ID).Cols( - "sorting", - ).Update(bs[i]) - if err != nil { - return err + return db.WithTx(ctx, func(ctx context.Context) error { + for i := range bs { + if _, err := db.GetEngine(ctx).ID(bs[i].ID).Cols( + "sorting", + ).Update(bs[i]); err != nil { + return err + } } - } - return nil + return nil + }) } diff --git a/models/project/board_test.go b/models/project/board_test.go new file mode 100644 index 0000000000..71ba29a589 --- /dev/null +++ b/models/project/board_test.go @@ -0,0 +1,44 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package project + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestGetDefaultBoard(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + projectWithoutDefault, err := GetProjectByID(db.DefaultContext, 5) + assert.NoError(t, err) + + // check if default board was added + board, err := projectWithoutDefault.getDefaultBoard(db.DefaultContext) + assert.NoError(t, err) + assert.Equal(t, int64(5), board.ProjectID) + assert.Equal(t, "Uncategorized", board.Title) + + projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6) + assert.NoError(t, err) + + // check if multiple defaults were removed + board, err = projectWithMultipleDefaults.getDefaultBoard(db.DefaultContext) + assert.NoError(t, err) + assert.Equal(t, int64(6), board.ProjectID) + assert.Equal(t, int64(9), board.ID) + + // set 8 as default board + assert.NoError(t, SetDefaultBoard(db.DefaultContext, board.ProjectID, 8)) + + // then 9 will become a non-default board + board, err = GetBoard(db.DefaultContext, 9) + assert.NoError(t, err) + assert.Equal(t, int64(6), board.ProjectID) + assert.False(t, board.Default) +} diff --git a/models/project/project_test.go b/models/project/project_test.go index 7a37c1faf2..8fbbdedecf 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -92,19 +92,19 @@ func TestProjectsSort(t *testing.T) { }{ { sortType: "default", - wants: []int64{1, 3, 2, 4}, + wants: []int64{1, 3, 2, 6, 5, 4}, }, { sortType: "oldest", - wants: []int64{4, 2, 3, 1}, + wants: []int64{4, 5, 6, 2, 3, 1}, }, { sortType: "recentupdate", - wants: []int64{1, 3, 2, 4}, + wants: []int64{1, 3, 2, 6, 5, 4}, }, { sortType: "leastupdate", - wants: []int64{4, 2, 3, 1}, + wants: []int64{4, 5, 6, 2, 3, 1}, }, } @@ -113,8 +113,8 @@ func TestProjectsSort(t *testing.T) { OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) - assert.EqualValues(t, int64(4), count) - if assert.Len(t, projects, 4) { + assert.EqualValues(t, int64(6), count) + if assert.Len(t, projects, 6) { for i := range projects { assert.EqualValues(t, tt.wants[i], projects[i].ID) } diff --git a/models/repo/attachment.go b/models/repo/attachment.go index 1a588398c1..9b0de11fdc 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -24,7 +24,7 @@ type Attachment struct { IssueID int64 `xorm:"INDEX"` // maybe zero when creating ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added - CommentID int64 + CommentID int64 `xorm:"INDEX"` Name string DownloadCount int64 `xorm:"DEFAULT 0"` Size int64 `xorm:"DEFAULT 0"` diff --git a/models/repo/issue.go b/models/repo/issue.go index 6f6b565a00..0dd4fd5ed4 100644 --- a/models/repo/issue.go +++ b/models/repo/issue.go @@ -53,7 +53,7 @@ func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool { var u *RepoUnit var err error if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { - log.Trace("%s", err) + log.Trace("IsDependenciesEnabled: %v", err) return setting.Service.DefaultEnableDependencies } return u.IssuesConfig().EnableDependencies diff --git a/models/repo/repo.go b/models/repo/repo.go index e830b736fd..257490f86c 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -531,6 +531,9 @@ func (repo *Repository) GetBaseRepo(ctx context.Context) (err error) { return nil } + if repo.BaseRepo != nil { + return nil + } repo.BaseRepo, err = GetRepositoryByID(ctx, repo.ForkID) return err } diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 6b452291ea..987c7df9b0 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -63,24 +63,60 @@ func RepositoryListOfMap(repoMap map[int64]*Repository) RepositoryList { return RepositoryList(ValuesRepository(repoMap)) } +func (repos RepositoryList) LoadUnits(ctx context.Context) error { + if len(repos) == 0 { + return nil + } + + // Load units. + units := make([]*RepoUnit, 0, len(repos)*6) + if err := db.GetEngine(ctx). + In("repo_id", repos.IDs()). + Find(&units); err != nil { + return fmt.Errorf("find units: %w", err) + } + + unitsMap := make(map[int64][]*RepoUnit, len(repos)) + for _, unit := range units { + if !unit.Type.UnitGlobalDisabled() { + unitsMap[unit.RepoID] = append(unitsMap[unit.RepoID], unit) + } + } + + for _, repo := range repos { + repo.Units = unitsMap[repo.ID] + } + + return nil +} + +func (repos RepositoryList) IDs() []int64 { + repoIDs := make([]int64, len(repos)) + for i := range repos { + repoIDs[i] = repos[i].ID + } + return repoIDs +} + // LoadAttributes loads the attributes for the given RepositoryList func (repos RepositoryList) LoadAttributes(ctx context.Context) error { if len(repos) == 0 { return nil } - set := make(container.Set[int64]) + userIDs := container.FilterSlice(repos, func(repo *Repository) (int64, bool) { + return repo.OwnerID, true + }) repoIDs := make([]int64, len(repos)) for i := range repos { - set.Add(repos[i].OwnerID) repoIDs[i] = repos[i].ID } // Load owners. - users := make(map[int64]*user_model.User, len(set)) + users := make(map[int64]*user_model.User, len(userIDs)) if err := db.GetEngine(ctx). Where("id > 0"). - In("id", set.Values()). + In("id", userIDs). Find(&users); err != nil { return fmt.Errorf("find users: %w", err) } diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go index 5a841f4d31..fd5baa9488 100644 --- a/models/repo/repo_unit.go +++ b/models/repo/repo_unit.go @@ -10,6 +10,7 @@ import ( "strings" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" @@ -41,11 +42,12 @@ func (err ErrUnitTypeNotExist) Unwrap() error { // RepoUnit describes all units of a repository type RepoUnit struct { //revive:disable-line:exported - ID int64 - RepoID int64 `xorm:"INDEX(s)"` - Type unit.Type `xorm:"INDEX(s)"` - Config convert.Conversion `xorm:"TEXT"` - CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` + ID int64 + RepoID int64 `xorm:"INDEX(s)"` + Type unit.Type `xorm:"INDEX(s)"` + Config convert.Conversion `xorm:"TEXT"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` + EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"` } func init() { diff --git a/models/repo/topic.go b/models/repo/topic.go index 9c828b54a4..8024becfae 100644 --- a/models/repo/topic.go +++ b/models/repo/topic.go @@ -178,7 +178,7 @@ type FindTopicOptions struct { Keyword string } -func (opts *FindTopicOptions) toConds() builder.Cond { +func (opts *FindTopicOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_topic.repo_id": opts.RepoID}) @@ -191,29 +191,24 @@ func (opts *FindTopicOptions) toConds() builder.Cond { return cond } -// FindTopics retrieves the topics via FindTopicOptions -func FindTopics(ctx context.Context, opts *FindTopicOptions) ([]*Topic, int64, error) { - sess := db.GetEngine(ctx).Select("topic.*").Where(opts.toConds()) +func (opts *FindTopicOptions) ToOrders() string { orderBy := "topic.repo_count DESC" if opts.RepoID > 0 { - sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id") orderBy = "topic.name" // when render topics for a repo, it's better to sort them by name, to get consistent result } - if opts.PageSize != 0 && opts.Page != 0 { - sess = db.SetSessionPagination(sess, opts) - } - topics := make([]*Topic, 0, 10) - total, err := sess.OrderBy(orderBy).FindAndCount(&topics) - return topics, total, err + return orderBy } -// CountTopics counts the number of topics matching the FindTopicOptions -func CountTopics(ctx context.Context, opts *FindTopicOptions) (int64, error) { - sess := db.GetEngine(ctx).Where(opts.toConds()) - if opts.RepoID > 0 { - sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id") +func (opts *FindTopicOptions) ToJoins() []db.JoinFunc { + if opts.RepoID <= 0 { + return nil + } + return []db.JoinFunc{ + func(e db.Engine) error { + e.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id") + return nil + }, } - return sess.Count(new(Topic)) } // GetRepoTopicByName retrieves topic from name for a repo if it exist @@ -311,7 +306,7 @@ func DeleteTopic(ctx context.Context, repoID int64, topicName string) (*Topic, e // SaveTopics save topics to a repository (add and delete respective topics) func SaveTopics(ctx context.Context, repoID int64, topicNames ...string) error { - topics, _, err := FindTopics(ctx, &FindTopicOptions{ + topics, err := db.Find[Topic](ctx, &FindTopicOptions{ RepoID: repoID, }) if err != nil { diff --git a/models/repo/topic_test.go b/models/repo/topic_test.go index 2b609e6d66..1600896b6e 100644 --- a/models/repo/topic_test.go +++ b/models/repo/topic_test.go @@ -19,18 +19,18 @@ func TestAddTopic(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - topics, _, err := repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err := db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, total, err := repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{ + topics, total, err := db.FindAndCount[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ ListOptions: db.ListOptions{Page: 1, PageSize: 2}, }) assert.NoError(t, err) assert.Len(t, topics, 2) assert.EqualValues(t, 6, total) - topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ RepoID: 1, }) assert.NoError(t, err) @@ -38,11 +38,11 @@ func TestAddTopic(t *testing.T) { assert.NoError(t, repo_model.SaveTopics(db.DefaultContext, 2, "golang")) repo2NrOfTopics := 1 - topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err) @@ -55,11 +55,11 @@ func TestAddTopic(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, topic.RepoCount) - topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, _, err = repo_model.FindTopics(db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err) diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index 6862247657..1c5412fe7d 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -170,7 +170,6 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) // the owner of a private repo needs to be explicitly added. cond = cond.Or(builder.Eq{"`user`.id": repo.Owner.ID}) } - } else { // This is a "public" repository: // Any user that has read access, is a watcher or organization member can be requested to review diff --git a/models/repo_transfer.go b/models/repo_transfer.go index 747ec2f248..37f591f65d 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -5,6 +5,7 @@ package models import ( "context" + "errors" "fmt" "code.gitea.io/gitea/models/db" @@ -147,7 +148,7 @@ func DeleteRepositoryTransfer(ctx context.Context, repoID int64) error { func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error { switch status { case repo_model.RepositoryBeingMigrated: - return fmt.Errorf("repo is not ready, currently migrating") + return errors.New("repo is not ready, currently migrating") case repo_model.RepositoryPendingTransfer: return ErrRepoTransferInProgress{} } diff --git a/models/unit/unit.go b/models/unit/unit.go index b216712d37..a78a2f1e47 100644 --- a/models/unit/unit.go +++ b/models/unit/unit.go @@ -191,16 +191,13 @@ type Unit struct { NameKey string URI string DescKey string - Idx int + Priority int MaxAccessMode perm.AccessMode // The max access mode of the unit. i.e. Read means this unit can only be read. } // IsLessThan compares order of two units func (u Unit) IsLessThan(unit Unit) bool { - if (u.Type == TypeExternalTracker || u.Type == TypeExternalWiki) && unit.Type != TypeExternalTracker && unit.Type != TypeExternalWiki { - return false - } - return u.Idx < unit.Idx + return u.Priority < unit.Priority } // MaxPerm returns the max perms of this unit @@ -236,7 +233,7 @@ var ( "repo.ext_issues", "/issues", "repo.ext_issues.desc", - 1, + 101, perm.AccessModeRead, } @@ -272,7 +269,7 @@ var ( "repo.ext_wiki", "/wiki", "repo.ext_wiki.desc", - 4, + 102, perm.AccessModeRead, } diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index cb90c12f2b..51de18fa9b 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/auth/password/hash" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting/config" @@ -106,6 +107,7 @@ func MainTest(m *testing.M, testOpts ...*TestOptions) { fatalTestError("Error creating test engine: %v\n", err) } + setting.IsInTesting = true setting.AppURL = "https://try.gitea.io/" setting.RunUser = "runuser" setting.SSH.User = "sshuser" @@ -148,6 +150,9 @@ func MainTest(m *testing.M, testOpts ...*TestOptions) { config.SetDynGetter(system.NewDatabaseDynKeyGetter()) + if err = cache.Init(); err != nil { + fatalTestError("cache.Init: %v\n", err) + } if err = storage.Init(); err != nil { fatalTestError("storage.Init: %v\n", err) } diff --git a/models/user/email_address.go b/models/user/email_address.go index 11700a0129..08771efe99 100644 --- a/models/user/email_address.go +++ b/models/user/email_address.go @@ -256,14 +256,6 @@ func IsEmailUsed(ctx context.Context, email string) (bool, error) { return db.GetEngine(ctx).Where("lower_email=?", strings.ToLower(email)).Get(&EmailAddress{}) } -// DeleteInactiveEmailAddresses deletes inactive email addresses -func DeleteInactiveEmailAddresses(ctx context.Context) error { - _, err := db.GetEngine(ctx). - Where("is_activated = ?", false). - Delete(new(EmailAddress)) - return err -} - // ActivateEmail activates the email address to given user. func ActivateEmail(ctx context.Context, email *EmailAddress) error { ctx, committer, err := db.TxContext(ctx) @@ -434,7 +426,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail cond = cond.And(builder.Eq{"email_address.is_activated": opts.IsActivated.Value()}) } - count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.ID = email_address.uid"). + count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.id = email_address.uid"). Where(cond).Count(new(EmailAddress)) if err != nil { return nil, 0, fmt.Errorf("Count: %w", err) @@ -450,7 +442,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail emails := make([]*SearchEmailResult, 0, opts.PageSize) err = db.GetEngine(ctx).Table("email_address"). Select("email_address.*, `user`.name, `user`.full_name"). - Join("INNER", "`user`", "`user`.ID = email_address.uid"). + Join("INNER", "`user`", "`user`.id = email_address.uid"). Where(cond). OrderBy(orderby). Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). @@ -539,17 +531,17 @@ func validateEmailBasic(email string) error { // validateEmailDomain checks whether the email domain is allowed or blocked func validateEmailDomain(email string) error { - // if there is no allow list, then check email against block list - if len(setting.Service.EmailDomainAllowList) == 0 && - validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) { - return ErrEmailInvalid{email} - } - - // if there is an allow list, then check email against allow list - if len(setting.Service.EmailDomainAllowList) > 0 && - !validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) { + if !IsEmailDomainAllowed(email) { return ErrEmailInvalid{email} } return nil } + +func IsEmailDomainAllowed(email string) bool { + if len(setting.Service.EmailDomainAllowList) == 0 { + return !validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) + } + + return validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) +} diff --git a/models/user/user.go b/models/user/user.go index 0bdda8655f..a5a5b5bdf6 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -425,7 +425,7 @@ func (u *User) GetDisplayName() string { return u.Name } -// GetCompleteName returns the the full name and username in the form of +// GetCompleteName returns the full name and username in the form of // "Full Name (username)" if full name is not empty, otherwise it returns // "username". func (u *User) GetCompleteName() string { @@ -501,19 +501,19 @@ func GetUserSalt() (string, error) { // Note: The set of characters here can safely expand without a breaking change, // but characters removed from this set can cause user account linking to break var ( - customCharsReplacement = strings.NewReplacer("Æ", "AE") - removeCharsRE = regexp.MustCompile(`['´\x60]`) - removeDiacriticsTransform = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) - replaceCharsHyphenRE = regexp.MustCompile(`[\s~+]`) + customCharsReplacement = strings.NewReplacer("Æ", "AE") + removeCharsRE = regexp.MustCompile("['`´]") + transformDiacritics = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) + replaceCharsHyphenRE = regexp.MustCompile(`[\s~+]`) ) -// normalizeUserName returns a string with single-quotes and diacritics -// removed, and any other non-supported username characters replaced with -// a `-` character +// NormalizeUserName only takes the name part if it is an email address, transforms it diacritics to ASCII characters. +// It returns a string with the single-quotes removed, and any other non-supported username characters are replaced with a `-` character func NormalizeUserName(s string) (string, error) { - strDiacriticsRemoved, n, err := transform.String(removeDiacriticsTransform, customCharsReplacement.Replace(s)) + s, _, _ = strings.Cut(s, "@") + strDiacriticsRemoved, n, err := transform.String(transformDiacritics, customCharsReplacement.Replace(s)) if err != nil { - return "", fmt.Errorf("Failed to normalize character `%v` in provided username `%v`", s[n], s) + return "", fmt.Errorf("failed to normalize the string of provided username %q at position %d", s, n) } return replaceCharsHyphenRE.ReplaceAllLiteralString(removeCharsRE.ReplaceAllLiteralString(strDiacriticsRemoved, ""), "-"), nil } @@ -988,9 +988,8 @@ func GetUserIDsByNames(ctx context.Context, names []string, ignoreNonExistent bo if err != nil { if ignoreNonExistent { continue - } else { - return nil, err } + return nil, err } ids = append(ids, u.ID) } @@ -1232,3 +1231,21 @@ func GetOrderByName() string { } return "name" } + +// IsFeatureDisabledWithLoginType checks if a user feature is disabled, taking into account the login type of the +// user if applicable +func IsFeatureDisabledWithLoginType(user *User, feature string) bool { + // NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType + return (user != nil && user.LoginType > auth.Plain && setting.Admin.ExternalUserDisableFeatures.Contains(feature)) || + setting.Admin.UserDisabledFeatures.Contains(feature) +} + +// DisabledFeaturesWithLoginType returns the set of user features disabled, taking into account the login type +// of the user if applicable +func DisabledFeaturesWithLoginType(user *User) *container.Set[string] { + // NOTE: in the long run it may be better to check the ExternalLoginUser table rather than user.LoginType + if user != nil && user.LoginType > auth.Plain { + return &setting.Admin.ExternalUserDisableFeatures + } + return &setting.Admin.UserDisabledFeatures +} diff --git a/models/user/user_test.go b/models/user/user_test.go index f4efd071ea..b4ffa1f322 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/auth/password/hash" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" @@ -505,15 +506,16 @@ func Test_NormalizeUserFromEmail(t *testing.T) { Expected string IsNormalizedValid bool }{ - {"test", "test", true}, + {"name@example.com", "name", true}, + {"test'`´name", "testname", true}, {"Sinéad.O'Connor", "Sinead.OConnor", true}, {"Æsir", "AEsir", true}, - // \u00e9\u0065\u0301 - {"éé", "ee", true}, + {"éé", "ee", true}, // \u00e9\u0065\u0301 {"Awareness Hub", "Awareness-Hub", true}, {"double__underscore", "double__underscore", false}, // We should consider squashing double non-alpha characters {".bad.", ".bad.", false}, {"new😀user", "new😀user", false}, // No plans to support + {`"quoted"`, `"quoted"`, false}, // No plans to support } for _, testCase := range testCases { normalizedName, err := user_model.NormalizeUserName(testCase.Input) @@ -526,3 +528,37 @@ func Test_NormalizeUserFromEmail(t *testing.T) { } } } + +func TestDisabledUserFeatures(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + testValues := container.SetOf(setting.UserFeatureDeletion, + setting.UserFeatureManageSSHKeys, + setting.UserFeatureManageGPGKeys) + + oldSetting := setting.Admin.ExternalUserDisableFeatures + defer func() { + setting.Admin.ExternalUserDisableFeatures = oldSetting + }() + setting.Admin.ExternalUserDisableFeatures = testValues + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + + assert.Len(t, setting.Admin.UserDisabledFeatures.Values(), 0) + + // no features should be disabled with a plain login type + assert.LessOrEqual(t, user.LoginType, auth.Plain) + assert.Len(t, user_model.DisabledFeaturesWithLoginType(user).Values(), 0) + for _, f := range testValues.Values() { + assert.False(t, user_model.IsFeatureDisabledWithLoginType(user, f)) + } + + // check disabled features with external login type + user.LoginType = auth.OAuth2 + + // all features should be disabled + assert.NotEmpty(t, user_model.DisabledFeaturesWithLoginType(user).Values()) + for _, f := range testValues.Values() { + assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f)) + } +} diff --git a/modules/actions/log.go b/modules/actions/log.go index cdf18646aa..c38082b5dc 100644 --- a/modules/actions/log.go +++ b/modules/actions/log.go @@ -100,7 +100,7 @@ func ReadLogs(ctx context.Context, inStorage bool, filename string, offset, limi } if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("scan: %w", err) + return nil, fmt.Errorf("ReadLogs scan: %w", err) } return rows, nil diff --git a/modules/actions/task_state.go b/modules/actions/task_state.go index fe925bbb5d..31a74be3fd 100644 --- a/modules/actions/task_state.go +++ b/modules/actions/task_state.go @@ -41,6 +41,12 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep { } logIndex += preStep.LogLength + // lastHasRunStep is the last step that has run. + // For example, + // 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1. + // 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3. + // 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2. + // So its Stopped is the Started of postStep when there are no more steps to run. var lastHasRunStep *actions_model.ActionTaskStep for _, step := range task.Steps { if step.Status.HasRun() { @@ -56,11 +62,15 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep { Name: postStepName, Status: actions_model.StatusWaiting, } - if task.Status.IsDone() { + // If the lastHasRunStep is the last step, or it has failed, postStep has started. + if lastHasRunStep.Status.IsFailure() || lastHasRunStep == task.Steps[len(task.Steps)-1] { postStep.LogIndex = logIndex postStep.LogLength = task.LogLength - postStep.LogIndex - postStep.Status = task.Status postStep.Started = lastHasRunStep.Stopped + postStep.Status = actions_model.StatusRunning + } + if task.Status.IsDone() { + postStep.Status = task.Status postStep.Stopped = task.Stopped } ret := make([]*actions_model.ActionTaskStep, 0, len(task.Steps)+2) diff --git a/modules/actions/task_state_test.go b/modules/actions/task_state_test.go index 3a599fbcbd..28213d781b 100644 --- a/modules/actions/task_state_test.go +++ b/modules/actions/task_state_test.go @@ -103,6 +103,40 @@ func TestFullSteps(t *testing.T) { {Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 100, LogLength: 0, Started: 10100, Stopped: 10100}, }, }, + { + name: "all steps finished but task is running", + task: &actions_model.ActionTask{ + Steps: []*actions_model.ActionTaskStep{ + {Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090}, + }, + Status: actions_model.StatusRunning, + Started: 10000, + Stopped: 0, + LogLength: 100, + }, + want: []*actions_model.ActionTaskStep{ + {Name: preStepName, Status: actions_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010}, + {Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090}, + {Name: postStepName, Status: actions_model.StatusRunning, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 0}, + }, + }, + { + name: "skipped task", + task: &actions_model.ActionTask{ + Steps: []*actions_model.ActionTaskStep{ + {Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + }, + Status: actions_model.StatusSkipped, + Started: 0, + Stopped: 0, + LogLength: 0, + }, + want: []*actions_model.ActionTaskStep{ + {Name: preStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + {Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + {Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/modules/auth/password/password.go b/modules/auth/password/password.go index 27074358a9..85f9780709 100644 --- a/modules/auth/password/password.go +++ b/modules/auth/password/password.go @@ -63,16 +63,16 @@ func NewComplexity() { func setupComplexity(values []string) { if len(values) != 1 || values[0] != "off" { for _, val := range values { - if complex, ok := charComplexities[val]; ok { - validChars += complex.ValidChars - requiredList = append(requiredList, complex) + if complexity, ok := charComplexities[val]; ok { + validChars += complexity.ValidChars + requiredList = append(requiredList, complexity) } } if len(requiredList) == 0 { // No valid character classes found; use all classes as default - for _, complex := range charComplexities { - validChars += complex.ValidChars - requiredList = append(requiredList, complex) + for _, complexity := range charComplexities { + validChars += complexity.ValidChars + requiredList = append(requiredList, complexity) } } } diff --git a/modules/base/tool.go b/modules/base/tool.go index 168a2220b2..40785e74e8 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -150,13 +150,16 @@ func TruncateString(str string, limit int) string { // StringsToInt64s converts a slice of string to a slice of int64. func StringsToInt64s(strs []string) ([]int64, error) { - ints := make([]int64, len(strs)) - for i := range strs { - n, err := strconv.ParseInt(strs[i], 10, 64) + if strs == nil { + return nil, nil + } + ints := make([]int64, 0, len(strs)) + for _, s := range strs { + n, err := strconv.ParseInt(s, 10, 64) if err != nil { - return ints, err + return nil, err } - ints[i] = n + ints = append(ints, n) } return ints, nil } diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go index d28deb593d..f21b89c74c 100644 --- a/modules/base/tool_test.go +++ b/modules/base/tool_test.go @@ -138,12 +138,13 @@ func TestStringsToInt64s(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expected, result) } + testSuccess(nil, nil) testSuccess([]string{}, []int64{}) testSuccess([]string{"-1234"}, []int64{-1234}) - testSuccess([]string{"1", "4", "16", "64", "256"}, - []int64{1, 4, 16, 64, 256}) + testSuccess([]string{"1", "4", "16", "64", "256"}, []int64{1, 4, 16, 64, 256}) - _, err := StringsToInt64s([]string{"-1", "a", "$"}) + ints, err := StringsToInt64s([]string{"-1", "a"}) + assert.Len(t, ints, 0) assert.Error(t, err) } diff --git a/modules/cache/cache.go b/modules/cache/cache.go index 09afc8b7f7..2ca77bdb29 100644 --- a/modules/cache/cache.go +++ b/modules/cache/cache.go @@ -4,149 +4,75 @@ package cache import ( - "fmt" "strconv" + "time" "code.gitea.io/gitea/modules/setting" - - mc "gitea.com/go-chi/cache" - - _ "gitea.com/go-chi/cache/memcache" // memcache plugin for cache ) -var conn mc.Cache - -func newCache(cacheConfig setting.Cache) (mc.Cache, error) { - return mc.NewCacher(mc.Options{ - Adapter: cacheConfig.Adapter, - AdapterConfig: cacheConfig.Conn, - Interval: cacheConfig.Interval, - }) -} +var defaultCache StringCache // Init start cache service func Init() error { - var err error - - if conn == nil { - if conn, err = newCache(setting.CacheService.Cache); err != nil { + if defaultCache == nil { + c, err := NewStringCache(setting.CacheService.Cache) + if err != nil { return err } - if err = conn.Ping(); err != nil { + for i := 0; i < 10; i++ { + if err = c.Ping(); err == nil { + break + } + time.Sleep(time.Second) + } + if err != nil { return err } + defaultCache = c } - - return err + return nil } // GetCache returns the currently configured cache -func GetCache() mc.Cache { - return conn +func GetCache() StringCache { + return defaultCache } // GetString returns the key value from cache with callback when no key exists in cache func GetString(key string, getFunc func() (string, error)) (string, error) { - if conn == nil || setting.CacheService.TTL == 0 { + if defaultCache == nil || setting.CacheService.TTL == 0 { return getFunc() } - - cached := conn.Get(key) - - if cached == nil { + cached, exist := defaultCache.Get(key) + if !exist { value, err := getFunc() if err != nil { return value, err } - return value, conn.Put(key, value, setting.CacheService.TTLSeconds()) - } - - if value, ok := cached.(string); ok { - return value, nil - } - - if stringer, ok := cached.(fmt.Stringer); ok { - return stringer.String(), nil - } - - return fmt.Sprintf("%s", cached), nil -} - -// GetInt returns key value from cache with callback when no key exists in cache -func GetInt(key string, getFunc func() (int, error)) (int, error) { - if conn == nil || setting.CacheService.TTL == 0 { - return getFunc() - } - - cached := conn.Get(key) - - if cached == nil { - value, err := getFunc() - if err != nil { - return value, err - } - - return value, conn.Put(key, value, setting.CacheService.TTLSeconds()) - } - - switch v := cached.(type) { - case int: - return v, nil - case string: - value, err := strconv.Atoi(v) - if err != nil { - return 0, err - } - return value, nil - default: - value, err := getFunc() - if err != nil { - return value, err - } - return value, conn.Put(key, value, setting.CacheService.TTLSeconds()) + return value, defaultCache.Put(key, value, setting.CacheService.TTLSeconds()) } + return cached, nil } // GetInt64 returns key value from cache with callback when no key exists in cache func GetInt64(key string, getFunc func() (int64, error)) (int64, error) { - if conn == nil || setting.CacheService.TTL == 0 { - return getFunc() + s, err := GetString(key, func() (string, error) { + v, err := getFunc() + return strconv.FormatInt(v, 10), err + }) + if err != nil { + return 0, err } - - cached := conn.Get(key) - - if cached == nil { - value, err := getFunc() - if err != nil { - return value, err - } - - return value, conn.Put(key, value, setting.CacheService.TTLSeconds()) - } - - switch v := conn.Get(key).(type) { - case int64: - return v, nil - case string: - value, err := strconv.ParseInt(v, 10, 64) - if err != nil { - return 0, err - } - return value, nil - default: - value, err := getFunc() - if err != nil { - return value, err - } - - return value, conn.Put(key, value, setting.CacheService.TTLSeconds()) + if s == "" { + return 0, nil } + return strconv.ParseInt(s, 10, 64) } // Remove key from cache func Remove(key string) { - if conn == nil { + if defaultCache == nil { return } - _ = conn.Delete(key) + _ = defaultCache.Delete(key) } diff --git a/modules/cache/cache_redis.go b/modules/cache/cache_redis.go index 6c358b0a78..c5b52a2086 100644 --- a/modules/cache/cache_redis.go +++ b/modules/cache/cache_redis.go @@ -11,7 +11,7 @@ import ( "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/nosql" - "gitea.com/go-chi/cache" + "gitea.com/go-chi/cache" //nolint:depguard "github.com/redis/go-redis/v9" ) diff --git a/modules/cache/cache_test.go b/modules/cache/cache_test.go index 3f65040924..0c68cc26ee 100644 --- a/modules/cache/cache_test.go +++ b/modules/cache/cache_test.go @@ -14,7 +14,7 @@ import ( ) func createTestCache() { - conn, _ = newCache(setting.Cache{ + defaultCache, _ = NewStringCache(setting.Cache{ Adapter: "memory", TTL: time.Minute, }) @@ -25,7 +25,7 @@ func TestNewContext(t *testing.T) { assert.NoError(t, Init()) setting.CacheService.Cache = setting.Cache{Adapter: "redis", Conn: "some random string"} - con, err := newCache(setting.Cache{ + con, err := NewStringCache(setting.Cache{ Adapter: "rand", Conn: "false conf", Interval: 100, @@ -76,42 +76,6 @@ func TestGetString(t *testing.T) { Remove("key") } -func TestGetInt(t *testing.T) { - createTestCache() - - data, err := GetInt("key", func() (int, error) { - return 0, fmt.Errorf("some error") - }) - assert.Error(t, err) - assert.Equal(t, 0, data) - - data, err = GetInt("key", func() (int, error) { - return 0, nil - }) - assert.NoError(t, err) - assert.Equal(t, 0, data) - - data, err = GetInt("key", func() (int, error) { - return 100, nil - }) - assert.NoError(t, err) - assert.Equal(t, 0, data) - Remove("key") - - data, err = GetInt("key", func() (int, error) { - return 100, nil - }) - assert.NoError(t, err) - assert.Equal(t, 100, data) - - data, err = GetInt("key", func() (int, error) { - return 0, fmt.Errorf("some error") - }) - assert.NoError(t, err) - assert.Equal(t, 100, data) - Remove("key") -} - func TestGetInt64(t *testing.T) { createTestCache() diff --git a/modules/cache/cache_twoqueue.go b/modules/cache/cache_twoqueue.go index f9de2563ec..1eda2debc4 100644 --- a/modules/cache/cache_twoqueue.go +++ b/modules/cache/cache_twoqueue.go @@ -10,7 +10,7 @@ import ( "code.gitea.io/gitea/modules/json" - mc "gitea.com/go-chi/cache" + mc "gitea.com/go-chi/cache" //nolint:depguard lru "github.com/hashicorp/golang-lru/v2" ) diff --git a/modules/cache/string_cache.go b/modules/cache/string_cache.go new file mode 100644 index 0000000000..4f659616f5 --- /dev/null +++ b/modules/cache/string_cache.go @@ -0,0 +1,120 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cache + +import ( + "errors" + "strings" + + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" + + chi_cache "gitea.com/go-chi/cache" //nolint:depguard +) + +type GetJSONError struct { + err error + cachedError string // Golang error can't be stored in cache, only the string message could be stored +} + +func (e *GetJSONError) ToError() error { + if e.err != nil { + return e.err + } + return errors.New("cached error: " + e.cachedError) +} + +type StringCache interface { + Ping() error + + Get(key string) (string, bool) + Put(key, value string, ttl int64) error + Delete(key string) error + IsExist(key string) bool + + PutJSON(key string, v any, ttl int64) error + GetJSON(key string, ptr any) (exist bool, err *GetJSONError) + + ChiCache() chi_cache.Cache +} + +type stringCache struct { + chiCache chi_cache.Cache +} + +func NewStringCache(cacheConfig setting.Cache) (StringCache, error) { + adapter := util.IfZero(cacheConfig.Adapter, "memory") + interval := util.IfZero(cacheConfig.Interval, 60) + cc, err := chi_cache.NewCacher(chi_cache.Options{ + Adapter: adapter, + AdapterConfig: cacheConfig.Conn, + Interval: interval, + }) + if err != nil { + return nil, err + } + return &stringCache{chiCache: cc}, nil +} + +func (sc *stringCache) Ping() error { + return sc.chiCache.Ping() +} + +func (sc *stringCache) Get(key string) (string, bool) { + v := sc.chiCache.Get(key) + if v == nil { + return "", false + } + s, ok := v.(string) + return s, ok +} + +func (sc *stringCache) Put(key, value string, ttl int64) error { + return sc.chiCache.Put(key, value, ttl) +} + +func (sc *stringCache) Delete(key string) error { + return sc.chiCache.Delete(key) +} + +func (sc *stringCache) IsExist(key string) bool { + return sc.chiCache.IsExist(key) +} + +const cachedErrorPrefix = ":" + +func (sc *stringCache) PutJSON(key string, v any, ttl int64) error { + var s string + switch v := v.(type) { + case error: + s = cachedErrorPrefix + v.Error() + default: + b, err := json.Marshal(v) + if err != nil { + return err + } + s = util.UnsafeBytesToString(b) + } + return sc.chiCache.Put(key, s, ttl) +} + +func (sc *stringCache) GetJSON(key string, ptr any) (exist bool, getErr *GetJSONError) { + s, ok := sc.Get(key) + if !ok || s == "" { + return false, nil + } + s, isCachedError := strings.CutPrefix(s, cachedErrorPrefix) + if isCachedError { + return true, &GetJSONError{cachedError: s} + } + if err := json.Unmarshal(util.UnsafeStringToBytes(s), ptr); err != nil { + return false, &GetJSONError{err: err} + } + return true, nil +} + +func (sc *stringCache) ChiCache() chi_cache.Cache { + return sc.chiCache +} diff --git a/modules/charset/escape_test.go b/modules/charset/escape_test.go index a353ced631..9d796a0c18 100644 --- a/modules/charset/escape_test.go +++ b/modules/charset/escape_test.go @@ -4,6 +4,7 @@ package charset import ( + "regexp" "strings" "testing" @@ -156,13 +157,16 @@ func TestEscapeControlReader(t *testing.T) { tests = append(tests, test) } + re := regexp.MustCompile(`repo.ambiguous_character:\d+,\d+`) // simplify the output for the tests, remove the translation variants for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { output := &strings.Builder{} status, err := EscapeControlReader(strings.NewReader(tt.text), output, &translation.MockLocale{}) assert.NoError(t, err) assert.Equal(t, tt.status, *status) - assert.Equal(t, tt.result, output.String()) + outStr := output.String() + outStr = re.ReplaceAllString(outStr, "repo.ambiguous_character") + assert.Equal(t, tt.result, outStr) }) } } diff --git a/modules/container/filter.go b/modules/container/filter.go new file mode 100644 index 0000000000..37ec7c3d56 --- /dev/null +++ b/modules/container/filter.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package container + +import "slices" + +// FilterSlice ranges over the slice and calls include() for each element. +// If the second returned value is true, the first returned value will be included in the resulting +// slice (after deduplication). +func FilterSlice[E any, T comparable](s []E, include func(E) (T, bool)) []T { + filtered := make([]T, 0, len(s)) // slice will be clipped before returning + seen := make(map[T]bool, len(s)) + for i := range s { + if v, ok := include(s[i]); ok && !seen[v] { + filtered = append(filtered, v) + seen[v] = true + } + } + return slices.Clip(filtered) +} diff --git a/modules/container/filter_test.go b/modules/container/filter_test.go new file mode 100644 index 0000000000..ad304e5abb --- /dev/null +++ b/modules/container/filter_test.go @@ -0,0 +1,28 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package container + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFilterMapUnique(t *testing.T) { + result := FilterSlice([]int{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + }, func(i int) (int, bool) { + switch i { + case 0: + return 0, true // included later + case 1: + return 0, true // duplicate of previous (should be ignored) + case 2: + return 2, false // not included + default: + return i, true + } + }) + assert.Equal(t, []int{0, 3, 4, 5, 6, 7, 8, 9}, result) +} diff --git a/modules/csv/csv_test.go b/modules/csv/csv_test.go index f6e782a5a4..3ddb47acbb 100644 --- a/modules/csv/csv_test.go +++ b/modules/csv/csv_test.go @@ -561,14 +561,14 @@ func TestFormatError(t *testing.T) { err: &csv.ParseError{ Err: csv.ErrFieldCount, }, - expectedMessage: "repo.error.csv.invalid_field_count", + expectedMessage: "repo.error.csv.invalid_field_count:0", expectsError: false, }, { err: &csv.ParseError{ Err: csv.ErrBareQuote, }, - expectedMessage: "repo.error.csv.unexpected", + expectedMessage: "repo.error.csv.unexpected:0,0", expectsError: false, }, { diff --git a/modules/dump/dumper.go b/modules/dump/dumper.go new file mode 100644 index 0000000000..47730851fb --- /dev/null +++ b/modules/dump/dumper.go @@ -0,0 +1,174 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package dump + +import ( + "fmt" + "io" + "os" + "path" + "path/filepath" + "slices" + "strings" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" + + "github.com/mholt/archiver/v3" +) + +var SupportedOutputTypes = []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4", "tar.zst"} + +// PrepareFileNameAndType prepares the output file name and type, if the type is not supported, it returns an empty "outType" +func PrepareFileNameAndType(argFile, argType string) (outFileName, outType string) { + if argFile == "" && argType == "" { + outType = SupportedOutputTypes[0] + outFileName = fmt.Sprintf("gitea-dump-%d.%s", timeutil.TimeStampNow(), outType) + } else if argFile == "" { + outType = argType + outFileName = fmt.Sprintf("gitea-dump-%d.%s", timeutil.TimeStampNow(), outType) + } else if argType == "" { + if filepath.Ext(outFileName) == "" { + outType = SupportedOutputTypes[0] + outFileName = argFile + } else { + for _, t := range SupportedOutputTypes { + if strings.HasSuffix(argFile, "."+t) { + outFileName = argFile + outType = t + } + } + } + } else { + outFileName, outType = argFile, argType + } + if !slices.Contains(SupportedOutputTypes, outType) { + return "", "" + } + return outFileName, outType +} + +func IsSubdir(upper, lower string) (bool, error) { + if relPath, err := filepath.Rel(upper, lower); err != nil { + return false, err + } else if relPath == "." || !strings.HasPrefix(relPath, ".") { + return true, nil + } + return false, nil +} + +type Dumper struct { + Writer archiver.Writer + Verbose bool + + globalExcludeAbsPaths []string +} + +func (dumper *Dumper) AddReader(r io.ReadCloser, info os.FileInfo, customName string) error { + if dumper.Verbose { + log.Info("Adding file %s", customName) + } + + return dumper.Writer.Write(archiver.File{ + FileInfo: archiver.FileInfo{ + FileInfo: info, + CustomName: customName, + }, + ReadCloser: r, + }) +} + +func (dumper *Dumper) AddFile(filePath, absPath string) error { + file, err := os.Open(absPath) + if err != nil { + return err + } + defer file.Close() + fileInfo, err := file.Stat() + if err != nil { + return err + } + return dumper.AddReader(file, fileInfo, filePath) +} + +func (dumper *Dumper) normalizeFilePath(absPath string) string { + absPath = filepath.Clean(absPath) + if setting.IsWindows { + absPath = strings.ToLower(absPath) + } + return absPath +} + +func (dumper *Dumper) GlobalExcludeAbsPath(absPaths ...string) { + for _, absPath := range absPaths { + dumper.globalExcludeAbsPaths = append(dumper.globalExcludeAbsPaths, dumper.normalizeFilePath(absPath)) + } +} + +func (dumper *Dumper) shouldExclude(absPath string, excludes []string) bool { + norm := dumper.normalizeFilePath(absPath) + return slices.Contains(dumper.globalExcludeAbsPaths, norm) || slices.Contains(excludes, norm) +} + +func (dumper *Dumper) AddRecursiveExclude(insidePath, absPath string, excludes []string) error { + excludes = slices.Clone(excludes) + for i := range excludes { + excludes[i] = dumper.normalizeFilePath(excludes[i]) + } + return dumper.addFileOrDir(insidePath, absPath, excludes) +} + +func (dumper *Dumper) addFileOrDir(insidePath, absPath string, excludes []string) error { + absPath, err := filepath.Abs(absPath) + if err != nil { + return err + } + dir, err := os.Open(absPath) + if err != nil { + return err + } + defer dir.Close() + + files, err := dir.Readdir(0) + if err != nil { + return err + } + for _, file := range files { + currentAbsPath := filepath.Join(absPath, file.Name()) + if dumper.shouldExclude(currentAbsPath, excludes) { + continue + } + + currentInsidePath := path.Join(insidePath, file.Name()) + if file.IsDir() { + if err := dumper.AddFile(currentInsidePath, currentAbsPath); err != nil { + return err + } + if err = dumper.addFileOrDir(currentInsidePath, currentAbsPath, excludes); err != nil { + return err + } + } else { + // only copy regular files and symlink regular files, skip non-regular files like socket/pipe/... + shouldAdd := file.Mode().IsRegular() + if !shouldAdd && file.Mode()&os.ModeSymlink == os.ModeSymlink { + target, err := filepath.EvalSymlinks(currentAbsPath) + if err != nil { + return err + } + targetStat, err := os.Stat(target) + if err != nil { + return err + } + shouldAdd = targetStat.Mode().IsRegular() + } + if shouldAdd { + if err = dumper.AddFile(currentInsidePath, currentAbsPath); err != nil { + return err + } + } + } + } + return nil +} diff --git a/modules/dump/dumper_test.go b/modules/dump/dumper_test.go new file mode 100644 index 0000000000..b444fa2de5 --- /dev/null +++ b/modules/dump/dumper_test.go @@ -0,0 +1,113 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package dump + +import ( + "fmt" + "io" + "os" + "path/filepath" + "sort" + "testing" + "time" + + "code.gitea.io/gitea/modules/timeutil" + + "github.com/mholt/archiver/v3" + "github.com/stretchr/testify/assert" +) + +func TestPrepareFileNameAndType(t *testing.T) { + defer timeutil.MockSet(time.Unix(1234, 0))() + test := func(argFile, argType, expFile, expType string) { + outFile, outType := PrepareFileNameAndType(argFile, argType) + assert.Equal(t, + fmt.Sprintf("outFile=%s, outType=%s", expFile, expType), + fmt.Sprintf("outFile=%s, outType=%s", outFile, outType), + fmt.Sprintf("argFile=%s, argType=%s", argFile, argType), + ) + } + + test("", "", "gitea-dump-1234.zip", "zip") + test("", "tar.gz", "gitea-dump-1234.tar.gz", "tar.gz") + test("", "no-such", "", "") + + test("-", "", "-", "zip") + test("-", "tar.gz", "-", "tar.gz") + test("-", "no-such", "", "") + + test("a", "", "a", "zip") + test("a", "tar.gz", "a", "tar.gz") + test("a", "no-such", "", "") + + test("a.zip", "", "a.zip", "zip") + test("a.zip", "tar.gz", "a.zip", "tar.gz") + test("a.zip", "no-such", "", "") + + test("a.tar.gz", "", "a.tar.gz", "zip") + test("a.tar.gz", "tar.gz", "a.tar.gz", "tar.gz") + test("a.tar.gz", "no-such", "", "") +} + +func TestIsSubDir(t *testing.T) { + tmpDir := t.TempDir() + _ = os.MkdirAll(filepath.Join(tmpDir, "include/sub"), 0o755) + + isSub, err := IsSubdir(filepath.Join(tmpDir, "include"), filepath.Join(tmpDir, "include")) + assert.NoError(t, err) + assert.True(t, isSub) + + isSub, err = IsSubdir(filepath.Join(tmpDir, "include"), filepath.Join(tmpDir, "include/sub")) + assert.NoError(t, err) + assert.True(t, isSub) + + isSub, err = IsSubdir(filepath.Join(tmpDir, "include/sub"), filepath.Join(tmpDir, "include")) + assert.NoError(t, err) + assert.False(t, isSub) +} + +type testWriter struct { + added []string +} + +func (t *testWriter) Create(out io.Writer) error { + return nil +} + +func (t *testWriter) Write(f archiver.File) error { + t.added = append(t.added, f.Name()) + return nil +} + +func (t *testWriter) Close() error { + return nil +} + +func TestDumper(t *testing.T) { + sortStrings := func(s []string) []string { + sort.Strings(s) + return s + } + tmpDir := t.TempDir() + _ = os.MkdirAll(filepath.Join(tmpDir, "include/exclude1"), 0o755) + _ = os.MkdirAll(filepath.Join(tmpDir, "include/exclude2"), 0o755) + _ = os.MkdirAll(filepath.Join(tmpDir, "include/sub"), 0o755) + _ = os.WriteFile(filepath.Join(tmpDir, "include/a"), nil, 0o644) + _ = os.WriteFile(filepath.Join(tmpDir, "include/sub/b"), nil, 0o644) + _ = os.WriteFile(filepath.Join(tmpDir, "include/exclude1/a-1"), nil, 0o644) + _ = os.WriteFile(filepath.Join(tmpDir, "include/exclude2/a-2"), nil, 0o644) + + tw := &testWriter{} + d := &Dumper{Writer: tw} + d.GlobalExcludeAbsPath(filepath.Join(tmpDir, "include/exclude1")) + err := d.AddRecursiveExclude("include", filepath.Join(tmpDir, "include"), []string{filepath.Join(tmpDir, "include/exclude2")}) + assert.NoError(t, err) + assert.EqualValues(t, sortStrings([]string{"include/a", "include/sub", "include/sub/b"}), sortStrings(tw.added)) + + tw = &testWriter{} + d = &Dumper{Writer: tw} + err = d.AddRecursiveExclude("include", filepath.Join(tmpDir, "include"), nil) + assert.NoError(t, err) + assert.EqualValues(t, sortStrings([]string{"include/exclude2", "include/exclude2/a-2", "include/a", "include/sub", "include/sub/b", "include/exclude1", "include/exclude1/a-1"}), sortStrings(tw.added)) +} diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go index 043dbb44bd..c988d6ab86 100644 --- a/modules/git/batch_reader.go +++ b/modules/git/batch_reader.go @@ -307,10 +307,10 @@ func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBu // Deal with the binary hash idx = 0 - len := objectFormat.FullLength() / 2 - for idx < len { + length := objectFormat.FullLength() / 2 + for idx < length { var read int - read, err = rd.Read(shaBuf[idx:len]) + read, err = rd.Read(shaBuf[idx:length]) n += read if err != nil { return mode, fname, sha, n, err diff --git a/modules/git/blame_sha256_test.go b/modules/git/blame_sha256_test.go index 01de0454a3..8cd345714f 100644 --- a/modules/git/blame_sha256_test.go +++ b/modules/git/blame_sha256_test.go @@ -118,11 +118,12 @@ func TestReadingBlameOutputSha256(t *testing.T) { }, } + objectFormat, err := repo.GetObjectFormat() + assert.NoError(t, err) for _, c := range cases { commit, err := repo.GetCommit(c.CommitID) assert.NoError(t, err) - - blameReader, err := CreateBlameReader(ctx, repo.objectFormat, "./tests/repos/repo6_blame_sha256", commit, "blame.txt", c.Bypass) + blameReader, err := CreateBlameReader(ctx, objectFormat, "./tests/repos/repo6_blame_sha256", commit, "blame.txt", c.Bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() diff --git a/modules/git/blame_test.go b/modules/git/blame_test.go index 327edab767..4220c85600 100644 --- a/modules/git/blame_test.go +++ b/modules/git/blame_test.go @@ -118,11 +118,13 @@ func TestReadingBlameOutput(t *testing.T) { }, } + objectFormat, err := repo.GetObjectFormat() + assert.NoError(t, err) for _, c := range cases { commit, err := repo.GetCommit(c.CommitID) assert.NoError(t, err) - blameReader, err := CreateBlameReader(ctx, repo.objectFormat, "./tests/repos/repo6_blame", commit, "blame.txt", c.Bypass) + blameReader, err := CreateBlameReader(ctx, objectFormat, "./tests/repos/repo6_blame", commit, "blame.txt", c.Bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() diff --git a/modules/git/command.go b/modules/git/command.go index 371109730a..22cb275ab2 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -367,7 +367,6 @@ type RunStdError interface { error Unwrap() error Stderr() string - IsExitCode(code int) bool } type runStdError struct { @@ -392,9 +391,9 @@ func (r *runStdError) Stderr() string { return r.stderr } -func (r *runStdError) IsExitCode(code int) bool { +func IsErrorExitCode(err error, code int) bool { var exitError *exec.ExitError - if errors.As(r.err, &exitError) { + if errors.As(err, &exitError) { return exitError.ExitCode() == code } return false diff --git a/modules/git/commit.go b/modules/git/commit.go index 5d960e92f3..d96cef37c8 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "errors" + "fmt" "io" "os/exec" "strconv" @@ -25,14 +26,14 @@ type Commit struct { Author *Signature Committer *Signature CommitMessage string - Signature *CommitGPGSignature + Signature *CommitSignature Parents []ObjectID // ID strings submoduleCache *ObjectCache } -// CommitGPGSignature represents a git commit signature part. -type CommitGPGSignature struct { +// CommitSignature represents a git commit signature part. +type CommitSignature struct { Signature string Payload string // TODO check if can be reconstruct from the rest of commit information to not have duplicate data } @@ -311,7 +312,7 @@ func (c *Commit) GetFilesChangedSinceCommit(pastCommit string) ([]string, error) return c.repo.GetFilesChangedBetween(pastCommit, c.ID.String()) } -// FileChangedSinceCommit Returns true if the file given has changed since the the past commit +// FileChangedSinceCommit Returns true if the file given has changed since the past commit // YOU MUST ENSURE THAT pastCommit is a valid commit ID. func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) { return c.repo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String()) @@ -396,6 +397,9 @@ func (c *Commit) GetSubModules() (*ObjectCache, error) { } } } + if err = scanner.Err(); err != nil { + return nil, fmt.Errorf("GetSubModules scan: %w", err) + } return c.submoduleCache, nil } @@ -464,7 +468,7 @@ func parseCommitFileStatus(fileStatus *CommitFileStatus, stdout io.Reader) { _, _ = rd.Discard(1) } for { - modifier, err := rd.ReadSlice('\x00') + modifier, err := rd.ReadString('\x00') if err != nil { if err != io.EOF { log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err) diff --git a/modules/git/commit_convert_gogit.go b/modules/git/commit_convert_gogit.go index 819ea0d1db..d7b945ed6b 100644 --- a/modules/git/commit_convert_gogit.go +++ b/modules/git/commit_convert_gogit.go @@ -13,7 +13,7 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" ) -func convertPGPSignature(c *object.Commit) *CommitGPGSignature { +func convertPGPSignature(c *object.Commit) *CommitSignature { if c.PGPSignature == "" { return nil } @@ -47,11 +47,17 @@ func convertPGPSignature(c *object.Commit) *CommitGPGSignature { return nil } + if c.Encoding != "" && c.Encoding != "UTF-8" { + if _, err = fmt.Fprintf(&w, "\nencoding %s\n", c.Encoding); err != nil { + return nil + } + } + if _, err = fmt.Fprintf(&w, "\n\n%s", c.Message); err != nil { return nil } - return &CommitGPGSignature{ + return &CommitSignature{ Signature: c.PGPSignature, Payload: w.String(), } diff --git a/modules/git/commit_reader.go b/modules/git/commit_reader.go index 4809d6c7ed..228bbaf314 100644 --- a/modules/git/commit_reader.go +++ b/modules/git/commit_reader.go @@ -49,9 +49,8 @@ readLoop: if len(line) > 0 && line[0] == ' ' { _, _ = signatureSB.Write(line[1:]) continue - } else { - pgpsig = false } + pgpsig = false } if !message { @@ -84,6 +83,8 @@ readLoop: commit.Committer = &Signature{} commit.Committer.Decode(data) _, _ = payloadSB.Write(line) + case "encoding": + _, _ = payloadSB.Write(line) case "gpgsig": fallthrough case "gpgsig-sha256": // FIXME: no intertop, so only 1 exists at present. @@ -97,7 +98,7 @@ readLoop: } } commit.CommitMessage = messageSB.String() - commit.Signature = &CommitGPGSignature{ + commit.Signature = &CommitSignature{ Signature: signatureSB.String(), Payload: payloadSB.String(), } diff --git a/modules/git/commit_sha256_test.go b/modules/git/commit_sha256_test.go index 82112cb409..3b8b6d3763 100644 --- a/modules/git/commit_sha256_test.go +++ b/modules/git/commit_sha256_test.go @@ -140,10 +140,13 @@ func TestHasPreviousCommitSha256(t *testing.T) { commit, err := repo.GetCommit("f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc") assert.NoError(t, err) + objectFormat, err := repo.GetObjectFormat() + assert.NoError(t, err) + parentSHA := MustIDFromString("b0ec7af4547047f12d5093e37ef8f1b3b5415ed8ee17894d43a34d7d34212e9c") notParentSHA := MustIDFromString("42e334efd04cd36eea6da0599913333c26116e1a537ca76e5b6e4af4dda00236") - assert.Equal(t, repo.objectFormat, parentSHA.Type()) - assert.Equal(t, repo.objectFormat.Name(), "sha256") + assert.Equal(t, objectFormat, parentSHA.Type()) + assert.Equal(t, objectFormat.Name(), "sha256") haz, err := commit.HasPreviousCommit(parentSHA) assert.NoError(t, err) diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go index e512eecc56..a33e7df31a 100644 --- a/modules/git/commit_test.go +++ b/modules/git/commit_test.go @@ -125,6 +125,73 @@ empty commit`, commitFromReader.Signature.Payload) assert.EqualValues(t, commitFromReader, commitFromReader2) } +func TestCommitWithEncodingFromReader(t *testing.T) { + commitString := `feaf4ba6bc635fec442f46ddd4512416ec43c2c2 commit 1074 +tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5 +parent 47b24e7ab977ed31c5a39989d570847d6d0052af +author KN4CK3R 1711702962 +0100 +committer KN4CK3R 1711702962 +0100 +encoding ISO-8859-1 +gpgsig -----BEGIN PGP SIGNATURE----- + + iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow + Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR + gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq + zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr + frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j + FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd + G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn + SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F + yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz + jw4YcO5u + =r3UU + -----END PGP SIGNATURE----- + +ISO-8859-1` + + sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2} + gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + assert.NoError(t, err) + assert.NotNil(t, gitRepo) + defer gitRepo.Close() + + commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString)) + assert.NoError(t, err) + if !assert.NotNil(t, commitFromReader) { + return + } + assert.EqualValues(t, sha, commitFromReader.ID) + assert.EqualValues(t, `-----BEGIN PGP SIGNATURE----- + +iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow +Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR +gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq +zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr +frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j +FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd +G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn +SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F +yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz +jw4YcO5u +=r3UU +-----END PGP SIGNATURE----- +`, commitFromReader.Signature.Signature) + assert.EqualValues(t, `tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5 +parent 47b24e7ab977ed31c5a39989d570847d6d0052af +author KN4CK3R 1711702962 +0100 +committer KN4CK3R 1711702962 +0100 +encoding ISO-8859-1 + +ISO-8859-1`, commitFromReader.Signature.Payload) + assert.EqualValues(t, "KN4CK3R ", commitFromReader.Author.String()) + + commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n")) + assert.NoError(t, err) + commitFromReader.CommitMessage += "\n\n" + commitFromReader.Signature.Payload += "\n\n" + assert.EqualValues(t, commitFromReader, commitFromReader2) +} + func TestHasPreviousCommit(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") diff --git a/modules/git/git.go b/modules/git/git.go index f688ea7488..e411269f7c 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -341,7 +341,7 @@ func checkGitVersionCompatibility(gitVer *version.Version) error { func configSet(key, value string) error { stdout, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil) - if err != nil && !err.IsExitCode(1) { + if err != nil && !IsErrorExitCode(err, 1) { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } @@ -364,7 +364,7 @@ func configSetNonExist(key, value string) error { // already exist return nil } - if err.IsExitCode(1) { + if IsErrorExitCode(err, 1) { // not exist, set new config _, _, err = NewCommand(DefaultContext, "config", "--global").AddDynamicArguments(key, value).RunStdString(nil) if err != nil { @@ -382,7 +382,7 @@ func configAddNonExist(key, value string) error { // already exist return nil } - if err.IsExitCode(1) { + if IsErrorExitCode(err, 1) { // not exist, add new config _, _, err = NewCommand(DefaultContext, "config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(nil) if err != nil { @@ -403,7 +403,7 @@ func configUnsetAll(key, value string) error { } return nil } - if err.IsExitCode(1) { + if IsErrorExitCode(err, 1) { // not exist return nil } diff --git a/modules/git/grep.go b/modules/git/grep.go new file mode 100644 index 0000000000..e7d238e586 --- /dev/null +++ b/modules/git/grep.go @@ -0,0 +1,130 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +import ( + "bufio" + "bytes" + "context" + "errors" + "fmt" + "os" + "slices" + "strconv" + "strings" + + "code.gitea.io/gitea/modules/util" +) + +type GrepResult struct { + Filename string + LineNumbers []int + LineCodes []string +} + +type GrepOptions struct { + RefName string + MaxResultLimit int + ContextLineNumber int + IsFuzzy bool + MaxLineLength int // the maximum length of a line to parse, exceeding chars will be truncated +} + +func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepOptions) ([]*GrepResult, error) { + stdoutReader, stdoutWriter, err := os.Pipe() + if err != nil { + return nil, fmt.Errorf("unable to create os pipe to grep: %w", err) + } + defer func() { + _ = stdoutReader.Close() + _ = stdoutWriter.Close() + }() + + /* + The output is like this ( "^@" means \x00): + + HEAD:.air.toml + 6^@bin = "gitea" + + HEAD:.changelog.yml + 2^@repo: go-gitea/gitea + */ + var results []*GrepResult + cmd := NewCommand(ctx, "grep", "--null", "--break", "--heading", "--fixed-strings", "--line-number", "--ignore-case", "--full-name") + cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber)) + if opts.IsFuzzy { + words := strings.Fields(search) + for _, word := range words { + cmd.AddOptionValues("-e", strings.TrimLeft(word, "-")) + } + } else { + cmd.AddOptionValues("-e", strings.TrimLeft(search, "-")) + } + cmd.AddDynamicArguments(util.IfZero(opts.RefName, "HEAD")) + opts.MaxResultLimit = util.IfZero(opts.MaxResultLimit, 50) + stderr := bytes.Buffer{} + err = cmd.Run(&RunOpts{ + Dir: repo.Path, + Stdout: stdoutWriter, + Stderr: &stderr, + PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { + _ = stdoutWriter.Close() + defer stdoutReader.Close() + + isInBlock := false + rd := bufio.NewReaderSize(stdoutReader, util.IfZero(opts.MaxLineLength, 16*1024)) + var res *GrepResult + for { + lineBytes, isPrefix, err := rd.ReadLine() + if isPrefix { + lineBytes = slices.Clone(lineBytes) + for isPrefix && err == nil { + _, isPrefix, err = rd.ReadLine() + } + } + if len(lineBytes) == 0 && err != nil { + break + } + line := string(lineBytes) // the memory of lineBytes is mutable + if !isInBlock { + if _ /* ref */, filename, ok := strings.Cut(line, ":"); ok { + isInBlock = true + res = &GrepResult{Filename: filename} + results = append(results, res) + } + continue + } + if line == "" { + if len(results) >= opts.MaxResultLimit { + cancel() + break + } + isInBlock = false + continue + } + if line == "--" { + continue + } + if lineNum, lineCode, ok := strings.Cut(line, "\x00"); ok { + lineNumInt, _ := strconv.Atoi(lineNum) + res.LineNumbers = append(res.LineNumbers, lineNumInt) + res.LineCodes = append(res.LineCodes, lineCode) + } + } + return nil + }, + }) + // git grep exits by cancel (killed), usually it is caused by the limit of results + if IsErrorExitCode(err, -1) && stderr.Len() == 0 { + return results, nil + } + // git grep exits with 1 if no results are found + if IsErrorExitCode(err, 1) && stderr.Len() == 0 { + return nil, nil + } + if err != nil && !errors.Is(err, context.Canceled) { + return nil, fmt.Errorf("unable to run git grep: %w, stderr: %s", err, stderr.String()) + } + return results, nil +} diff --git a/modules/git/grep_test.go b/modules/git/grep_test.go new file mode 100644 index 0000000000..7f4ded478f --- /dev/null +++ b/modules/git/grep_test.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +import ( + "context" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGrepSearch(t *testing.T) { + repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "language_stats_repo")) + assert.NoError(t, err) + defer repo.Close() + + res, err := GrepSearch(context.Background(), repo, "void", GrepOptions{}) + assert.NoError(t, err) + assert.Equal(t, []*GrepResult{ + { + Filename: "java-hello/main.java", + LineNumbers: []int{3}, + LineCodes: []string{" public static void main(String[] args)"}, + }, + { + Filename: "main.vendor.java", + LineNumbers: []int{3}, + LineCodes: []string{" public static void main(String[] args)"}, + }, + }, res) + + res, err = GrepSearch(context.Background(), repo, "void", GrepOptions{MaxResultLimit: 1}) + assert.NoError(t, err) + assert.Equal(t, []*GrepResult{ + { + Filename: "java-hello/main.java", + LineNumbers: []int{3}, + LineCodes: []string{" public static void main(String[] args)"}, + }, + }, res) + + res, err = GrepSearch(context.Background(), repo, "void", GrepOptions{MaxResultLimit: 1, MaxLineLength: 39}) + assert.NoError(t, err) + assert.Equal(t, []*GrepResult{ + { + Filename: "java-hello/main.java", + LineNumbers: []int{3}, + LineCodes: []string{" public static void main(String[] arg"}, + }, + }, res) + + res, err = GrepSearch(context.Background(), repo, "no-such-content", GrepOptions{}) + assert.NoError(t, err) + assert.Len(t, res, 0) + + res, err = GrepSearch(context.Background(), &Repository{Path: "no-such-git-repo"}, "no-such-content", GrepOptions{}) + assert.Error(t, err) + assert.Len(t, res, 0) +} diff --git a/modules/git/last_commit_cache.go b/modules/git/last_commit_cache.go index 5b62b90b27..cf9c10d7b4 100644 --- a/modules/git/last_commit_cache.go +++ b/modules/git/last_commit_cache.go @@ -7,18 +7,11 @@ import ( "crypto/sha256" "fmt" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) -// Cache represents a caching interface -type Cache interface { - // Put puts value into cache with key and expire time. - Put(key string, val any, timeout int64) error - // Get gets cached value by given key. - Get(key string) any -} - func getCacheKey(repoPath, commitID, entryPath string) string { hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, commitID, entryPath))) return fmt.Sprintf("last_commit:%x", hashBytes) @@ -30,11 +23,11 @@ type LastCommitCache struct { ttl func() int64 repo *Repository commitCache map[string]*Commit - cache Cache + cache cache.StringCache } // NewLastCommitCache creates a new last commit cache for repo -func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache Cache) *LastCommitCache { +func NewLastCommitCache(count int64, repoPath string, gitRepo *Repository, cache cache.StringCache) *LastCommitCache { if cache == nil { return nil } @@ -65,7 +58,7 @@ func (c *LastCommitCache) Get(ref, entryPath string) (*Commit, error) { return nil, nil } - commitID, ok := c.cache.Get(getCacheKey(c.repoPath, ref, entryPath)).(string) + commitID, ok := c.cache.Get(getCacheKey(c.repoPath, ref, entryPath)) if !ok || commitID == "" { return nil, nil } diff --git a/modules/git/object_format.go b/modules/git/object_format.go index a056b20e8a..3de9ff8cf4 100644 --- a/modules/git/object_format.go +++ b/modules/git/object_format.go @@ -33,7 +33,6 @@ type ObjectFormat interface { ComputeHash(t ObjectType, content []byte) ObjectID } -/* SHA1 Type */ type Sha1ObjectFormatImpl struct{} var ( @@ -70,14 +69,10 @@ func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID _, _ = hasher.Write([]byte(" ")) _, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10))) _, _ = hasher.Write([]byte{0}) - - // HashSum generates a SHA1 for the provided hash - var sha1 Sha1Hash - copy(sha1[:], hasher.Sum(nil)) - return &sha1 + _, _ = hasher.Write(content) + return h.MustID(hasher.Sum(nil)) } -/* SHA256 Type */ type Sha256ObjectFormatImpl struct{} var ( @@ -116,11 +111,8 @@ func (h Sha256ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) Object _, _ = hasher.Write([]byte(" ")) _, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10))) _, _ = hasher.Write([]byte{0}) - - // HashSum generates a SHA256 for the provided hash - var sha256 Sha1Hash - copy(sha256[:], hasher.Sum(nil)) - return &sha256 + _, _ = hasher.Write(content) + return h.MustID(hasher.Sum(nil)) } var ( diff --git a/modules/git/object_id.go b/modules/git/object_id.go index 4f8c39ee1d..33e5085005 100644 --- a/modules/git/object_id.go +++ b/modules/git/object_id.go @@ -16,7 +16,6 @@ type ObjectID interface { Type() ObjectFormat } -/* SHA1 */ type Sha1Hash [20]byte func (h *Sha1Hash) String() string { @@ -40,7 +39,6 @@ func MustIDFromString(hexHash string) ObjectID { return id } -/* SHA256 */ type Sha256Hash [32]byte func (h *Sha256Hash) String() string { @@ -54,7 +52,6 @@ func (h *Sha256Hash) IsZero() bool { func (h *Sha256Hash) RawValue() []byte { return h[:] } func (*Sha256Hash) Type() ObjectFormat { return Sha256ObjectFormat } -/* utility */ func NewIDFromString(hexHash string) (ObjectID, error) { var theObjectFormat ObjectFormat for _, objectFormat := range SupportedObjectFormats { diff --git a/modules/git/object_id_test.go b/modules/git/object_id_test.go index 1ad40096a0..03d0c85d87 100644 --- a/modules/git/object_id_test.go +++ b/modules/git/object_id_test.go @@ -18,4 +18,8 @@ func TestIsValidSHAPattern(t *testing.T) { assert.False(t, h.IsValid("abc")) assert.False(t, h.IsValid("123g")) assert.False(t, h.IsValid("some random text")) + assert.Equal(t, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", ComputeBlobHash(Sha1ObjectFormat, nil).String()) + assert.Equal(t, "2e65efe2a145dda7ee51d1741299f848e5bf752e", ComputeBlobHash(Sha1ObjectFormat, []byte("a")).String()) + assert.Equal(t, "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813", ComputeBlobHash(Sha256ObjectFormat, nil).String()) + assert.Equal(t, "eb337bcee2061c5313c9a1392116b6c76039e9e30d71467ae359b36277e17dc7", ComputeBlobHash(Sha256ObjectFormat, []byte("a")).String()) } diff --git a/modules/git/pipeline/lfs_common.go b/modules/git/pipeline/lfs_common.go new file mode 100644 index 0000000000..188e7d4d65 --- /dev/null +++ b/modules/git/pipeline/lfs_common.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package pipeline + +import ( + "fmt" + "time" + + "code.gitea.io/gitea/modules/git" +) + +// LFSResult represents commits found using a provided pointer file hash +type LFSResult struct { + Name string + SHA string + Summary string + When time.Time + ParentHashes []git.ObjectID + BranchName string + FullCommitName string +} + +type lfsResultSlice []*LFSResult + +func (a lfsResultSlice) Len() int { return len(a) } +func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) } + +func lfsError(msg string, err error) error { + return fmt.Errorf("LFS error occurred, %s: err: %w", msg, err) +} diff --git a/modules/git/pipeline/lfs.go b/modules/git/pipeline/lfs_gogit.go similarity index 80% rename from modules/git/pipeline/lfs.go rename to modules/git/pipeline/lfs_gogit.go index 6dfca24f29..adcf8ed09c 100644 --- a/modules/git/pipeline/lfs.go +++ b/modules/git/pipeline/lfs_gogit.go @@ -7,12 +7,10 @@ package pipeline import ( "bufio" - "fmt" "io" "sort" "strings" "sync" - "time" "code.gitea.io/gitea/modules/git" @@ -21,23 +19,6 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" ) -// LFSResult represents commits found using a provided pointer file hash -type LFSResult struct { - Name string - SHA string - Summary string - When time.Time - ParentHashes []git.ObjectID - BranchName string - FullCommitName string -} - -type lfsResultSlice []*LFSResult - -func (a lfsResultSlice) Len() int { return len(a) } -func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) } - // FindLFSFile finds commits that contain a provided pointer file hash func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) { resultsMap := map[string]*LFSResult{} @@ -51,7 +32,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err All: true, }) if err != nil { - return nil, fmt.Errorf("Failed to get GoGit CommitsIter. Error: %w", err) + return nil, lfsError("failed to get GoGit CommitsIter", err) } err = commitsIter.ForEach(func(gitCommit *object.Commit) error { @@ -85,7 +66,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err return nil }) if err != nil && err != io.EOF { - return nil, fmt.Errorf("Failure in CommitIter.ForEach: %w", err) + return nil, lfsError("failure in CommitIter.ForEach", err) } for _, result := range resultsMap { @@ -156,7 +137,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err select { case err, has := <-errChan: if has { - return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err) + return nil, lfsError("unable to obtain name for LFS files", err) } default: } diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go index 4c65249089..349cfbd9ce 100644 --- a/modules/git/pipeline/lfs_nogogit.go +++ b/modules/git/pipeline/lfs_nogogit.go @@ -8,33 +8,14 @@ package pipeline import ( "bufio" "bytes" - "fmt" "io" "sort" "strings" "sync" - "time" "code.gitea.io/gitea/modules/git" ) -// LFSResult represents commits found using a provided pointer file hash -type LFSResult struct { - Name string - SHA string - Summary string - When time.Time - ParentIDs []git.ObjectID - BranchName string - FullCommitName string -} - -type lfsResultSlice []*LFSResult - -func (a lfsResultSlice) Len() int { return len(a) } -func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) } - // FindLFSFile finds commits that contain a provided pointer file hash func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) { resultsMap := map[string]*LFSResult{} @@ -137,11 +118,11 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err n += int64(count) if bytes.Equal(binObjectID, objectID.RawValue()) { result := LFSResult{ - Name: curPath + string(fname), - SHA: curCommit.ID.String(), - Summary: strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0], - When: curCommit.Author.When, - ParentIDs: curCommit.Parents, + Name: curPath + string(fname), + SHA: curCommit.ID.String(), + Summary: strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0], + When: curCommit.Author.When, + ParentHashes: curCommit.Parents, } resultsMap[curCommit.ID.String()+":"+curPath+string(fname)] = &result } else if string(mode) == git.EntryModeTree.String() { @@ -183,7 +164,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err for _, result := range resultsMap { hasParent := false - for _, parentID := range result.ParentIDs { + for _, parentID := range result.ParentHashes { if _, hasParent = resultsMap[parentID.String()+":"+result.Name]; hasParent { break } @@ -232,7 +213,6 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err errChan <- err break } - } }() @@ -241,7 +221,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err select { case err, has := <-errChan: if has { - return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err) + return nil, lfsError("unable to obtain name for LFS files", err) } default: } diff --git a/modules/git/repo.go b/modules/git/repo.go index cef45c6af0..4511e900e0 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -283,7 +283,7 @@ type DivergeObject struct { // GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) { cmd := NewCommand(ctx, "rev-list", "--count", "--left-right"). - AddDynamicArguments(baseBranch + "..." + targetBranch) + AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--") stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}) if err != nil { return do, err diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 7f6512200b..5511526e78 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -71,11 +71,6 @@ 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, repoPath) - repo.objectFormat, err = repo.GetObjectFormat() - if err != nil { - return nil, err - } - return repo, nil } diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 9c9ee7768f..f9168bef7e 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -246,18 +246,23 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) } }() - len := repo.objectFormat.FullLength() + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } + + length := objectFormat.FullLength() commits := []*Commit{} - shaline := make([]byte, len+1) + shaline := make([]byte, length+1) for { n, err := io.ReadFull(stdoutReader, shaline) - if err != nil || n < len { + if err != nil || n < length { if err == io.EOF { err = nil } return commits, err } - objectID, err := NewIDFromString(string(shaline[0:len])) + objectID, err := NewIDFromString(string(shaline[0:length])) if err != nil { return nil, err } diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index 4cab957564..84580be9a5 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -41,7 +41,10 @@ func (repo *Repository) RemoveReference(name string) error { // ConvertToHash returns a Hash object from a potential ID string func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) { - objectFormat := repo.objectFormat + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } if len(commitID) == hash.HexSize && objectFormat.IsValid(commitID) { ID, err := NewIDFromString(commitID) if err == nil { diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index a7031184e2..ae4c21aaa3 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -132,8 +132,11 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID) // ConvertToGitID returns a GitHash object from a potential ID string func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) { - IDType := repo.objectFormat - if len(commitID) == IDType.FullLength() && IDType.IsValid(commitID) { + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } + if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) { ID, err := NewIDFromString(commitID) if err == nil { return ID, nil @@ -142,7 +145,7 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) { wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx) defer cancel() - _, err := wr.Write([]byte(commitID + "\n")) + _, err = wr.Write([]byte(commitID + "\n")) if err != nil { return nil, err } diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 0e9a0c70d7..b6e9d2b44a 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -283,8 +283,12 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error { // If base is undefined empty SHA (zeros), it only returns the files changed in the head commit // If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) { + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z") - if base == repo.objectFormat.EmptyObjectID().String() { + if base == objectFormat.EmptyObjectID().String() { cmd.AddDynamicArguments(head) } else { cmd.AddDynamicArguments(base, head) diff --git a/modules/git/repo_compare_test.go b/modules/git/repo_compare_test.go index 526b213550..9983873186 100644 --- a/modules/git/repo_compare_test.go +++ b/modules/git/repo_compare_test.go @@ -126,17 +126,20 @@ func TestGetCommitFilesChanged(t *testing.T) { assert.NoError(t, err) defer repo.Close() + objectFormat, err := repo.GetObjectFormat() + assert.NoError(t, err) + testCases := []struct { base, head string files []string }{ { - repo.objectFormat.EmptyObjectID().String(), + objectFormat.EmptyObjectID().String(), "95bb4d39648ee7e325106df01a621c530863a653", []string{"file1.txt"}, }, { - repo.objectFormat.EmptyObjectID().String(), + objectFormat.EmptyObjectID().String(), "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", []string{"file2.txt"}, }, @@ -146,7 +149,7 @@ func TestGetCommitFilesChanged(t *testing.T) { []string{"file2.txt"}, }, { - repo.objectFormat.EmptyTree().String(), + objectFormat.EmptyTree().String(), "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", []string{"file1.txt", "file2.txt"}, }, diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 47705a92af..6aaab242c1 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -94,6 +94,10 @@ func (repo *Repository) LsFiles(filenames ...string) ([]string, error) { // RemoveFilesFromIndex removes given filenames from the index - it does not check whether they are present. func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return err + } cmd := NewCommand(repo.Ctx, "update-index", "--remove", "-z", "--index-info") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) @@ -101,7 +105,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { for _, file := range filenames { if file != "" { buffer.WriteString("0 ") - buffer.WriteString(repo.objectFormat.EmptyObjectID().String()) + buffer.WriteString(objectFormat.EmptyObjectID().String()) buffer.WriteByte('\t') buffer.WriteString(file) buffer.WriteByte('\000') diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index 41f94e24f9..83220104bd 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -124,6 +124,10 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) } } } + if err = scanner.Err(); err != nil { + _ = stdoutReader.Close() + return fmt.Errorf("GetCodeActivityStats scan: %w", err) + } a := make([]*CodeActivityAuthor, 0, len(authors)) for _, v := range authors { a = append(a, v) diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index ae5dbd171f..2026a4c9f5 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -141,7 +141,7 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) { break } - tag, err := parseTagRef(repo.objectFormat, ref) + tag, err := parseTagRef(ref) if err != nil { return nil, 0, fmt.Errorf("GetTagInfos: parse tag: %w", err) } @@ -161,7 +161,7 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) { } // parseTagRef parses a tag from a 'git for-each-ref'-produced reference. -func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, err error) { +func parseTagRef(ref map[string]string) (tag *Tag, err error) { tag = &Tag{ Type: ref["objecttype"], Name: ref["refname:lstrip=2"], @@ -185,17 +185,15 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er tag.Tagger = parseSignatureFromCommitLine(ref["creator"]) tag.Message = ref["contents"] - // strip PGP signature if present in contents field - pgpStart := strings.Index(tag.Message, beginpgp) - if pgpStart >= 0 { - tag.Message = tag.Message[0:pgpStart] - } + + // strip any signature if present in contents field + _, tag.Message, _ = parsePayloadSignature(util.UnsafeStringToBytes(tag.Message), 0) // annotated tag with GPG signature if tag.Type == "tag" && ref["contents:signature"] != "" { payload := fmt.Sprintf("object %s\ntype commit\ntag %s\ntagger %s\n\n%s\n", tag.Object, tag.Name, ref["creator"], strings.TrimSpace(tag.Message)) - tag.Signature = &CommitGPGSignature{ + tag.Signature = &CommitSignature{ Signature: ref["contents:signature"], Payload: payload, } diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go index 9816e311a8..0117cb902d 100644 --- a/modules/git/repo_tag_test.go +++ b/modules/git/repo_tag_test.go @@ -194,7 +194,6 @@ func TestRepository_GetAnnotatedTag(t *testing.T) { } func TestRepository_parseTagRef(t *testing.T) { - sha1 := Sha1ObjectFormat tests := []struct { name string @@ -316,7 +315,7 @@ qbHDASXl Type: "tag", Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"), Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md", - Signature: &CommitGPGSignature{ + Signature: &CommitSignature{ Signature: `-----BEGIN PGP SIGNATURE----- aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3 @@ -351,7 +350,7 @@ Add changelog of v1.9.1 (#7859) for _, test := range tests { tc := test // don't close over loop variable t.Run(tc.name, func(t *testing.T) { - got, err := parseTagRef(sha1, tc.givenRef) + got, err := parseTagRef(tc.givenRef) if tc.wantErr { require.Error(t, err) diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index 6391959e6a..dc97ce1344 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -21,7 +21,12 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { // GetTree find the tree object in the repository. func (repo *Repository) GetTree(idStr string) (*Tree, error) { - if len(idStr) != repo.objectFormat.FullLength() { + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } + + if len(idStr) != objectFormat.FullLength() { res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path}) if err != nil { return nil, err diff --git a/modules/git/repo_tree_nogogit.go b/modules/git/repo_tree_nogogit.go index 582247b4a4..e82012de6f 100644 --- a/modules/git/repo_tree_nogogit.go +++ b/modules/git/repo_tree_nogogit.go @@ -51,7 +51,11 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { case "tree": tree := NewTree(repo, id) tree.ResolvedID = id - tree.entries, err = catBatchParseTreeEntries(repo.objectFormat, tree, rd, size) + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } + tree.entries, err = catBatchParseTreeEntries(objectFormat, tree, rd, size) if err != nil { return nil, err } @@ -69,7 +73,11 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { // GetTree find the tree object in the repository. func (repo *Repository) GetTree(idStr string) (*Tree, error) { - if len(idStr) != repo.objectFormat.FullLength() { + objectFormat, err := repo.GetObjectFormat() + if err != nil { + return nil, err + } + if len(idStr) != objectFormat.FullLength() { res, err := repo.GetRefCommitID(idStr) if err != nil { return nil, err diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 37813ea4c7..b99c81582b 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -64,7 +64,6 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string { // ex: git@try.gitea.io:go-gitea/gitea match := scpSyntax.FindAllStringSubmatch(refURI, -1) if len(match) > 0 { - m := match[0] refHostname := m[2] pth := m[3] diff --git a/modules/git/tag.go b/modules/git/tag.go index 94e5cd7c63..f7666aa89b 100644 --- a/modules/git/tag.go +++ b/modules/git/tag.go @@ -6,16 +6,10 @@ package git import ( "bytes" "sort" - "strings" "code.gitea.io/gitea/modules/util" ) -const ( - beginpgp = "\n-----BEGIN PGP SIGNATURE-----\n" - endpgp = "\n-----END PGP SIGNATURE-----" -) - // Tag represents a Git tag. type Tag struct { Name string @@ -24,7 +18,7 @@ type Tag struct { Type string Tagger *Signature Message string - Signature *CommitGPGSignature + Signature *CommitSignature } // Commit return the commit of the tag reference @@ -32,6 +26,36 @@ func (tag *Tag) Commit(gitRepo *Repository) (*Commit, error) { return gitRepo.getCommit(tag.Object) } +func parsePayloadSignature(data []byte, messageStart int) (payload, msg, sign string) { + pos := messageStart + signStart, signEnd := -1, -1 + for { + eol := bytes.IndexByte(data[pos:], '\n') + if eol < 0 { + break + } + line := data[pos : pos+eol] + signType, hasPrefix := bytes.CutPrefix(line, []byte("-----BEGIN ")) + signType, hasSuffix := bytes.CutSuffix(signType, []byte(" SIGNATURE-----")) + if hasPrefix && hasSuffix { + signEndBytes := append([]byte("\n-----END "), signType...) + signEndBytes = append(signEndBytes, []byte(" SIGNATURE-----")...) + signEnd = bytes.Index(data[pos:], signEndBytes) + if signEnd != -1 { + signStart = pos + signEnd = pos + signEnd + len(signEndBytes) + } + } + pos += eol + 1 + } + + if signStart != -1 && signEnd != -1 { + msgEnd := max(messageStart, signStart-1) + return string(data[:msgEnd]), string(data[messageStart:msgEnd]), string(data[signStart:signEnd]) + } + return string(data), string(data[messageStart:]), "" +} + // Parse commit information from the (uncompressed) raw // data from the commit object. // \n\n separate headers from message @@ -40,47 +64,37 @@ func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) { tag.ID = objectFormat.EmptyObjectID() tag.Object = objectFormat.EmptyObjectID() tag.Tagger = &Signature{} - // we now have the contents of the commit object. Let's investigate... - nextline := 0 -l: + + pos := 0 for { - eol := bytes.IndexByte(data[nextline:], '\n') - switch { - case eol > 0: - line := data[nextline : nextline+eol] - spacepos := bytes.IndexByte(line, ' ') - reftype := line[:spacepos] - switch string(reftype) { - case "object": - id, err := NewIDFromString(string(line[spacepos+1:])) - if err != nil { - return nil, err - } - tag.Object = id - case "type": - // A commit can have one or more parents - tag.Type = string(line[spacepos+1:]) - case "tagger": - tag.Tagger = parseSignatureFromCommitLine(util.UnsafeBytesToString(line[spacepos+1:])) - } - nextline += eol + 1 - case eol == 0: - tag.Message = string(data[nextline+1:]) - break l - default: - break l + eol := bytes.IndexByte(data[pos:], '\n') + if eol == -1 { + break // shouldn't happen, but could just tolerate it } + if eol == 0 { + pos++ + break // end of headers + } + line := data[pos : pos+eol] + key, val, _ := bytes.Cut(line, []byte(" ")) + switch string(key) { + case "object": + id, err := NewIDFromString(string(val)) + if err != nil { + return nil, err + } + tag.Object = id + case "type": + tag.Type = string(val) // A commit can have one or more parents + case "tagger": + tag.Tagger = parseSignatureFromCommitLine(util.UnsafeBytesToString(val)) + } + pos += eol + 1 } - idx := strings.LastIndex(tag.Message, beginpgp) - if idx > 0 { - endSigIdx := strings.Index(tag.Message[idx:], endpgp) - if endSigIdx > 0 { - tag.Signature = &CommitGPGSignature{ - Signature: tag.Message[idx+1 : idx+endSigIdx+len(endpgp)], - Payload: string(data[:bytes.LastIndex(data, []byte(beginpgp))+1]), - } - tag.Message = tag.Message[:idx+1] - } + payload, msg, sign := parsePayloadSignature(data, pos) + tag.Message = msg + if len(sign) > 0 { + tag.Signature = &CommitSignature{Signature: sign, Payload: payload} } return tag, nil } diff --git a/modules/git/tag_test.go b/modules/git/tag_test.go index f980b0c560..ba02c28946 100644 --- a/modules/git/tag_test.go +++ b/modules/git/tag_test.go @@ -12,24 +12,28 @@ import ( func Test_parseTagData(t *testing.T) { testData := []struct { - data []byte - tag Tag + data string + expected Tag }{ - {data: []byte(`object 3b114ab800c6432ad42387ccf6bc8d4388a2885a + { + data: `object 3b114ab800c6432ad42387ccf6bc8d4388a2885a type commit tag 1.22.0 tagger Lucas Michot 1484491741 +0100 -`), tag: Tag{ - Name: "", - ID: Sha1ObjectFormat.EmptyObjectID(), - Object: &Sha1Hash{0x3b, 0x11, 0x4a, 0xb8, 0x0, 0xc6, 0x43, 0x2a, 0xd4, 0x23, 0x87, 0xcc, 0xf6, 0xbc, 0x8d, 0x43, 0x88, 0xa2, 0x88, 0x5a}, - Type: "commit", - Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)}, - Message: "", - Signature: nil, - }}, - {data: []byte(`object 7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc +`, + expected: Tag{ + Name: "", + ID: Sha1ObjectFormat.EmptyObjectID(), + Object: MustIDFromString("3b114ab800c6432ad42387ccf6bc8d4388a2885a"), + Type: "commit", + Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0).In(time.FixedZone("", 3600))}, + Message: "", + Signature: nil, + }, + }, + { + data: `object 7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc type commit tag 1.22.1 tagger Lucas Michot 1484553735 +0100 @@ -37,37 +41,57 @@ tagger Lucas Michot 1484553735 +0100 test message o -ono`), tag: Tag{ - Name: "", - ID: Sha1ObjectFormat.EmptyObjectID(), - Object: &Sha1Hash{0x7c, 0xdf, 0x42, 0xc0, 0xb1, 0xcc, 0x76, 0x3a, 0xb7, 0xe4, 0xc3, 0x3c, 0x47, 0xa2, 0x4e, 0x27, 0xc6, 0x6b, 0xfc, 0xcc}, - Type: "commit", - Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0)}, - Message: "test message\no\n\nono", - Signature: nil, - }}, +ono`, + expected: Tag{ + Name: "", + ID: Sha1ObjectFormat.EmptyObjectID(), + Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"), + Type: "commit", + Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0).In(time.FixedZone("", 3600))}, + Message: "test message\no\n\nono", + Signature: nil, + }, + }, + { + data: `object 7cdf42c0b1cc763ab7e4c33c47a24e27c66bfaaa +type commit +tag v0 +tagger dummy user 1484491741 +0100 + +dummy message +-----BEGIN SSH SIGNATURE----- +dummy signature +-----END SSH SIGNATURE----- +`, + expected: Tag{ + Name: "", + ID: Sha1ObjectFormat.EmptyObjectID(), + Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfaaa"), + Type: "commit", + Tagger: &Signature{Name: "dummy user", Email: "dummy-email@example.com", When: time.Unix(1484491741, 0).In(time.FixedZone("", 3600))}, + Message: "dummy message", + Signature: &CommitSignature{ + Signature: `-----BEGIN SSH SIGNATURE----- +dummy signature +-----END SSH SIGNATURE-----`, + Payload: `object 7cdf42c0b1cc763ab7e4c33c47a24e27c66bfaaa +type commit +tag v0 +tagger dummy user 1484491741 +0100 + +dummy message`, + }, + }, + }, } for _, test := range testData { - tag, err := parseTagData(Sha1ObjectFormat, test.data) + tag, err := parseTagData(Sha1ObjectFormat, []byte(test.data)) assert.NoError(t, err) - assert.EqualValues(t, test.tag.ID, tag.ID) - assert.EqualValues(t, test.tag.Object, tag.Object) - assert.EqualValues(t, test.tag.Name, tag.Name) - assert.EqualValues(t, test.tag.Message, tag.Message) - assert.EqualValues(t, test.tag.Type, tag.Type) - if test.tag.Signature != nil && assert.NotNil(t, tag.Signature) { - assert.EqualValues(t, test.tag.Signature.Signature, tag.Signature.Signature) - assert.EqualValues(t, test.tag.Signature.Payload, tag.Signature.Payload) - } else { - assert.Nil(t, tag.Signature) - } - if test.tag.Tagger != nil && assert.NotNil(t, tag.Tagger) { - assert.EqualValues(t, test.tag.Tagger.Name, tag.Tagger.Name) - assert.EqualValues(t, test.tag.Tagger.Email, tag.Tagger.Email) - assert.EqualValues(t, test.tag.Tagger.When.Unix(), tag.Tagger.When.Unix()) - } else { - assert.Nil(t, tag.Tagger) - } + assert.Equal(t, test.expected, *tag) } + + tag, err := parseTagData(Sha1ObjectFormat, []byte("type commit\n\nfoo\n-----BEGIN SSH SIGNATURE-----\ncorrupted...")) + assert.NoError(t, err) + assert.Equal(t, "foo\n-----BEGIN SSH SIGNATURE-----\ncorrupted...", tag.Message) } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index 28d02c7e81..a591485082 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -77,8 +77,11 @@ func (t *Tree) ListEntries() (Entries, error) { return nil, runErr } - var err error - t.entries, err = parseTreeEntries(t.repo.objectFormat, stdout, t) + objectFormat, err := t.repo.GetObjectFormat() + if err != nil { + return nil, err + } + t.entries, err = parseTreeEntries(objectFormat, stdout, t) if err == nil { t.entriesParsed = true } @@ -101,8 +104,11 @@ func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) { return nil, runErr } - var err error - t.entriesRecursive, err = parseTreeEntries(t.repo.objectFormat, stdout, t) + objectFormat, err := t.repo.GetObjectFormat() + if err != nil { + return nil, err + } + t.entriesRecursive, err = parseTreeEntries(objectFormat, stdout, t) if err == nil { t.entriesRecursiveParsed = true } diff --git a/modules/graceful/manager.go b/modules/graceful/manager.go index f3f412863a..3f1115066a 100644 --- a/modules/graceful/manager.go +++ b/modules/graceful/manager.go @@ -233,7 +233,10 @@ func (g *Manager) setStateTransition(old, new state) bool { // At the moment the total number of servers (numberOfServersToCreate) are pre-defined as a const before global init, // so this function MUST be called if a server is not used. func (g *Manager) InformCleanup() { - g.createServerWaitGroup.Done() + g.createServerCond.L.Lock() + defer g.createServerCond.L.Unlock() + g.createdServer++ + g.createServerCond.Signal() } // Done allows the manager to be viewed as a context.Context, it returns a channel that is closed when the server is finished terminating diff --git a/modules/graceful/manager_common.go b/modules/graceful/manager_common.go index 27196e1531..f6dbcc748d 100644 --- a/modules/graceful/manager_common.go +++ b/modules/graceful/manager_common.go @@ -42,8 +42,9 @@ type Manager struct { terminateCtxCancel context.CancelFunc managerCtxCancel context.CancelFunc runningServerWaitGroup sync.WaitGroup - createServerWaitGroup sync.WaitGroup terminateWaitGroup sync.WaitGroup + createServerCond sync.Cond + createdServer int shutdownRequested chan struct{} toRunAtShutdown []func() @@ -52,7 +53,7 @@ type Manager struct { func newGracefulManager(ctx context.Context) *Manager { manager := &Manager{ctx: ctx, shutdownRequested: make(chan struct{})} - manager.createServerWaitGroup.Add(numberOfServersToCreate) + manager.createServerCond.L = &sync.Mutex{} manager.prepare(ctx) manager.start() return manager diff --git a/modules/graceful/manager_unix.go b/modules/graceful/manager_unix.go index edf5fc248f..d03fff9b5b 100644 --- a/modules/graceful/manager_unix.go +++ b/modules/graceful/manager_unix.go @@ -57,20 +57,27 @@ func (g *Manager) start() { // Handle clean up of unused provided listeners and delayed start-up startupDone := make(chan struct{}) go func() { - defer close(startupDone) - // Wait till we're done getting all the listeners and then close the unused ones - func() { - // FIXME: there is a fundamental design problem of the "manager" and the "wait group". - // If nothing has started, the "Wait" just panics: sync: WaitGroup is reused before previous Wait has returned - // There is no clear solution besides a complete rewriting of the "manager" - defer func() { - _ = recover() - }() - g.createServerWaitGroup.Wait() + defer func() { + close(startupDone) + // Close the unused listeners + closeProvidedListeners() }() - // Ignore the error here there's not much we can do with it, they're logged in the CloseProvidedListeners function - _ = CloseProvidedListeners() - g.notify(readyMsg) + // Wait for all servers to be created + g.createServerCond.L.Lock() + for { + if g.createdServer >= numberOfServersToCreate { + g.createServerCond.L.Unlock() + g.notify(readyMsg) + return + } + select { + case <-g.IsShutdown(): + g.createServerCond.L.Unlock() + return + default: + } + g.createServerCond.Wait() + } }() if setting.StartupTimeout > 0 { go func() { @@ -78,16 +85,7 @@ func (g *Manager) start() { case <-startupDone: return case <-g.IsShutdown(): - func() { - // When WaitGroup counter goes negative it will panic - we don't care about this so we can just ignore it. - defer func() { - _ = recover() - }() - // Ensure that the createServerWaitGroup stops waiting - for { - g.createServerWaitGroup.Done() - } - }() + g.createServerCond.Signal() return case <-time.After(setting.StartupTimeout): log.Error("Startup took too long! Shutting down") diff --git a/modules/graceful/manager_windows.go b/modules/graceful/manager_windows.go index ecf30af3f3..d776e0e9f9 100644 --- a/modules/graceful/manager_windows.go +++ b/modules/graceful/manager_windows.go @@ -149,33 +149,35 @@ hammerLoop: func (g *Manager) awaitServer(limit time.Duration) bool { c := make(chan struct{}) go func() { - defer close(c) - func() { - // FIXME: there is a fundamental design problem of the "manager" and the "wait group". - // If nothing has started, the "Wait" just panics: sync: WaitGroup is reused before previous Wait has returned - // There is no clear solution besides a complete rewriting of the "manager" - defer func() { - _ = recover() - }() - g.createServerWaitGroup.Wait() - }() + g.createServerCond.L.Lock() + for { + if g.createdServer >= numberOfServersToCreate { + g.createServerCond.L.Unlock() + close(c) + return + } + select { + case <-g.IsShutdown(): + g.createServerCond.L.Unlock() + return + default: + } + g.createServerCond.Wait() + } }() + + var tc <-chan time.Time if limit > 0 { - select { - case <-c: - return true // completed normally - case <-time.After(limit): - return false // timed out - case <-g.IsShutdown(): - return false - } - } else { - select { - case <-c: - return true // completed normally - case <-g.IsShutdown(): - return false - } + tc = time.After(limit) + } + select { + case <-c: + return true // completed normally + case <-tc: + return false // timed out + case <-g.IsShutdown(): + g.createServerCond.Signal() + return false } } diff --git a/modules/graceful/net_unix.go b/modules/graceful/net_unix.go index 4f8c036a69..796e00507c 100644 --- a/modules/graceful/net_unix.go +++ b/modules/graceful/net_unix.go @@ -129,25 +129,17 @@ func getProvidedFDs() (savedErr error) { return savedErr } -// CloseProvidedListeners closes all unused provided listeners. -func CloseProvidedListeners() error { +// closeProvidedListeners closes all unused provided listeners. +func closeProvidedListeners() { mutex.Lock() defer mutex.Unlock() - var returnableError error for _, l := range providedListeners { err := l.Close() if err != nil { log.Error("Error in closing unused provided listener: %v", err) - if returnableError != nil { - returnableError = fmt.Errorf("%v & %w", returnableError, err) - } else { - returnableError = err - } } } providedListeners = []net.Listener{} - - return returnableError } // DefaultGetListener obtains a listener for the stream-oriented local network address: diff --git a/modules/httplib/url.go b/modules/httplib/url.go index 14b95898f5..903799cb68 100644 --- a/modules/httplib/url.go +++ b/modules/httplib/url.go @@ -8,20 +8,42 @@ import ( "strings" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" ) -// IsRiskyRedirectURL returns true if the URL is considered risky for redirects -func IsRiskyRedirectURL(s string) bool { +func urlIsRelative(s string, u *url.URL) bool { // Unfortunately browsers consider a redirect Location with preceding "//", "\\", "/\" and "\/" as meaning redirect to "http(s)://REST_OF_PATH" // Therefore we should ignore these redirect locations to prevent open redirects if len(s) > 1 && (s[0] == '/' || s[0] == '\\') && (s[1] == '/' || s[1] == '\\') { - return true + return false } - - u, err := url.Parse(s) - if err != nil || ((u.Scheme != "" || u.Host != "") && !strings.HasPrefix(strings.ToLower(s), strings.ToLower(setting.AppURL))) { - return true - } - - return false + return u != nil && u.Scheme == "" && u.Host == "" +} + +// IsRelativeURL detects if a URL is relative (no scheme or host) +func IsRelativeURL(s string) bool { + u, err := url.Parse(s) + return err == nil && urlIsRelative(s, u) +} + +func IsCurrentGiteaSiteURL(s string) bool { + u, err := url.Parse(s) + if err != nil { + return false + } + if u.Path != "" { + cleanedPath := util.PathJoinRelX(u.Path) + if cleanedPath == "" || cleanedPath == "." { + u.Path = "/" + } else { + u.Path += "/" + cleanedPath + "/" + } + } + if urlIsRelative(s, u) { + return u.Path == "" || strings.HasPrefix(strings.ToLower(u.Path), strings.ToLower(setting.AppSubURL+"/")) + } + if u.Path == "" { + u.Path = "/" + } + return strings.HasPrefix(strings.ToLower(u.String()), strings.ToLower(setting.AppURL)) } diff --git a/modules/httplib/url_test.go b/modules/httplib/url_test.go index 72033b1208..9bf09bcf2f 100644 --- a/modules/httplib/url_test.go +++ b/modules/httplib/url_test.go @@ -7,32 +7,70 @@ import ( "testing" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" "github.com/stretchr/testify/assert" ) -func TestIsRiskyRedirectURL(t *testing.T) { - setting.AppURL = "http://localhost:3000/" - tests := []struct { - input string - want bool - }{ - {"", false}, - {"foo", false}, - {"/", false}, - {"/foo?k=%20#abc", false}, - - {"//", true}, - {"\\\\", true}, - {"/\\", true}, - {"\\/", true}, - {"mail:a@b.com", true}, - {"https://test.com", true}, - {setting.AppURL + "/foo", false}, +func TestIsRelativeURL(t *testing.T) { + defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")() + defer test.MockVariableValue(&setting.AppSubURL, "/sub")() + rel := []string{ + "", + "foo", + "/", + "/foo?k=%20#abc", } - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - assert.Equal(t, tt.want, IsRiskyRedirectURL(tt.input)) - }) + for _, s := range rel { + assert.True(t, IsRelativeURL(s), "rel = %q", s) + } + abs := []string{ + "//", + "\\\\", + "/\\", + "\\/", + "mailto:a@b.com", + "https://test.com", + } + for _, s := range abs { + assert.False(t, IsRelativeURL(s), "abs = %q", s) } } + +func TestIsCurrentGiteaSiteURL(t *testing.T) { + defer test.MockVariableValue(&setting.AppURL, "http://localhost:3000/sub/")() + defer test.MockVariableValue(&setting.AppSubURL, "/sub")() + good := []string{ + "?key=val", + "/sub", + "/sub/", + "/sub/foo", + "/sub/foo/", + "http://localhost:3000/sub?key=val", + "http://localhost:3000/sub/", + } + for _, s := range good { + assert.True(t, IsCurrentGiteaSiteURL(s), "good = %q", s) + } + bad := []string{ + ".", + "foo", + "/", + "//", + "\\\\", + "/foo", + "http://localhost:3000/sub/..", + "http://localhost:3000/other", + "http://other/", + } + for _, s := range bad { + assert.False(t, IsCurrentGiteaSiteURL(s), "bad = %q", s) + } + + setting.AppURL = "http://localhost:3000/" + setting.AppSubURL = "" + assert.False(t, IsCurrentGiteaSiteURL("//")) + assert.False(t, IsCurrentGiteaSiteURL("\\\\")) + assert.False(t, IsCurrentGiteaSiteURL("http://localhost")) + assert.True(t, IsCurrentGiteaSiteURL("http://localhost:3000?key=val")) +} diff --git a/modules/indexer/code/bleve/bleve.go b/modules/indexer/code/bleve/bleve.go index 107dd23598..bd844205a6 100644 --- a/modules/indexer/code/bleve/bleve.go +++ b/modules/indexer/code/bleve/bleve.go @@ -39,6 +39,8 @@ import ( const ( unicodeNormalizeName = "unicodeNormalize" maxBatchSize = 16 + // fuzzyDenominator determines the levenshtein distance per each character of a keyword + fuzzyDenominator = 4 ) func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error { @@ -142,7 +144,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro return err } if size, err = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64); err != nil { - return fmt.Errorf("Misformatted git cat-file output: %w", err) + return fmt.Errorf("misformatted git cat-file output: %w", err) } } @@ -189,7 +191,6 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository, batch func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error { batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize) if len(changes.Updates) > 0 { - // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first! if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil { log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err) @@ -233,26 +234,23 @@ func (b *Indexer) Delete(_ context.Context, repoID int64) error { // Search searches for files in the specified repo. // Returns the matching file-paths -func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isFuzzy bool) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) { +func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) { var ( indexerQuery query.Query keywordQuery query.Query ) - if isFuzzy { - phraseQuery := bleve.NewMatchPhraseQuery(keyword) - phraseQuery.FieldVal = "Content" - phraseQuery.Analyzer = repoIndexerAnalyzer - keywordQuery = phraseQuery - } else { - prefixQuery := bleve.NewPrefixQuery(keyword) - prefixQuery.FieldVal = "Content" - keywordQuery = prefixQuery + phraseQuery := bleve.NewMatchPhraseQuery(opts.Keyword) + phraseQuery.FieldVal = "Content" + phraseQuery.Analyzer = repoIndexerAnalyzer + keywordQuery = phraseQuery + if opts.IsKeywordFuzzy { + phraseQuery.Fuzziness = len(opts.Keyword) / fuzzyDenominator } - if len(repoIDs) > 0 { - repoQueries := make([]query.Query, 0, len(repoIDs)) - for _, repoID := range repoIDs { + if len(opts.RepoIDs) > 0 { + repoQueries := make([]query.Query, 0, len(opts.RepoIDs)) + for _, repoID := range opts.RepoIDs { repoQueries = append(repoQueries, inner_bleve.NumericEqualityQuery(repoID, "RepoID")) } @@ -266,8 +264,8 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword // Save for reuse without language filter facetQuery := indexerQuery - if len(language) > 0 { - languageQuery := bleve.NewMatchQuery(language) + if len(opts.Language) > 0 { + languageQuery := bleve.NewMatchQuery(opts.Language) languageQuery.FieldVal = "Language" languageQuery.Analyzer = analyzer_keyword.Name @@ -277,12 +275,12 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword ) } - from := (page - 1) * pageSize + from, pageSize := opts.GetSkipTake() searchRequest := bleve.NewSearchRequestOptions(indexerQuery, pageSize, from, false) searchRequest.Fields = []string{"Content", "RepoID", "Language", "CommitID", "UpdatedAt"} searchRequest.IncludeLocations = true - if len(language) == 0 { + if len(opts.Language) == 0 { searchRequest.AddFacet("languages", bleve.NewFacetRequest("Language", 10)) } @@ -326,7 +324,7 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword } searchResultLanguages := make([]*internal.SearchResultLanguages, 0, 10) - if len(language) > 0 { + if len(opts.Language) > 0 { // Use separate query to go get all language counts facetRequest := bleve.NewSearchRequestOptions(facetQuery, 1, 0, false) facetRequest.Fields = []string{"Content", "RepoID", "Language", "CommitID", "UpdatedAt"} @@ -336,7 +334,6 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword if result, err = b.inner.Indexer.Search(facetRequest); err != nil { return 0, nil, nil, err } - } languagesFacet := result.Facets["languages"] for _, term := range languagesFacet.Terms.Terms() { diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go index 065b0b2061..e4622fd66e 100644 --- a/modules/indexer/code/elasticsearch/elasticsearch.go +++ b/modules/indexer/code/elasticsearch/elasticsearch.go @@ -281,18 +281,18 @@ func extractAggs(searchResult *elastic.SearchResult) []*internal.SearchResultLan } // Search searches for codes and language stats by given conditions. -func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isFuzzy bool) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) { +func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) { searchType := esMultiMatchTypePhrasePrefix - if isFuzzy { + if opts.IsKeywordFuzzy { searchType = esMultiMatchTypeBestFields } - kwQuery := elastic.NewMultiMatchQuery(keyword, "content").Type(searchType) + kwQuery := elastic.NewMultiMatchQuery(opts.Keyword, "content").Type(searchType) query := elastic.NewBoolQuery() query = query.Must(kwQuery) - if len(repoIDs) > 0 { - repoStrs := make([]any, 0, len(repoIDs)) - for _, repoID := range repoIDs { + if len(opts.RepoIDs) > 0 { + repoStrs := make([]any, 0, len(opts.RepoIDs)) + for _, repoID := range opts.RepoIDs { repoStrs = append(repoStrs, repoID) } repoQuery := elastic.NewTermsQuery("repo_id", repoStrs...) @@ -300,16 +300,12 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword } var ( - start int - kw = "" + keyword + "" - aggregation = elastic.NewTermsAggregation().Field("language").Size(10).OrderByCountDesc() + start, pageSize = opts.GetSkipTake() + kw = "" + opts.Keyword + "" + aggregation = elastic.NewTermsAggregation().Field("language").Size(10).OrderByCountDesc() ) - if page > 0 { - start = (page - 1) * pageSize - } - - if len(language) == 0 { + if len(opts.Language) == 0 { searchResult, err := b.inner.Client.Search(). Index(b.inner.VersionedIndexName()). Aggregation("language", aggregation). @@ -330,7 +326,7 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword return convertResult(searchResult, kw, pageSize) } - langQuery := elastic.NewMatchQuery("language", language) + langQuery := elastic.NewMatchQuery("language", opts.Language) countResult, err := b.inner.Client.Search(). Index(b.inner.VersionedIndexName()). Aggregation("language", aggregation). diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index 76cd78e11e..2905a540e5 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -32,7 +32,7 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision s needGenesis := len(status.CommitSha) == 0 if !needGenesis { - hasAncestorCmd := git.NewCommand(ctx, "merge-base").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) + hasAncestorCmd := git.NewCommand(ctx, "merge-base").AddDynamicArguments(status.CommitSha, revision) stdout, _, _ := hasAncestorCmd.RunStdString(&git.RunOpts{Dir: repo.RepoPath()}) needGenesis = len(stdout) == 0 } @@ -91,11 +91,9 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s return nil, runErr } + objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName) + var err error - objectFormat, err := git.GetObjectFormatOfRepo(ctx, repo.RepoPath()) - if err != nil { - return nil, err - } changes.Updates, err = parseGitLsTreeOutput(objectFormat, stdout) return &changes, err } @@ -174,10 +172,8 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio return nil, err } - objectFormat, err := git.GetObjectFormatOfRepo(ctx, repo.RepoPath()) - if err != nil { - return nil, err - } + objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName) + changes.Updates, err = parseGitLsTreeOutput(objectFormat, lsTreeStdout) return &changes, err } diff --git a/modules/indexer/code/indexer_test.go b/modules/indexer/code/indexer_test.go index 23dbd63410..8975c5ce40 100644 --- a/modules/indexer/code/indexer_test.go +++ b/modules/indexer/code/indexer_test.go @@ -8,6 +8,7 @@ import ( "os" "testing" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/indexer/code/bleve" @@ -70,7 +71,15 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) { for _, kw := range keywords { t.Run(kw.Keyword, func(t *testing.T) { - total, res, langs, err := indexer.Search(context.TODO(), kw.RepoIDs, "", kw.Keyword, 1, 10, true) + total, res, langs, err := indexer.Search(context.TODO(), &internal.SearchOptions{ + RepoIDs: kw.RepoIDs, + Keyword: kw.Keyword, + Paginator: &db.ListOptions{ + Page: 1, + PageSize: 10, + }, + IsKeywordFuzzy: true, + }) assert.NoError(t, err) assert.Len(t, kw.IDs, int(total)) assert.Len(t, langs, kw.Langs) diff --git a/modules/indexer/code/internal/indexer.go b/modules/indexer/code/internal/indexer.go index c92419deb2..c259fcd26e 100644 --- a/modules/indexer/code/internal/indexer.go +++ b/modules/indexer/code/internal/indexer.go @@ -7,6 +7,7 @@ import ( "context" "fmt" + "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/indexer/internal" ) @@ -16,7 +17,17 @@ type Indexer interface { internal.Indexer Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *RepoChanges) error Delete(ctx context.Context, repoID int64) error - Search(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isFuzzy bool) (int64, []*SearchResult, []*SearchResultLanguages, error) + Search(ctx context.Context, opts *SearchOptions) (int64, []*SearchResult, []*SearchResultLanguages, error) +} + +type SearchOptions struct { + RepoIDs []int64 + Keyword string + Language string + + IsKeywordFuzzy bool + + db.Paginator } // NewDummyIndexer returns a dummy indexer @@ -38,6 +49,6 @@ func (d *dummyIndexer) Delete(ctx context.Context, repoID int64) error { return fmt.Errorf("indexer is not ready") } -func (d *dummyIndexer) Search(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isFuzzy bool) (int64, []*SearchResult, []*SearchResultLanguages, error) { +func (d *dummyIndexer) Search(ctx context.Context, opts *SearchOptions) (int64, []*SearchResult, []*SearchResultLanguages, error) { return 0, nil, nil, fmt.Errorf("indexer is not ready") } diff --git a/modules/indexer/code/search.go b/modules/indexer/code/search.go index 89a62a8d3e..74c957dde6 100644 --- a/modules/indexer/code/search.go +++ b/modules/indexer/code/search.go @@ -22,7 +22,7 @@ type Result struct { UpdatedUnix timeutil.TimeStamp Language string Color string - Lines []ResultLine + Lines []*ResultLine } type ResultLine struct { @@ -32,6 +32,8 @@ type ResultLine struct { type SearchResultLanguages = internal.SearchResultLanguages +type SearchOptions = internal.SearchOptions + func indices(content string, selectionStartIndex, selectionEndIndex int) (int, int) { startIndex := selectionStartIndex numLinesBefore := 0 @@ -68,13 +70,29 @@ func writeStrings(buf *bytes.Buffer, strs ...string) error { return nil } +func HighlightSearchResultCode(filename, language string, lineNums []int, code string) []*ResultLine { + // we should highlight the whole code block first, otherwise it doesn't work well with multiple line highlighting + hl, _ := highlight.Code(filename, language, code) + highlightedLines := strings.Split(string(hl), "\n") + + // The lineNums outputted by highlight.Code might not match the original lineNums, because "highlight" removes the last `\n` + lines := make([]*ResultLine, min(len(highlightedLines), len(lineNums))) + for i := 0; i < len(lines); i++ { + lines[i] = &ResultLine{ + Num: lineNums[i], + FormattedContent: template.HTML(highlightedLines[i]), + } + } + return lines +} + func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Result, error) { startLineNum := 1 + strings.Count(result.Content[:startIndex], "\n") var formattedLinesBuffer bytes.Buffer contentLines := strings.SplitAfter(result.Content[startIndex:endIndex], "\n") - lines := make([]ResultLine, 0, len(contentLines)) + lineNums := make([]int, 0, len(contentLines)) index := startIndex for i, line := range contentLines { var err error @@ -89,29 +107,16 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res line[closeActiveIndex:], ) } else { - err = writeStrings(&formattedLinesBuffer, - line, - ) + err = writeStrings(&formattedLinesBuffer, line) } if err != nil { return nil, err } - lines = append(lines, ResultLine{Num: startLineNum + i}) + lineNums = append(lineNums, startLineNum+i) index += len(line) } - // we should highlight the whole code block first, otherwise it doesn't work well with multiple line highlighting - hl, _ := highlight.Code(result.Filename, "", formattedLinesBuffer.String()) - highlightedLines := strings.Split(string(hl), "\n") - - // The lines outputted by highlight.Code might not match the original lines, because "highlight" removes the last `\n` - lines = lines[:min(len(highlightedLines), len(lines))] - highlightedLines = highlightedLines[:len(lines)] - for i := 0; i < len(lines); i++ { - lines[i].FormattedContent = template.HTML(highlightedLines[i]) - } - return &Result{ RepoID: result.RepoID, Filename: result.Filename, @@ -119,18 +124,18 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res UpdatedUnix: result.UpdatedUnix, Language: result.Language, Color: result.Color, - Lines: lines, + Lines: HighlightSearchResultCode(result.Filename, result.Language, lineNums, formattedLinesBuffer.String()), }, nil } // PerformSearch perform a search on a repository // if isFuzzy is true set the Damerau-Levenshtein distance from 0 to 2 -func PerformSearch(ctx context.Context, repoIDs []int64, language, keyword string, page, pageSize int, isFuzzy bool) (int, []*Result, []*internal.SearchResultLanguages, error) { - if len(keyword) == 0 { +func PerformSearch(ctx context.Context, opts *SearchOptions) (int, []*Result, []*SearchResultLanguages, error) { + if opts == nil || len(opts.Keyword) == 0 { return 0, nil, nil, nil } - total, results, resultLanguages, err := (*globalIndexer.Load()).Search(ctx, repoIDs, language, keyword, page, pageSize, isFuzzy) + total, results, resultLanguages, err := (*globalIndexer.Load()).Search(ctx, opts) if err != nil { return 0, nil, nil, err } diff --git a/modules/indexer/internal/bleve/query.go b/modules/indexer/internal/bleve/query.go index 2a427c4020..21422b281c 100644 --- a/modules/indexer/internal/bleve/query.go +++ b/modules/indexer/internal/bleve/query.go @@ -4,6 +4,8 @@ package bleve import ( + "code.gitea.io/gitea/modules/optional" + "github.com/blevesearch/bleve/v2" "github.com/blevesearch/bleve/v2/search/query" ) @@ -18,17 +20,11 @@ func NumericEqualityQuery(value int64, field string) *query.NumericRangeQuery { } // MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer -func MatchPhraseQuery(matchPhrase, field, analyzer string) *query.MatchPhraseQuery { +func MatchPhraseQuery(matchPhrase, field, analyzer string, fuzziness int) *query.MatchPhraseQuery { q := bleve.NewMatchPhraseQuery(matchPhrase) q.FieldVal = field q.Analyzer = analyzer - return q -} - -// PrefixQuery generates a match prefix query for the given prefix and field -func PrefixQuery(matchPrefix, field string) *query.PrefixQuery { - q := bleve.NewPrefixQuery(matchPrefix) - q.FieldVal = field + q.Fuzziness = fuzziness return q } @@ -39,18 +35,18 @@ func BoolFieldQuery(value bool, field string) *query.BoolFieldQuery { return q } -func NumericRangeInclusiveQuery(min, max *int64, field string) *query.NumericRangeQuery { +func NumericRangeInclusiveQuery(min, max optional.Option[int64], field string) *query.NumericRangeQuery { var minF, maxF *float64 var minI, maxI *bool - if min != nil { + if min.Has() { minF = new(float64) - *minF = float64(*min) + *minF = float64(min.Value()) minI = new(bool) *minI = true } - if max != nil { + if max.Has() { maxF = new(float64) - *maxF = float64(*max) + *maxF = float64(max.Value()) maxI = new(bool) *maxI = true } diff --git a/modules/indexer/internal/paginator.go b/modules/indexer/internal/paginator.go index de0a33c06f..ee204bf047 100644 --- a/modules/indexer/internal/paginator.go +++ b/modules/indexer/internal/paginator.go @@ -10,7 +10,7 @@ import ( ) // ParsePaginator parses a db.Paginator into a skip and limit -func ParsePaginator(paginator db.Paginator, max ...int) (int, int) { +func ParsePaginator(paginator *db.ListOptions, max ...int) (int, int) { // Use a very large number to indicate no limit unlimited := math.MaxInt32 if len(max) > 0 { @@ -19,22 +19,15 @@ func ParsePaginator(paginator db.Paginator, max ...int) (int, int) { } if paginator == nil || paginator.IsListAll() { + // It shouldn't happen. In actual usage scenarios, there should not be requests to search all. + // But if it does happen, respect it and return "unlimited". + // And it's also useful for testing. return 0, unlimited } - // Warning: Do not use GetSkipTake() for *db.ListOptions - // Its implementation could reset the page size with setting.API.MaxResponseItems - if listOptions, ok := paginator.(*db.ListOptions); ok { - if listOptions.Page >= 0 && listOptions.PageSize > 0 { - var start int - if listOptions.Page == 0 { - start = 0 - } else { - start = (listOptions.Page - 1) * listOptions.PageSize - } - return start, listOptions.PageSize - } - return 0, unlimited + if paginator.PageSize == 0 { + // Do not return any results when searching, it's used to get the total count only. + return 0, 0 } return paginator.GetSkipTake() diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go index aaea854efa..1f54be721b 100644 --- a/modules/indexer/issues/bleve/bleve.go +++ b/modules/indexer/issues/bleve/bleve.go @@ -35,7 +35,11 @@ func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error { }) } -const maxBatchSize = 16 +const ( + maxBatchSize = 16 + // fuzzyDenominator determines the levenshtein distance per each character of a keyword + fuzzyDenominator = 4 +) // IndexerData an update to the issue indexer type IndexerData internal.IndexerData @@ -156,19 +160,16 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( var queries []query.Query if options.Keyword != "" { + fuzziness := 0 if options.IsFuzzyKeyword { - queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{ - inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer), - inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer), - inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer), - }...)) - } else { - queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{ - inner_bleve.PrefixQuery(options.Keyword, "title"), - inner_bleve.PrefixQuery(options.Keyword, "content"), - inner_bleve.PrefixQuery(options.Keyword, "comments"), - }...)) + fuzziness = len(options.Keyword) / fuzzyDenominator } + + queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{ + inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer, fuzziness), + inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer, fuzziness), + inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer, fuzziness), + }...)) } if len(options.RepoIDs) > 0 || options.AllPublic { @@ -224,38 +225,41 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( queries = append(queries, bleve.NewDisjunctionQuery(milestoneQueries...)) } - if options.ProjectID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.ProjectID, "project_id")) + if options.ProjectID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.ProjectID.Value(), "project_id")) } - if options.ProjectBoardID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.ProjectBoardID, "project_board_id")) + if options.ProjectBoardID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.ProjectBoardID.Value(), "project_board_id")) } - if options.PosterID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.PosterID, "poster_id")) + if options.PosterID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.PosterID.Value(), "poster_id")) } - if options.AssigneeID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.AssigneeID, "assignee_id")) + if options.AssigneeID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.AssigneeID.Value(), "assignee_id")) } - if options.MentionID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.MentionID, "mention_ids")) + if options.MentionID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.MentionID.Value(), "mention_ids")) } - if options.ReviewedID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.ReviewedID, "reviewed_ids")) + if options.ReviewedID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.ReviewedID.Value(), "reviewed_ids")) } - if options.ReviewRequestedID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.ReviewRequestedID, "review_requested_ids")) + if options.ReviewRequestedID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.ReviewRequestedID.Value(), "review_requested_ids")) } - if options.SubscriberID != nil { - queries = append(queries, inner_bleve.NumericEqualityQuery(*options.SubscriberID, "subscriber_ids")) + if options.SubscriberID.Has() { + queries = append(queries, inner_bleve.NumericEqualityQuery(options.SubscriberID.Value(), "subscriber_ids")) } - if options.UpdatedAfterUnix != nil || options.UpdatedBeforeUnix != nil { - queries = append(queries, inner_bleve.NumericRangeInclusiveQuery(options.UpdatedAfterUnix, options.UpdatedBeforeUnix, "updated_unix")) + if options.UpdatedAfterUnix.Has() || options.UpdatedBeforeUnix.Has() { + queries = append(queries, inner_bleve.NumericRangeInclusiveQuery( + options.UpdatedAfterUnix, + options.UpdatedBeforeUnix, + "updated_unix")) } var indexerQuery query.Query = bleve.NewConjunctionQuery(queries...) diff --git a/modules/indexer/issues/db/db.go b/modules/indexer/issues/db/db.go index 1016523b72..05ec548435 100644 --- a/modules/indexer/issues/db/db.go +++ b/modules/indexer/issues/db/db.go @@ -78,6 +78,17 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( return nil, err } + // If pagesize == 0, return total count only. It's a special case for search count. + if options.Paginator != nil && options.Paginator.PageSize == 0 { + total, err := issue_model.CountIssues(ctx, opt, cond) + if err != nil { + return nil, err + } + return &internal.SearchResult{ + Total: total, + }, nil + } + ids, total, err := issue_model.IssueIDs(ctx, opt, cond) if err != nil { return nil, err diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go index 69146573a8..eeaf1696ad 100644 --- a/modules/indexer/issues/db/options.go +++ b/modules/indexer/issues/db/options.go @@ -15,22 +15,6 @@ import ( ) func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_model.IssuesOptions, error) { - // See the comment of issues_model.SearchOptions for the reason why we need to convert - convertID := func(id *int64) int64 { - if id == nil { - return 0 - } - if *id == 0 { - return db.NoConditionID - } - return *id - } - convertInt64 := func(i *int64) int64 { - if i == nil { - return 0 - } - return *i - } var sortType string switch options.SortBy { case internal.SortByCreatedAsc: @@ -53,6 +37,18 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m sortType = "newest" } + // See the comment of issues_model.SearchOptions for the reason why we need to convert + convertID := func(id optional.Option[int64]) int64 { + if !id.Has() { + return 0 + } + value := id.Value() + if value == 0 { + return db.NoConditionID + } + return value + } + opts := &issue_model.IssuesOptions{ Paginator: options.Paginator, RepoIDs: options.RepoIDs, @@ -73,8 +69,8 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m IncludeMilestones: nil, SortType: sortType, IssueIDs: nil, - UpdatedAfterUnix: convertInt64(options.UpdatedAfterUnix), - UpdatedBeforeUnix: convertInt64(options.UpdatedBeforeUnix), + UpdatedAfterUnix: options.UpdatedAfterUnix.Value(), + UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(), PriorityRepoID: 0, IsArchived: optional.None[bool](), Org: nil, diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go index 80e233e29a..8f94088742 100644 --- a/modules/indexer/issues/dboptions.go +++ b/modules/indexer/issues/dboptions.go @@ -6,6 +6,7 @@ package issues import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/modules/optional" ) func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions { @@ -38,13 +39,12 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp } // See the comment of issues_model.SearchOptions for the reason why we need to convert - convertID := func(id int64) *int64 { + convertID := func(id int64) optional.Option[int64] { if id > 0 { - return &id + return optional.Some(id) } if id == db.NoConditionID { - var zero int64 - return &zero + return optional.None[int64]() } return nil } @@ -59,16 +59,16 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp searchOpt.SubscriberID = convertID(opts.SubscriberID) if opts.UpdatedAfterUnix > 0 { - searchOpt.UpdatedAfterUnix = &opts.UpdatedAfterUnix + searchOpt.UpdatedAfterUnix = optional.Some(opts.UpdatedAfterUnix) } if opts.UpdatedBeforeUnix > 0 { - searchOpt.UpdatedBeforeUnix = &opts.UpdatedBeforeUnix + searchOpt.UpdatedBeforeUnix = optional.Some(opts.UpdatedBeforeUnix) } searchOpt.Paginator = opts.Paginator switch opts.SortType { - case "": + case "", "latest": searchOpt.SortBy = SortByCreatedDesc case "oldest": searchOpt.SortBy = SortByCreatedAsc @@ -86,7 +86,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp searchOpt.SortBy = SortByDeadlineDesc case "priority", "priorityrepo", "project-column-sorting": // Unsupported sort type for search - searchOpt.SortBy = SortByUpdatedDesc + fallthrough default: searchOpt.SortBy = SortByUpdatedDesc } diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go index 0077da263a..c7cb59f2cf 100644 --- a/modules/indexer/issues/elasticsearch/elasticsearch.go +++ b/modules/indexer/issues/elasticsearch/elasticsearch.go @@ -145,7 +145,6 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( query := elastic.NewBoolQuery() if options.Keyword != "" { - searchType := esMultiMatchTypePhrasePrefix if options.IsFuzzyKeyword { searchType = esMultiMatchTypeBestFields @@ -195,43 +194,43 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( query.Must(elastic.NewTermsQuery("milestone_id", toAnySlice(options.MilestoneIDs)...)) } - if options.ProjectID != nil { - query.Must(elastic.NewTermQuery("project_id", *options.ProjectID)) + if options.ProjectID.Has() { + query.Must(elastic.NewTermQuery("project_id", options.ProjectID.Value())) } - if options.ProjectBoardID != nil { - query.Must(elastic.NewTermQuery("project_board_id", *options.ProjectBoardID)) + if options.ProjectBoardID.Has() { + query.Must(elastic.NewTermQuery("project_board_id", options.ProjectBoardID.Value())) } - if options.PosterID != nil { - query.Must(elastic.NewTermQuery("poster_id", *options.PosterID)) + if options.PosterID.Has() { + query.Must(elastic.NewTermQuery("poster_id", options.PosterID.Value())) } - if options.AssigneeID != nil { - query.Must(elastic.NewTermQuery("assignee_id", *options.AssigneeID)) + if options.AssigneeID.Has() { + query.Must(elastic.NewTermQuery("assignee_id", options.AssigneeID.Value())) } - if options.MentionID != nil { - query.Must(elastic.NewTermQuery("mention_ids", *options.MentionID)) + if options.MentionID.Has() { + query.Must(elastic.NewTermQuery("mention_ids", options.MentionID.Value())) } - if options.ReviewedID != nil { - query.Must(elastic.NewTermQuery("reviewed_ids", *options.ReviewedID)) + if options.ReviewedID.Has() { + query.Must(elastic.NewTermQuery("reviewed_ids", options.ReviewedID.Value())) } - if options.ReviewRequestedID != nil { - query.Must(elastic.NewTermQuery("review_requested_ids", *options.ReviewRequestedID)) + if options.ReviewRequestedID.Has() { + query.Must(elastic.NewTermQuery("review_requested_ids", options.ReviewRequestedID.Value())) } - if options.SubscriberID != nil { - query.Must(elastic.NewTermQuery("subscriber_ids", *options.SubscriberID)) + if options.SubscriberID.Has() { + query.Must(elastic.NewTermQuery("subscriber_ids", options.SubscriberID.Value())) } - if options.UpdatedAfterUnix != nil || options.UpdatedBeforeUnix != nil { + if options.UpdatedAfterUnix.Has() || options.UpdatedBeforeUnix.Has() { q := elastic.NewRangeQuery("updated_unix") - if options.UpdatedAfterUnix != nil { - q.Gte(*options.UpdatedAfterUnix) + if options.UpdatedAfterUnix.Has() { + q.Gte(options.UpdatedAfterUnix.Value()) } - if options.UpdatedBeforeUnix != nil { - q.Lte(*options.UpdatedBeforeUnix) + if options.UpdatedBeforeUnix.Has() { + q.Lte(options.UpdatedBeforeUnix.Value()) } query.Must(q) } diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index e3bc21b49d..1cb86feb82 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -308,7 +308,7 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err // CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count. func CountIssues(ctx context.Context, opts *SearchOptions) (int64, error) { - opts = opts.Copy(func(options *SearchOptions) { opts.Paginator = &db_model.ListOptions{PageSize: 0} }) + opts = opts.Copy(func(options *SearchOptions) { options.Paginator = &db_model.ListOptions{PageSize: 0} }) _, total, err := SearchIssues(ctx, opts) return total, err diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go index 10ffa7cbe6..0d0cfc8516 100644 --- a/modules/indexer/issues/indexer_test.go +++ b/modules/indexer/issues/indexer_test.go @@ -134,63 +134,60 @@ func searchIssueInRepo(t *testing.T) { } func searchIssueByID(t *testing.T) { - int64Pointer := func(x int64) *int64 { - return &x - } tests := []struct { opts SearchOptions expectedIDs []int64 }{ { - SearchOptions{ - PosterID: int64Pointer(1), + opts: SearchOptions{ + PosterID: optional.Some(int64(1)), }, - []int64{11, 6, 3, 2, 1}, + expectedIDs: []int64{11, 6, 3, 2, 1}, }, { - SearchOptions{ - AssigneeID: int64Pointer(1), + opts: SearchOptions{ + AssigneeID: optional.Some(int64(1)), }, - []int64{6, 1}, + expectedIDs: []int64{6, 1}, }, { - SearchOptions{ - MentionID: int64Pointer(4), + opts: SearchOptions{ + MentionID: optional.Some(int64(4)), }, - []int64{1}, + expectedIDs: []int64{1}, }, { - SearchOptions{ - ReviewedID: int64Pointer(1), + opts: SearchOptions{ + ReviewedID: optional.Some(int64(1)), }, - []int64{}, + expectedIDs: []int64{}, }, { - SearchOptions{ - ReviewRequestedID: int64Pointer(1), + opts: SearchOptions{ + ReviewRequestedID: optional.Some(int64(1)), }, - []int64{12}, + expectedIDs: []int64{12}, }, { - SearchOptions{ - SubscriberID: int64Pointer(1), + opts: SearchOptions{ + SubscriberID: optional.Some(int64(1)), }, - []int64{11, 6, 5, 3, 2, 1}, + expectedIDs: []int64{11, 6, 5, 3, 2, 1}, }, { // issue 20 request user 15 and team 5 which user 15 belongs to // the review request number of issue 20 should be 1 - SearchOptions{ - ReviewRequestedID: int64Pointer(15), + opts: SearchOptions{ + ReviewRequestedID: optional.Some(int64(15)), }, - []int64{12, 20}, + expectedIDs: []int64{12, 20}, }, { // user 20 approved the issue 20, so return nothing - SearchOptions{ - ReviewRequestedID: int64Pointer(20), + opts: SearchOptions{ + ReviewRequestedID: optional.Some(int64(20)), }, - []int64{}, + expectedIDs: []int64{}, }, } @@ -318,16 +315,13 @@ func searchIssueByLabelID(t *testing.T) { } func searchIssueByTime(t *testing.T) { - int64Pointer := func(i int64) *int64 { - return &i - } tests := []struct { opts SearchOptions expectedIDs []int64 }{ { SearchOptions{ - UpdatedAfterUnix: int64Pointer(0), + UpdatedAfterUnix: optional.Some(int64(0)), }, []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1}, }, @@ -363,28 +357,25 @@ func searchIssueWithOrder(t *testing.T) { } func searchIssueInProject(t *testing.T) { - int64Pointer := func(i int64) *int64 { - return &i - } tests := []struct { opts SearchOptions expectedIDs []int64 }{ { SearchOptions{ - ProjectID: int64Pointer(1), + ProjectID: optional.Some(int64(1)), }, []int64{5, 3, 2, 1}, }, { SearchOptions{ - ProjectBoardID: int64Pointer(1), + ProjectBoardID: optional.Some(int64(1)), }, []int64{1}, }, { SearchOptions{ - ProjectBoardID: int64Pointer(0), // issue with in default board + ProjectBoardID: optional.Some(int64(0)), // issue with in default board }, []int64{2}, }, diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go index d41fec4aba..e9c4eca559 100644 --- a/modules/indexer/issues/internal/model.go +++ b/modules/indexer/issues/internal/model.go @@ -89,24 +89,24 @@ type SearchOptions struct { MilestoneIDs []int64 // milestones the issues have - ProjectID *int64 // project the issues belong to - ProjectBoardID *int64 // project board the issues belong to + ProjectID optional.Option[int64] // project the issues belong to + ProjectBoardID optional.Option[int64] // project board the issues belong to - PosterID *int64 // poster of the issues + PosterID optional.Option[int64] // poster of the issues - AssigneeID *int64 // assignee of the issues, zero means no assignee + AssigneeID optional.Option[int64] // assignee of the issues, zero means no assignee - MentionID *int64 // mentioned user of the issues + MentionID optional.Option[int64] // mentioned user of the issues - ReviewedID *int64 // reviewer of the issues - ReviewRequestedID *int64 // requested reviewer of the issues + ReviewedID optional.Option[int64] // reviewer of the issues + ReviewRequestedID optional.Option[int64] // requested reviewer of the issues - SubscriberID *int64 // subscriber of the issues + SubscriberID optional.Option[int64] // subscriber of the issues - UpdatedAfterUnix *int64 - UpdatedBeforeUnix *int64 + UpdatedAfterUnix optional.Option[int64] + UpdatedBeforeUnix optional.Option[int64] - db.Paginator + Paginator *db.ListOptions SortBy SortBy // sort by field } diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index 6724471539..7f32876d80 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -77,6 +77,13 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) { assert.Equal(t, c.ExpectedIDs, ids) assert.Equal(t, c.ExpectedTotal, result.Total) } + + // test counting + c.SearchOptions.Paginator = &db.ListOptions{PageSize: 0} + countResult, err := indexer.Search(context.Background(), c.SearchOptions) + require.NoError(t, err) + assert.Empty(t, countResult.Hits) + assert.Equal(t, result.Total, countResult.Total) }) } } @@ -300,10 +307,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ProjectID: func() *int64 { - id := int64(1) - return &id - }(), + ProjectID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -321,10 +325,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ProjectID: func() *int64 { - id := int64(0) - return &id - }(), + ProjectID: optional.Some(int64(0)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -342,10 +343,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ProjectBoardID: func() *int64 { - id := int64(1) - return &id - }(), + ProjectBoardID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -363,10 +361,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ProjectBoardID: func() *int64 { - id := int64(0) - return &id - }(), + ProjectBoardID: optional.Some(int64(0)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -384,10 +379,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - PosterID: func() *int64 { - id := int64(1) - return &id - }(), + PosterID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -405,10 +397,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - AssigneeID: func() *int64 { - id := int64(1) - return &id - }(), + AssigneeID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -426,10 +415,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - AssigneeID: func() *int64 { - id := int64(0) - return &id - }(), + AssigneeID: optional.Some(int64(0)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -447,10 +433,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - MentionID: func() *int64 { - id := int64(1) - return &id - }(), + MentionID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -468,10 +451,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ReviewedID: func() *int64 { - id := int64(1) - return &id - }(), + ReviewedID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -489,10 +469,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - ReviewRequestedID: func() *int64 { - id := int64(1) - return &id - }(), + ReviewRequestedID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -510,10 +487,7 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - SubscriberID: func() *int64 { - id := int64(1) - return &id - }(), + SubscriberID: optional.Some(int64(1)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -531,14 +505,8 @@ var cases = []*testIndexerCase{ Paginator: &db.ListOptions{ PageSize: 5, }, - UpdatedAfterUnix: func() *int64 { - var t int64 = 20 - return &t - }(), - UpdatedBeforeUnix: func() *int64 { - var t int64 = 30 - return &t - }(), + UpdatedAfterUnix: optional.Some(int64(20)), + UpdatedBeforeUnix: optional.Some(int64(30)), }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, 5, len(result.Hits)) @@ -554,10 +522,8 @@ var cases = []*testIndexerCase{ { Name: "SortByCreatedDesc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByCreatedDesc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByCreatedDesc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -572,10 +538,8 @@ var cases = []*testIndexerCase{ { Name: "SortByUpdatedDesc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByUpdatedDesc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByUpdatedDesc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -590,10 +554,8 @@ var cases = []*testIndexerCase{ { Name: "SortByCommentsDesc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByCommentsDesc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByCommentsDesc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -608,10 +570,8 @@ var cases = []*testIndexerCase{ { Name: "SortByDeadlineDesc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByDeadlineDesc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByDeadlineDesc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -626,10 +586,8 @@ var cases = []*testIndexerCase{ { Name: "SortByCreatedAsc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByCreatedAsc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByCreatedAsc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -644,10 +602,8 @@ var cases = []*testIndexerCase{ { Name: "SortByUpdatedAsc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByUpdatedAsc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByUpdatedAsc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -662,10 +618,8 @@ var cases = []*testIndexerCase{ { Name: "SortByCommentsAsc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByCommentsAsc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByCommentsAsc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) @@ -680,10 +634,8 @@ var cases = []*testIndexerCase{ { Name: "SortByDeadlineAsc", SearchOptions: &internal.SearchOptions{ - Paginator: &db.ListOptions{ - ListAll: true, - }, - SortBy: internal.SortByDeadlineAsc, + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByDeadlineAsc, }, Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Equal(t, len(data), len(result.Hits)) diff --git a/modules/indexer/issues/meilisearch/meilisearch.go b/modules/indexer/issues/meilisearch/meilisearch.go index c429920065..8a7cec6cba 100644 --- a/modules/indexer/issues/meilisearch/meilisearch.go +++ b/modules/indexer/issues/meilisearch/meilisearch.go @@ -6,6 +6,7 @@ package meilisearch import ( "context" "errors" + "fmt" "strconv" "strings" @@ -170,41 +171,41 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( query.And(inner_meilisearch.NewFilterIn("milestone_id", options.MilestoneIDs...)) } - if options.ProjectID != nil { - query.And(inner_meilisearch.NewFilterEq("project_id", *options.ProjectID)) + if options.ProjectID.Has() { + query.And(inner_meilisearch.NewFilterEq("project_id", options.ProjectID.Value())) } - if options.ProjectBoardID != nil { - query.And(inner_meilisearch.NewFilterEq("project_board_id", *options.ProjectBoardID)) + if options.ProjectBoardID.Has() { + query.And(inner_meilisearch.NewFilterEq("project_board_id", options.ProjectBoardID.Value())) } - if options.PosterID != nil { - query.And(inner_meilisearch.NewFilterEq("poster_id", *options.PosterID)) + if options.PosterID.Has() { + query.And(inner_meilisearch.NewFilterEq("poster_id", options.PosterID.Value())) } - if options.AssigneeID != nil { - query.And(inner_meilisearch.NewFilterEq("assignee_id", *options.AssigneeID)) + if options.AssigneeID.Has() { + query.And(inner_meilisearch.NewFilterEq("assignee_id", options.AssigneeID.Value())) } - if options.MentionID != nil { - query.And(inner_meilisearch.NewFilterEq("mention_ids", *options.MentionID)) + if options.MentionID.Has() { + query.And(inner_meilisearch.NewFilterEq("mention_ids", options.MentionID.Value())) } - if options.ReviewedID != nil { - query.And(inner_meilisearch.NewFilterEq("reviewed_ids", *options.ReviewedID)) + if options.ReviewedID.Has() { + query.And(inner_meilisearch.NewFilterEq("reviewed_ids", options.ReviewedID.Value())) } - if options.ReviewRequestedID != nil { - query.And(inner_meilisearch.NewFilterEq("review_requested_ids", *options.ReviewRequestedID)) + if options.ReviewRequestedID.Has() { + query.And(inner_meilisearch.NewFilterEq("review_requested_ids", options.ReviewRequestedID.Value())) } - if options.SubscriberID != nil { - query.And(inner_meilisearch.NewFilterEq("subscriber_ids", *options.SubscriberID)) + if options.SubscriberID.Has() { + query.And(inner_meilisearch.NewFilterEq("subscriber_ids", options.SubscriberID.Value())) } - if options.UpdatedAfterUnix != nil { - query.And(inner_meilisearch.NewFilterGte("updated_unix", *options.UpdatedAfterUnix)) + if options.UpdatedAfterUnix.Has() { + query.And(inner_meilisearch.NewFilterGte("updated_unix", options.UpdatedAfterUnix.Value())) } - if options.UpdatedBeforeUnix != nil { - query.And(inner_meilisearch.NewFilterLte("updated_unix", *options.UpdatedBeforeUnix)) + if options.UpdatedBeforeUnix.Has() { + query.And(inner_meilisearch.NewFilterLte("updated_unix", options.UpdatedBeforeUnix.Value())) } if options.SortBy == "" { @@ -217,7 +218,22 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits) - searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(options.Keyword, &meilisearch.SearchRequest{ + counting := limit == 0 + if counting { + // If set limit to 0, it will be 20 by default, and -1 is not allowed. + // See https://www.meilisearch.com/docs/reference/api/search#limit + // So set limit to 1 to make the cost as low as possible, then clear the result before returning. + limit = 1 + } + + keyword := options.Keyword + if !options.IsFuzzyKeyword { + // to make it non fuzzy ("typo tolerance" in meilisearch terms), we have to quote the keyword(s) + // https://www.meilisearch.com/docs/reference/api/search#phrase-search + keyword = doubleQuoteKeyword(keyword) + } + + searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{ Filter: query.Statement(), Limit: int64(limit), Offset: int64(skip), @@ -228,7 +244,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( return nil, err } - hits, err := nonFuzzyWorkaround(searchRes, options.Keyword, options.IsFuzzyKeyword) + if counting { + searchRes.Hits = nil + } + + hits, err := convertHits(searchRes) if err != nil { return nil, err } @@ -247,11 +267,20 @@ func parseSortBy(sortBy internal.SortBy) string { return field + ":asc" } -// nonFuzzyWorkaround is needed as meilisearch does not have an exact search -// and you can only change "typo tolerance" per index. So we have to post-filter the results -// https://www.meilisearch.com/docs/learn/configuration/typo_tolerance#configuring-typo-tolerance -// TODO: remove once https://github.com/orgs/meilisearch/discussions/377 is addressed -func nonFuzzyWorkaround(searchRes *meilisearch.SearchResponse, keyword string, isFuzzy bool) ([]internal.Match, error) { +func doubleQuoteKeyword(k string) string { + kp := strings.Split(k, " ") + parts := 0 + for i := range kp { + part := strings.Trim(kp[i], "\"") + if part != "" { + kp[parts] = fmt.Sprintf(`"%s"`, part) + parts++ + } + } + return strings.Join(kp[:parts], " ") +} + +func convertHits(searchRes *meilisearch.SearchResponse) ([]internal.Match, error) { hits := make([]internal.Match, 0, len(searchRes.Hits)) for _, hit := range searchRes.Hits { hit, ok := hit.(map[string]any) @@ -259,61 +288,11 @@ func nonFuzzyWorkaround(searchRes *meilisearch.SearchResponse, keyword string, i return nil, ErrMalformedResponse } - if !isFuzzy { - keyword = strings.ToLower(keyword) - - // declare a anon func to check if the title, content or at least one comment contains the keyword - found, err := func() (bool, error) { - // check if title match first - title, ok := hit["title"].(string) - if !ok { - return false, ErrMalformedResponse - } else if strings.Contains(strings.ToLower(title), keyword) { - return true, nil - } - - // check if content has a match - content, ok := hit["content"].(string) - if !ok { - return false, ErrMalformedResponse - } else if strings.Contains(strings.ToLower(content), keyword) { - return true, nil - } - - // now check for each comment if one has a match - // so we first try to cast and skip if there are no comments - comments, ok := hit["comments"].([]any) - if !ok { - return false, ErrMalformedResponse - } else if len(comments) == 0 { - return false, nil - } - - // now we iterate over all and report as soon as we detect one match - for i := range comments { - comment, ok := comments[i].(string) - if !ok { - return false, ErrMalformedResponse - } - if strings.Contains(strings.ToLower(comment), keyword) { - return true, nil - } - } - - // we got no match - return false, nil - }() - - if err != nil { - return nil, err - } else if !found { - continue - } - } issueID, ok := hit["id"].(float64) if !ok { return nil, ErrMalformedResponse } + hits = append(hits, internal.Match{ ID: int64(issueID), }) diff --git a/modules/indexer/issues/meilisearch/meilisearch_test.go b/modules/indexer/issues/meilisearch/meilisearch_test.go index ecce704236..4666df136a 100644 --- a/modules/indexer/issues/meilisearch/meilisearch_test.go +++ b/modules/indexer/issues/meilisearch/meilisearch_test.go @@ -53,11 +53,10 @@ func TestMeilisearchIndexer(t *testing.T) { tests.TestIndexer(t, indexer) } -func TestNonFuzzyWorkaround(t *testing.T) { - // get unexpected return - _, err := nonFuzzyWorkaround(&meilisearch.SearchResponse{ +func TestConvertHits(t *testing.T) { + _, err := convertHits(&meilisearch.SearchResponse{ Hits: []any{"aa", "bb", "cc", "dd"}, - }, "bowling", false) + }) assert.ErrorIs(t, err, ErrMalformedResponse) validResponse := &meilisearch.SearchResponse{ @@ -82,14 +81,15 @@ func TestNonFuzzyWorkaround(t *testing.T) { }, }, } - - // nonFuzzy - hits, err := nonFuzzyWorkaround(validResponse, "bowling", false) - assert.NoError(t, err) - assert.EqualValues(t, []internal.Match{{ID: 11}, {ID: 22}}, hits) - - // fuzzy - hits, err = nonFuzzyWorkaround(validResponse, "bowling", true) + hits, err := convertHits(validResponse) assert.NoError(t, err) assert.EqualValues(t, []internal.Match{{ID: 11}, {ID: 22}, {ID: 33}}, hits) } + +func TestDoubleQuoteKeyword(t *testing.T) { + assert.EqualValues(t, "", doubleQuoteKeyword("")) + assert.EqualValues(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c")) + assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g")) + assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g")) + assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`)) +} diff --git a/modules/indexer/issues/util.go b/modules/indexer/issues/util.go index 510b4060b2..9861c808dc 100644 --- a/modules/indexer/issues/util.go +++ b/modules/indexer/issues/util.go @@ -61,9 +61,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD ) { reviews, err := issue_model.FindReviews(ctx, issue_model.FindReviewOptions{ - ListOptions: db.ListOptions{ - ListAll: true, - }, + ListOptions: db.ListOptionsAll, IssueID: issueID, OfficialOnly: false, }) diff --git a/modules/lfs/filesystem_client.go b/modules/lfs/filesystem_client.go index 3503a9effc..71bef5c899 100644 --- a/modules/lfs/filesystem_client.go +++ b/modules/lfs/filesystem_client.go @@ -44,7 +44,7 @@ func (c *FilesystemClient) Download(ctx context.Context, objects []Pointer, call if err != nil { return err } - + defer f.Close() if err := callback(p, f, nil); err != nil { return err } @@ -75,7 +75,7 @@ func (c *FilesystemClient) Upload(ctx context.Context, objects []Pointer, callba if err != nil { return err } - + defer f.Close() _, err = io.Copy(f, content) return err diff --git a/modules/log/event_format.go b/modules/log/event_format.go index 524ca3dd87..d9dbebf831 100644 --- a/modules/log/event_format.go +++ b/modules/log/event_format.go @@ -125,7 +125,6 @@ func EventFormatTextMessage(mode *WriterMode, event *Event, msgFormat string, ms if mode.Colorize { buf = append(buf, resetBytes...) } - } if flags&(Lshortfile|Llongfile) != 0 { if mode.Colorize { diff --git a/modules/markup/csv/csv.go b/modules/markup/csv/csv.go index 12458e954a..1dd26eb8ac 100644 --- a/modules/markup/csv/csv.go +++ b/modules/markup/csv/csv.go @@ -6,6 +6,7 @@ package markup import ( "bufio" "bytes" + "fmt" "html" "io" "regexp" @@ -77,29 +78,65 @@ func writeField(w io.Writer, element, class, field string) error { } // Render implements markup.Renderer -func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error { +func (r Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error { tmpBlock := bufio.NewWriter(output) + maxSize := setting.UI.CSV.MaxFileSize - // FIXME: don't read all to memory - rawBytes, err := io.ReadAll(input) + if maxSize == 0 { + return r.tableRender(ctx, input, tmpBlock) + } + + rawBytes, err := io.ReadAll(io.LimitReader(input, maxSize+1)) if err != nil { return err } - if setting.UI.CSV.MaxFileSize != 0 && setting.UI.CSV.MaxFileSize < int64(len(rawBytes)) { - if _, err := tmpBlock.WriteString("
"); err != nil {
-			return err
-		}
-		if _, err := tmpBlock.WriteString(html.EscapeString(string(rawBytes))); err != nil {
-			return err
-		}
-		if _, err := tmpBlock.WriteString("
"); err != nil { - return err - } - return tmpBlock.Flush() + if int64(len(rawBytes)) <= maxSize { + return r.tableRender(ctx, bytes.NewReader(rawBytes), tmpBlock) + } + return r.fallbackRender(io.MultiReader(bytes.NewReader(rawBytes), input), tmpBlock) +} + +func (Renderer) fallbackRender(input io.Reader, tmpBlock *bufio.Writer) error { + _, err := tmpBlock.WriteString("
")
+	if err != nil {
+		return err
 	}
 
-	rd, err := csv.CreateReaderAndDetermineDelimiter(ctx, bytes.NewReader(rawBytes))
+	scan := bufio.NewScanner(input)
+	scan.Split(bufio.ScanRunes)
+	for scan.Scan() {
+		switch scan.Text() {
+		case `&`:
+			_, err = tmpBlock.WriteString("&")
+		case `'`:
+			_, err = tmpBlock.WriteString("'") // "'" is shorter than "'" and apos was not in HTML until HTML5.
+		case `<`:
+			_, err = tmpBlock.WriteString("<")
+		case `>`:
+			_, err = tmpBlock.WriteString(">")
+		case `"`:
+			_, err = tmpBlock.WriteString(""") // """ is shorter than """.
+		default:
+			_, err = tmpBlock.Write(scan.Bytes())
+		}
+		if err != nil {
+			return err
+		}
+	}
+	if err = scan.Err(); err != nil {
+		return fmt.Errorf("fallbackRender scan: %w", err)
+	}
+
+	_, err = tmpBlock.WriteString("
") + if err != nil { + return err + } + return tmpBlock.Flush() +} + +func (Renderer) tableRender(ctx *markup.RenderContext, input io.Reader, tmpBlock *bufio.Writer) error { + rd, err := csv.CreateReaderAndDetermineDelimiter(ctx, input) if err != nil { return err } diff --git a/modules/markup/csv/csv_test.go b/modules/markup/csv/csv_test.go index 8c07184b21..3d12be477c 100644 --- a/modules/markup/csv/csv_test.go +++ b/modules/markup/csv/csv_test.go @@ -4,6 +4,8 @@ package markup import ( + "bufio" + "bytes" "strings" "testing" @@ -29,4 +31,12 @@ func TestRenderCSV(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, v, buf.String()) } + + t.Run("fallbackRender", func(t *testing.T) { + var buf bytes.Buffer + err := render.fallbackRender(strings.NewReader("1,\n2,"), bufio.NewWriter(&buf)) + assert.NoError(t, err) + want := "
1,<a>\n2,<b>
" + assert.Equal(t, want, buf.String()) + }) } diff --git a/modules/markup/html.go b/modules/markup/html.go index 56e1a1c54e..cef643bf18 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -171,6 +171,7 @@ type processor func(ctx *RenderContext, node *html.Node) var defaultProcessors = []processor{ fullIssuePatternProcessor, comparePatternProcessor, + codePreviewPatternProcessor, fullHashPatternProcessor, shortLinkProcessor, linkProcessor, @@ -609,7 +610,7 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) { if ok && strings.Contains(mention, "/") { mentionOrgAndTeam := strings.Split(mention, "/") if mentionOrgAndTeam[0][1:] == ctx.Metas["org"] && strings.Contains(teams, ","+strings.ToLower(mentionOrgAndTeam[1])+",") { - replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, "org", ctx.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "mention")) + replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), "org", ctx.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "mention")) node = node.NextSibling.NextSibling start = 0 continue @@ -620,7 +621,7 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) { mentionedUsername := mention[1:] if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { - replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, mentionedUsername), mention, "mention")) + replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "mention")) node = node.NextSibling.NextSibling } else { node = node.NextSibling @@ -708,7 +709,8 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) { name += tail image := false - switch ext := filepath.Ext(link); ext { + ext := filepath.Ext(link) + switch ext { // fast path: empty string, ignore case "": // leave image as false @@ -766,11 +768,26 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) { } } else { if !absoluteLink { + var base string if ctx.IsWiki { - link = util.URLJoin(ctx.Links.WikiLink(), link) + switch ext { + case "": + // no file extension, create a regular wiki link + base = ctx.Links.WikiLink() + default: + // we have a file extension: + // return a regular wiki link if it's a renderable file (extension), + // raw link otherwise + if Type(link) != "" { + base = ctx.Links.WikiLink() + } else { + base = ctx.Links.WikiRawLink() + } + } } else { - link = util.URLJoin(ctx.Links.SrcLink(), link) + base = ctx.Links.SrcLink() } + link = util.URLJoin(base, link) } childNode.Type = html.TextNode childNode.Data = name @@ -898,9 +915,9 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) { path = "pulls" } if ref.Owner == "" { - link = createLink(util.URLJoin(setting.AppURL, ctx.Metas["user"], ctx.Metas["repo"], path, ref.Issue), reftext, "ref-issue") + link = createLink(util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], path, ref.Issue), reftext, "ref-issue") } else { - link = createLink(util.URLJoin(setting.AppURL, ref.Owner, ref.Name, path, ref.Issue), reftext, "ref-issue") + link = createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, path, ref.Issue), reftext, "ref-issue") } } @@ -939,7 +956,7 @@ func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) { } reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha) - link := createLink(util.URLJoin(setting.AppSubURL, ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit") + link := createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit") replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link) node = node.NextSibling.NextSibling @@ -1166,7 +1183,7 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) { continue } - link := util.URLJoin(setting.AppURL, ctx.Metas["user"], ctx.Metas["repo"], "commit", hash) + link := util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], "commit", hash) replaceContent(node, m[2], m[3], createCodeLink(link, base.ShortSha(hash), "commit")) start = 0 node = node.NextSibling.NextSibling diff --git a/modules/markup/html_codepreview.go b/modules/markup/html_codepreview.go new file mode 100644 index 0000000000..d9da24ea34 --- /dev/null +++ b/modules/markup/html_codepreview.go @@ -0,0 +1,92 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markup + +import ( + "html/template" + "net/url" + "regexp" + "strconv" + "strings" + + "code.gitea.io/gitea/modules/httplib" + "code.gitea.io/gitea/modules/log" + + "golang.org/x/net/html" +) + +// codePreviewPattern matches "http://domain/.../{owner}/{repo}/src/commit/{commit}/{filepath}#L10-L20" +var codePreviewPattern = regexp.MustCompile(`https?://\S+/([^\s/]+)/([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)`) + +type RenderCodePreviewOptions struct { + FullURL string + OwnerName string + RepoName string + CommitID string + FilePath string + + LineStart, LineStop int +} + +func renderCodeBlock(ctx *RenderContext, node *html.Node) (urlPosStart, urlPosStop int, htm template.HTML, err error) { + m := codePreviewPattern.FindStringSubmatchIndex(node.Data) + if m == nil { + return 0, 0, "", nil + } + + opts := RenderCodePreviewOptions{ + FullURL: node.Data[m[0]:m[1]], + OwnerName: node.Data[m[2]:m[3]], + RepoName: node.Data[m[4]:m[5]], + CommitID: node.Data[m[6]:m[7]], + FilePath: node.Data[m[8]:m[9]], + } + if !httplib.IsCurrentGiteaSiteURL(opts.FullURL) { + return 0, 0, "", nil + } + u, err := url.Parse(opts.FilePath) + if err != nil { + return 0, 0, "", err + } + opts.FilePath = strings.TrimPrefix(u.Path, "/") + + lineStartStr, lineStopStr, _ := strings.Cut(node.Data[m[10]:m[11]], "-") + lineStart, _ := strconv.Atoi(strings.TrimPrefix(lineStartStr, "L")) + lineStop, _ := strconv.Atoi(strings.TrimPrefix(lineStopStr, "L")) + opts.LineStart, opts.LineStop = lineStart, lineStop + h, err := DefaultProcessorHelper.RenderRepoFileCodePreview(ctx.Ctx, opts) + return m[0], m[1], h, err +} + +func codePreviewPatternProcessor(ctx *RenderContext, node *html.Node) { + for node != nil { + if node.Type != html.TextNode { + node = node.NextSibling + continue + } + urlPosStart, urlPosEnd, h, err := renderCodeBlock(ctx, node) + if err != nil || h == "" { + if err != nil { + log.Error("Unable to render code preview: %v", err) + } + node = node.NextSibling + continue + } + next := node.NextSibling + textBefore := node.Data[:urlPosStart] + textAfter := node.Data[urlPosEnd:] + // "textBefore" could be empty if there is only a URL in the text node, then an empty node (p, or li) will be left here. + // However, the empty node can't be simply removed, because: + // 1. the following processors will still try to access it (need to double-check undefined behaviors) + // 2. the new node is inserted as "

{TextBefore}

{TextAfter}

" (the parent could also be "li") + // then it is resolved as: "

{TextBefore}

{TextAfter}

", + // so unless it could correctly replace the parent "p/li" node, it is very difficult to eliminate the "TextBefore" empty node. + node.Data = textBefore + node.Parent.InsertBefore(&html.Node{Type: html.RawNode, Data: string(h)}, next) + if textAfter != "" { + node.Parent.InsertBefore(&html.Node{Type: html.TextNode, Data: textAfter}, next) + } + node = next + } +} diff --git a/modules/markup/html_codepreview_test.go b/modules/markup/html_codepreview_test.go new file mode 100644 index 0000000000..d33630d040 --- /dev/null +++ b/modules/markup/html_codepreview_test.go @@ -0,0 +1,34 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markup_test + +import ( + "context" + "html/template" + "strings" + "testing" + + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/markup" + + "github.com/stretchr/testify/assert" +) + +func TestRenderCodePreview(t *testing.T) { + markup.Init(&markup.ProcessorHelper{ + RenderRepoFileCodePreview: func(ctx context.Context, opts markup.RenderCodePreviewOptions) (template.HTML, error) { + return "
code preview
", nil + }, + }) + test := func(input, expected string) { + buffer, err := markup.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Type: "markdown", + }, input) + assert.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) + } + test("http://localhost:3000/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20", "

code preview

") + test("http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20", `

http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20

`) +} diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index 93ba9d7667..e313be7040 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -287,6 +287,7 @@ func TestRender_IssueIndexPattern_Document(t *testing.T) { } func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *RenderContext) { + ctx.Links.AbsolutePrefix = true if ctx.Links.Base == "" { ctx.Links.Base = TestRepoURL } diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index ccb63c6bab..916e74fb62 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -43,7 +43,8 @@ func TestRender_Commits(t *testing.T) { Ctx: git.DefaultContext, RelativePath: ".md", Links: markup.Links{ - Base: markup.TestRepoURL, + AbsolutePrefix: true, + Base: markup.TestRepoURL, }, Metas: localMetas, }, input) @@ -96,7 +97,8 @@ func TestRender_CrossReferences(t *testing.T) { Ctx: git.DefaultContext, RelativePath: "a.md", Links: markup.Links{ - Base: setting.AppSubURL, + AbsolutePrefix: true, + Base: setting.AppSubURL, }, Metas: localMetas, }, input) @@ -425,6 +427,10 @@ func TestRender_ShortLinks(t *testing.T) { otherImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+Other.jpg") encodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+%23.jpg") notencodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "some", "path", "Link+#.jpg") + renderableFileURL := util.URLJoin(tree, "markdown_file.md") + renderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "markdown_file.md") + unrenderableFileURL := util.URLJoin(tree, "file.zip") + unrenderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "file.zip") favicon := "http://google.com/favicon.ico" test( @@ -479,6 +485,14 @@ func TestRender_ShortLinks(t *testing.T) { "[[Link]] [[Other Link]] [[Link?]]", `

Link Other Link Link?

`, `

Link Other Link Link?

`) + test( + "[[markdown_file.md]]", + `

markdown_file.md

`, + `

markdown_file.md

`) + test( + "[[file.zip]]", + `

file.zip

`, + `

file.zip

`) test( "[[Link #.jpg]]", `

Link #.jpg

`, @@ -588,7 +602,8 @@ func TestPostProcess_RenderDocument(t *testing.T) { err := markup.PostProcess(&markup.RenderContext{ Ctx: git.DefaultContext, Links: markup.Links{ - Base: "https://example.com", + AbsolutePrefix: true, + Base: "https://example.com", }, Metas: localMetas, }, strings.NewReader(input), &res) diff --git a/modules/markup/markdown/ast.go b/modules/markup/markdown/ast.go index 77ce5cb359..624c35d945 100644 --- a/modules/markup/markdown/ast.go +++ b/modules/markup/markdown/ast.go @@ -175,13 +175,6 @@ func NewColorPreview(color []byte) *ColorPreview { } } -// IsColorPreview returns true if the given node implements the ColorPreview interface, -// otherwise false. -func IsColorPreview(node ast.Node) bool { - _, ok := node.(*ColorPreview) - return ok -} - // Attention is an inline for an attention type Attention struct { ast.BaseInline diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 67817ce27b..b8b3aeaab0 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -4,19 +4,14 @@ package markdown import ( - "bytes" "fmt" "regexp" "strings" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/markup" - "code.gitea.io/gitea/modules/markup/common" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/svg" - giteautil "code.gitea.io/gitea/modules/util" - "github.com/microcosm-cc/bluemonday/css" "github.com/yuin/goldmark/ast" east "github.com/yuin/goldmark/extension/ast" "github.com/yuin/goldmark/parser" @@ -27,7 +22,21 @@ import ( ) // ASTTransformer is a default transformer of the goldmark tree. -type ASTTransformer struct{} +type ASTTransformer struct { + attentionTypes container.Set[string] +} + +func NewASTTransformer() *ASTTransformer { + return &ASTTransformer{ + attentionTypes: container.SetOf("note", "tip", "important", "warning", "caution"), + } +} + +func (g *ASTTransformer) applyElementDir(n ast.Node) { + if markup.DefaultProcessorHelper.ElementDir != "" { + n.SetAttributeString("dir", []byte(markup.DefaultProcessorHelper.ElementDir)) + } +} // Transform transforms the given AST tree. func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) { @@ -45,12 +54,6 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa tocMode = rc.TOC } - applyElementDir := func(n ast.Node) { - if markup.DefaultProcessorHelper.ElementDir != "" { - n.SetAttributeString("dir", []byte(markup.DefaultProcessorHelper.ElementDir)) - } - } - _ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { if !entering { return ast.WalkContinue, nil @@ -58,123 +61,15 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa switch v := n.(type) { case *ast.Heading: - for _, attr := range v.Attributes() { - if _, ok := attr.Value.([]byte); !ok { - v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value))) - } - } - txt := n.Text(reader.Source()) - header := markup.Header{ - Text: util.BytesToReadOnlyString(txt), - Level: v.Level, - } - if id, found := v.AttributeString("id"); found { - header.ID = util.BytesToReadOnlyString(id.([]byte)) - } - tocList = append(tocList, header) - applyElementDir(v) + g.transformHeading(ctx, v, reader, &tocList) case *ast.Paragraph: - applyElementDir(v) + g.applyElementDir(v) case *ast.Image: - // Images need two things: - // - // 1. Their src needs to munged to be a real value - // 2. If they're not wrapped with a link they need a link wrapper - - // Check if the destination is a real link - if len(v.Destination) > 0 && !markup.IsFullURLBytes(v.Destination) { - v.Destination = []byte(giteautil.URLJoin( - ctx.Links.ResolveMediaLink(ctx.IsWiki), - strings.TrimLeft(string(v.Destination), "/"), - )) - } - - parent := n.Parent() - // Create a link around image only if parent is not already a link - if _, ok := parent.(*ast.Link); !ok && parent != nil { - next := n.NextSibling() - - // Create a link wrapper - wrap := ast.NewLink() - wrap.Destination = v.Destination - wrap.Title = v.Title - wrap.SetAttributeString("target", []byte("_blank")) - - // Duplicate the current image node - image := ast.NewImage(ast.NewLink()) - image.Destination = v.Destination - image.Title = v.Title - for _, attr := range v.Attributes() { - image.SetAttribute(attr.Name, attr.Value) - } - for child := v.FirstChild(); child != nil; { - next := child.NextSibling() - image.AppendChild(image, child) - child = next - } - - // Append our duplicate image to the wrapper link - wrap.AppendChild(wrap, image) - - // Wire in the next sibling - wrap.SetNextSibling(next) - - // Replace the current node with the wrapper link - parent.ReplaceChild(parent, n, wrap) - - // But most importantly ensure the next sibling is still on the old image too - v.SetNextSibling(next) - } + g.transformImage(ctx, v, reader) case *ast.Link: - // Links need their href to munged to be a real value - link := v.Destination - isAnchorFragment := len(link) > 0 && link[0] == '#' - if !isAnchorFragment && !markup.IsFullURLBytes(link) { - base := ctx.Links.Base - if ctx.IsWiki { - base = ctx.Links.WikiLink() - } else if ctx.Links.HasBranchInfo() { - base = ctx.Links.SrcLink() - } - link = []byte(giteautil.URLJoin(base, string(link))) - } - if isAnchorFragment { - link = []byte("#user-content-" + string(link)[1:]) - } - v.Destination = link + g.transformLink(ctx, v, reader) case *ast.List: - if v.HasChildren() { - children := make([]ast.Node, 0, v.ChildCount()) - child := v.FirstChild() - for child != nil { - children = append(children, child) - child = child.NextSibling() - } - v.RemoveChildren(v) - - for _, child := range children { - listItem := child.(*ast.ListItem) - if !child.HasChildren() || !child.FirstChild().HasChildren() { - v.AppendChild(v, child) - continue - } - taskCheckBox, ok := child.FirstChild().FirstChild().(*east.TaskCheckBox) - if !ok { - v.AppendChild(v, child) - continue - } - newChild := NewTaskCheckBoxListItem(listItem) - newChild.IsChecked = taskCheckBox.IsChecked - newChild.SetAttributeString("class", []byte("task-list-item")) - segments := newChild.FirstChild().Lines() - if segments.Len() > 0 { - segment := segments.At(0) - newChild.SourcePosition = rc.metaLength + segment.Start - } - v.AppendChild(v, newChild) - } - } - applyElementDir(v) + g.transformList(ctx, v, reader, rc) case *ast.Text: if v.SoftLineBreak() && !v.HardLineBreak() { if ctx.Metas["mode"] != "document" { @@ -184,56 +79,9 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa } } case *ast.CodeSpan: - colorContent := n.Text(reader.Source()) - if css.ColorHandler(strings.ToLower(string(colorContent))) { - v.AppendChild(v, NewColorPreview(colorContent)) - } + g.transformCodeSpan(ctx, v, reader) case *ast.Blockquote: - // We only want attention blockquotes when the AST looks like: - // Text: "[" - // Text: "!TYPE" - // Text(SoftLineBreak): "]" - - // grab these nodes and make sure we adhere to the attention blockquote structure - firstParagraph := v.FirstChild() - if firstParagraph.ChildCount() < 3 { - return ast.WalkContinue, nil - } - firstTextNode, ok := firstParagraph.FirstChild().(*ast.Text) - if !ok || string(firstTextNode.Segment.Value(reader.Source())) != "[" { - return ast.WalkContinue, nil - } - secondTextNode, ok := firstTextNode.NextSibling().(*ast.Text) - if !ok || !attentionTypeRE.MatchString(string(secondTextNode.Segment.Value(reader.Source()))) { - return ast.WalkContinue, nil - } - thirdTextNode, ok := secondTextNode.NextSibling().(*ast.Text) - if !ok || string(thirdTextNode.Segment.Value(reader.Source())) != "]" { - return ast.WalkContinue, nil - } - - // grab attention type from markdown source - attentionType := strings.ToLower(strings.TrimPrefix(string(secondTextNode.Segment.Value(reader.Source())), "!")) - - // color the blockquote - v.SetAttributeString("class", []byte("gt-py-3 attention attention-"+attentionType)) - - // create an emphasis to make it bold - attentionParagraph := ast.NewParagraph() - emphasis := ast.NewEmphasis(2) - emphasis.SetAttributeString("class", []byte("attention-"+attentionType)) - - // capitalize first letter - attentionText := ast.NewString([]byte(strings.ToUpper(string(attentionType[0])) + attentionType[1:])) - - // replace the ![TYPE] with a dedicated paragraph of icon+Type - emphasis.AppendChild(emphasis, attentionText) - attentionParagraph.AppendChild(attentionParagraph, NewAttention(attentionType)) - attentionParagraph.AppendChild(attentionParagraph, emphasis) - firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph) - firstParagraph.RemoveChild(firstParagraph, firstTextNode) - firstParagraph.RemoveChild(firstParagraph, secondTextNode) - firstParagraph.RemoveChild(firstParagraph, thirdTextNode) + return g.transformBlockquote(v, reader) } return ast.WalkContinue, nil }) @@ -255,55 +103,12 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa } } -type prefixedIDs struct { - values container.Set[string] -} - -// Generate generates a new element id. -func (p *prefixedIDs) Generate(value []byte, kind ast.NodeKind) []byte { - dft := []byte("id") - if kind == ast.KindHeading { - dft = []byte("heading") - } - return p.GenerateWithDefault(value, dft) -} - -// Generate generates a new element id. -func (p *prefixedIDs) GenerateWithDefault(value, dft []byte) []byte { - result := common.CleanValue(value) - if len(result) == 0 { - result = dft - } - if !bytes.HasPrefix(result, []byte("user-content-")) { - result = append([]byte("user-content-"), result...) - } - if p.values.Add(util.BytesToReadOnlyString(result)) { - return result - } - for i := 1; ; i++ { - newResult := fmt.Sprintf("%s-%d", result, i) - if p.values.Add(newResult) { - return []byte(newResult) - } - } -} - -// Put puts a given element id to the used ids table. -func (p *prefixedIDs) Put(value []byte) { - p.values.Add(util.BytesToReadOnlyString(value)) -} - -func newPrefixedIDs() *prefixedIDs { - return &prefixedIDs{ - values: make(container.Set[string]), - } -} - // NewHTMLRenderer creates a HTMLRenderer to render // in the gitea form. func NewHTMLRenderer(opts ...html.Option) renderer.NodeRenderer { r := &HTMLRenderer{ - Config: html.NewConfig(), + Config: html.NewConfig(), + reValidName: regexp.MustCompile("^[a-z ]+$"), } for _, opt := range opts { opt.SetHTMLOption(&r.Config) @@ -315,6 +120,7 @@ func NewHTMLRenderer(opts ...html.Option) renderer.NodeRenderer { // renders gitea specific features. type HTMLRenderer struct { html.Config + reValidName *regexp.Regexp } // RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs. @@ -329,66 +135,6 @@ func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) { reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox) } -// renderCodeSpan renders CodeSpan elements (like goldmark upstream does) but also renders ColorPreview elements. -// See #21474 for reference -func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { - if entering { - if n.Attributes() != nil { - _, _ = w.WriteString("') - } else { - _, _ = w.WriteString("") - } - for c := n.FirstChild(); c != nil; c = c.NextSibling() { - switch v := c.(type) { - case *ast.Text: - segment := v.Segment - value := segment.Value(source) - if bytes.HasSuffix(value, []byte("\n")) { - r.Writer.RawWrite(w, value[:len(value)-1]) - r.Writer.RawWrite(w, []byte(" ")) - } else { - r.Writer.RawWrite(w, value) - } - case *ColorPreview: - _, _ = w.WriteString(fmt.Sprintf(``, string(v.Color))) - } - } - return ast.WalkSkipChildren, nil - } - _, _ = w.WriteString("") - return ast.WalkContinue, nil -} - -// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg -func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { - if entering { - _, _ = w.WriteString(``) - - var octiconType string - switch n.AttentionType { - case "note": - octiconType = "info" - case "tip": - octiconType = "light-bulb" - case "important": - octiconType = "report" - case "warning": - octiconType = "alert" - case "caution": - octiconType = "stop" - } - _, _ = w.WriteString(string(svg.RenderHTML("octicon-" + octiconType))) - } else { - _, _ = w.WriteString("\n") - } - return ast.WalkContinue, nil -} - func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { n := node.(*ast.Document) @@ -448,11 +194,6 @@ func (r *HTMLRenderer) renderSummary(w util.BufWriter, source []byte, node ast.N return ast.WalkContinue, nil } -var ( - validNameRE = regexp.MustCompile("^[a-z ]+$") - attentionTypeRE = regexp.MustCompile("^!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)$") -) - func (r *HTMLRenderer) renderIcon(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { if !entering { return ast.WalkContinue, nil @@ -467,7 +208,7 @@ func (r *HTMLRenderer) renderIcon(w util.BufWriter, source []byte, node ast.Node return ast.WalkContinue, nil } - if !validNameRE.MatchString(name) { + if !r.reValidName.MatchString(name) { // skip this return ast.WalkContinue, nil } @@ -480,38 +221,3 @@ func (r *HTMLRenderer) renderIcon(w util.BufWriter, source []byte, node ast.Node return ast.WalkContinue, nil } - -func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { - n := node.(*TaskCheckBoxListItem) - if entering { - if n.Attributes() != nil { - _, _ = w.WriteString("') - } else { - _, _ = w.WriteString("
  • ") - } - fmt.Fprintf(w, ``) - } else { - _ = w.WriteByte('>') - } - fc := n.FirstChild() - if fc != nil { - if _, ok := fc.(*ast.TextBlock); !ok { - _ = w.WriteByte('\n') - } - } - } else { - _, _ = w.WriteString("
  • \n") - } - return ast.WalkContinue, nil -} - -func (r *HTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { - return ast.WalkContinue, nil -} diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index f0b1afa27e..db4e5706f6 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -104,7 +104,8 @@ func SpecializedMarkdown() goldmark.Markdown { } // include language-x class as part of commonmark spec - _, err = w.WriteString(``) + // the "display" class is used by "js/markup/math.js" to render the code element as a block + _, err = w.WriteString(``) if err != nil { return } @@ -125,7 +126,7 @@ func SpecializedMarkdown() goldmark.Markdown { parser.WithAttribute(), parser.WithAutoHeadingID(), parser.WithASTTransformers( - util.Prioritized(&ASTTransformer{}, 10000), + util.Prioritized(NewASTTransformer(), 10000), ), ), goldmark.WithRendererOptions( diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index dbf95e5e62..bc6ad7fb3c 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -16,9 +16,12 @@ import ( "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/svg" "code.gitea.io/gitea/modules/util" "github.com/stretchr/testify/assert" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) const ( @@ -130,11 +133,11 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
  • Links, Language bindings, Engine bindings
  • Tips
  • -

    See commit 65f1bf27bc

    +

    See commit 65f1bf27bc

    Ideas and codes

      -
    • Bezier widget (by @r-lyeh) ocornut/imgui#786
    • -
    • Bezier widget (by @r-lyeh) #786
    • +
    • Bezier widget (by @r-lyeh) ocornut/imgui#786
    • +
    • Bezier widget (by @r-lyeh) #786
    • Node graph editors https://github.com/ocornut/imgui/issues/306
    • Memory Editor
    • Plot var helper
    • @@ -433,6 +436,10 @@ func TestColorPreview(t *testing.T) { testcase string expected string }{ + { // do not render color names + "The CSS class `red` is there", + "

      The CSS class red is there

      \n", + }, { // hex "`#FF0000`", `

      #FF0000

      ` + nl, @@ -442,8 +449,8 @@ func TestColorPreview(t *testing.T) { `

      rgb(16, 32, 64)

      ` + nl, }, { // short hex - "This is the color white `#000`", - `

      This is the color white #000

      ` + nl, + "This is the color white `#0a0`", + `

      This is the color white #0a0

      ` + nl, }, { // hsl "HSL stands for hue, saturation, and lightness. An example: `hsl(0, 100%, 50%)`.", @@ -459,7 +466,6 @@ func TestColorPreview(t *testing.T) { res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) - } negativeTests := []string{ @@ -504,9 +510,17 @@ func TestMathBlock(t *testing.T) { `\(a\) \(b\)`, `

      a b

      ` + nl, }, + { + `$a$.`, + `

      a.

      ` + nl, + }, + { + `.$a$`, + `

      .$a$

      ` + nl, + }, { `$a a$b b$`, - `

      a a$b b

      ` + nl, + `

      $a a$b b$

      ` + nl, }, { `a a$b b`, @@ -514,7 +528,15 @@ func TestMathBlock(t *testing.T) { }, { `a$b $a a$b b$`, - `

      a$b a a$b b

      ` + nl, + `

      a$b $a a$b b$

      ` + nl, + }, + { + "a$x$", + `

      a$x$

      ` + nl, + }, + { + "$x$a", + `

      $x$a

      ` + nl, }, { "$$a$$", @@ -526,7 +548,6 @@ func TestMathBlock(t *testing.T) { res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) - } } @@ -630,9 +651,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -688,9 +709,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -746,9 +767,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -806,9 +827,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -866,9 +887,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -928,9 +949,9 @@ space

      Expected: `

      space @mention-user
      /just/a/path.bin
      https://example.com/file.bin
      -local link
      +local link
      remote link
      -local link
      +local link
      remote link
      local image
      local image
      @@ -957,3 +978,36 @@ space

      assert.Equal(t, template.HTML(c.Expected), result, "Unexpected result in testcase %v", i) } } + +func TestAttention(t *testing.T) { + defer svg.MockIcon("octicon-info")() + defer svg.MockIcon("octicon-light-bulb")() + defer svg.MockIcon("octicon-report")() + defer svg.MockIcon("octicon-alert")() + defer svg.MockIcon("octicon-stop")() + + renderAttention := func(attention, icon string) string { + tmpl := `

      {Attention}

      ` + tmpl = strings.ReplaceAll(tmpl, "{attention}", attention) + tmpl = strings.ReplaceAll(tmpl, "{icon}", icon) + tmpl = strings.ReplaceAll(tmpl, "{Attention}", cases.Title(language.English).String(attention)) + return tmpl + } + + test := func(input, expected string) { + result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background()}, input) + assert.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(result))) + } + + test(` +> [!NOTE] +> text +`, renderAttention("note", "octicon-info")+"\n

      text

      \n
      ") + + test(`> [!note]`, renderAttention("note", "octicon-info")+"\n") + test(`> [!tip]`, renderAttention("tip", "octicon-light-bulb")+"\n") + test(`> [!important]`, renderAttention("important", "octicon-report")+"\n") + test(`> [!warning]`, renderAttention("warning", "octicon-alert")+"\n") + test(`> [!caution]`, renderAttention("caution", "octicon-stop")+"\n") +} diff --git a/modules/markup/markdown/math/inline_parser.go b/modules/markup/markdown/math/inline_parser.go index 0ac25c2b2a..862234e69b 100644 --- a/modules/markup/markdown/math/inline_parser.go +++ b/modules/markup/markdown/math/inline_parser.go @@ -41,9 +41,12 @@ func (parser *inlineParser) Trigger() []byte { return parser.start[0:1] } +func isPunctuation(b byte) bool { + return b == '.' || b == '!' || b == '?' || b == ',' || b == ';' || b == ':' +} + func isAlphanumeric(b byte) bool { - // Github only cares about 0-9A-Za-z - return (b >= '0' && b <= '9') || (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') } // Parse parses the current line and returns a result of parsing. @@ -56,7 +59,7 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. } precedingCharacter := block.PrecendingCharacter() - if precedingCharacter < 256 && isAlphanumeric(byte(precedingCharacter)) { + if precedingCharacter < 256 && (isAlphanumeric(byte(precedingCharacter)) || isPunctuation(byte(precedingCharacter))) { // need to exclude things like `a$` from being considered a start return nil } @@ -75,14 +78,19 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. ender += pos // Now we want to check the character at the end of our parser section - // that is ender + len(parser.end) + // that is ender + len(parser.end) and check if char before ender is '\' pos = ender + len(parser.end) if len(line) <= pos { break } - if !isAlphanumeric(line[pos]) { + suceedingCharacter := line[pos] + if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') { + return nil + } + if line[ender-1] != '\\' { break } + // move the pointer onwards ender += len(parser.end) } diff --git a/modules/markup/markdown/prefixed_id.go b/modules/markup/markdown/prefixed_id.go new file mode 100644 index 0000000000..9c60949202 --- /dev/null +++ b/modules/markup/markdown/prefixed_id.go @@ -0,0 +1,59 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "bytes" + "fmt" + + "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/markup/common" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/util" +) + +type prefixedIDs struct { + values container.Set[string] +} + +// Generate generates a new element id. +func (p *prefixedIDs) Generate(value []byte, kind ast.NodeKind) []byte { + dft := []byte("id") + if kind == ast.KindHeading { + dft = []byte("heading") + } + return p.GenerateWithDefault(value, dft) +} + +// GenerateWithDefault generates a new element id. +func (p *prefixedIDs) GenerateWithDefault(value, dft []byte) []byte { + result := common.CleanValue(value) + if len(result) == 0 { + result = dft + } + if !bytes.HasPrefix(result, []byte("user-content-")) { + result = append([]byte("user-content-"), result...) + } + if p.values.Add(util.BytesToReadOnlyString(result)) { + return result + } + for i := 1; ; i++ { + newResult := fmt.Sprintf("%s-%d", result, i) + if p.values.Add(newResult) { + return []byte(newResult) + } + } +} + +// Put puts a given element id to the used ids table. +func (p *prefixedIDs) Put(value []byte) { + p.values.Add(util.BytesToReadOnlyString(value)) +} + +func newPrefixedIDs() *prefixedIDs { + return &prefixedIDs{ + values: make(container.Set[string]), + } +} diff --git a/modules/markup/markdown/transform_blockquote.go b/modules/markup/markdown/transform_blockquote.go new file mode 100644 index 0000000000..933f0e5c59 --- /dev/null +++ b/modules/markup/markdown/transform_blockquote.go @@ -0,0 +1,98 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "strings" + + "code.gitea.io/gitea/modules/svg" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" + "github.com/yuin/goldmark/util" + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg +func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + if entering { + n := node.(*Attention) + var octiconName string + switch n.AttentionType { + case "tip": + octiconName = "light-bulb" + case "important": + octiconName = "report" + case "warning": + octiconName = "alert" + case "caution": + octiconName = "stop" + default: // including "note" + octiconName = "info" + } + _, _ = w.WriteString(string(svg.RenderHTML("octicon-"+octiconName, 16, "attention-icon attention-"+n.AttentionType))) + } + return ast.WalkContinue, nil +} + +func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) { + // We only want attention blockquotes when the AST looks like: + // > Text("[") Text("!TYPE") Text("]") + + // grab these nodes and make sure we adhere to the attention blockquote structure + firstParagraph := v.FirstChild() + g.applyElementDir(firstParagraph) + if firstParagraph.ChildCount() < 3 { + return ast.WalkContinue, nil + } + node1, ok := firstParagraph.FirstChild().(*ast.Text) + if !ok { + return ast.WalkContinue, nil + } + node2, ok := node1.NextSibling().(*ast.Text) + if !ok { + return ast.WalkContinue, nil + } + node3, ok := node2.NextSibling().(*ast.Text) + if !ok { + return ast.WalkContinue, nil + } + val1 := string(node1.Segment.Value(reader.Source())) + val2 := string(node2.Segment.Value(reader.Source())) + val3 := string(node3.Segment.Value(reader.Source())) + if val1 != "[" || val3 != "]" || !strings.HasPrefix(val2, "!") { + return ast.WalkContinue, nil + } + + // grab attention type from markdown source + attentionType := strings.ToLower(val2[1:]) + if !g.attentionTypes.Contains(attentionType) { + return ast.WalkContinue, nil + } + + // color the blockquote + v.SetAttributeString("class", []byte("attention-header attention-"+attentionType)) + + // create an emphasis to make it bold + attentionParagraph := ast.NewParagraph() + g.applyElementDir(attentionParagraph) + emphasis := ast.NewEmphasis(2) + emphasis.SetAttributeString("class", []byte("attention-"+attentionType)) + + attentionAstString := ast.NewString([]byte(cases.Title(language.English).String(attentionType))) + + // replace the ![TYPE] with a dedicated paragraph of icon+Type + emphasis.AppendChild(emphasis, attentionAstString) + attentionParagraph.AppendChild(attentionParagraph, NewAttention(attentionType)) + attentionParagraph.AppendChild(attentionParagraph, emphasis) + firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph) + firstParagraph.RemoveChild(firstParagraph, node1) + firstParagraph.RemoveChild(firstParagraph, node2) + firstParagraph.RemoveChild(firstParagraph, node3) + if firstParagraph.ChildCount() == 0 { + firstParagraph.Parent().RemoveChild(firstParagraph.Parent(), firstParagraph) + } + return ast.WalkContinue, nil +} diff --git a/modules/markup/markdown/transform_codespan.go b/modules/markup/markdown/transform_codespan.go new file mode 100644 index 0000000000..5b07d72999 --- /dev/null +++ b/modules/markup/markdown/transform_codespan.go @@ -0,0 +1,76 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "bytes" + "fmt" + "strings" + + "code.gitea.io/gitea/modules/markup" + + "github.com/microcosm-cc/bluemonday/css" + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/renderer/html" + "github.com/yuin/goldmark/text" + "github.com/yuin/goldmark/util" +) + +// renderCodeSpan renders CodeSpan elements (like goldmark upstream does) but also renders ColorPreview elements. +// See #21474 for reference +func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { + if entering { + if n.Attributes() != nil { + _, _ = w.WriteString("') + } else { + _, _ = w.WriteString("") + } + for c := n.FirstChild(); c != nil; c = c.NextSibling() { + switch v := c.(type) { + case *ast.Text: + segment := v.Segment + value := segment.Value(source) + if bytes.HasSuffix(value, []byte("\n")) { + r.Writer.RawWrite(w, value[:len(value)-1]) + r.Writer.RawWrite(w, []byte(" ")) + } else { + r.Writer.RawWrite(w, value) + } + case *ColorPreview: + _, _ = w.WriteString(fmt.Sprintf(``, string(v.Color))) + } + } + return ast.WalkSkipChildren, nil + } + _, _ = w.WriteString("") + return ast.WalkContinue, nil +} + +// cssColorHandler checks if a string is a render-able CSS color value. +// The code is from "github.com/microcosm-cc/bluemonday/css.ColorHandler", except that it doesn't handle color words like "red". +func cssColorHandler(value string) bool { + value = strings.ToLower(value) + if css.HexRGB.MatchString(value) { + return true + } + if css.RGB.MatchString(value) { + return true + } + if css.RGBA.MatchString(value) { + return true + } + if css.HSL.MatchString(value) { + return true + } + return css.HSLA.MatchString(value) +} + +func (g *ASTTransformer) transformCodeSpan(ctx *markup.RenderContext, v *ast.CodeSpan, reader text.Reader) { + colorContent := v.Text(reader.Source()) + if cssColorHandler(string(colorContent)) { + v.AppendChild(v, NewColorPreview(colorContent)) + } +} diff --git a/modules/markup/markdown/transform_heading.go b/modules/markup/markdown/transform_heading.go new file mode 100644 index 0000000000..ce585a37de --- /dev/null +++ b/modules/markup/markdown/transform_heading.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "fmt" + + "code.gitea.io/gitea/modules/markup" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" + "github.com/yuin/goldmark/util" +) + +func (g *ASTTransformer) transformHeading(ctx *markup.RenderContext, v *ast.Heading, reader text.Reader, tocList *[]markup.Header) { + for _, attr := range v.Attributes() { + if _, ok := attr.Value.([]byte); !ok { + v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value))) + } + } + txt := v.Text(reader.Source()) + header := markup.Header{ + Text: util.BytesToReadOnlyString(txt), + Level: v.Level, + } + if id, found := v.AttributeString("id"); found { + header.ID = util.BytesToReadOnlyString(id.([]byte)) + } + *tocList = append(*tocList, header) + g.applyElementDir(v) +} diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go new file mode 100644 index 0000000000..f290dc3721 --- /dev/null +++ b/modules/markup/markdown/transform_image.go @@ -0,0 +1,66 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "strings" + + "code.gitea.io/gitea/modules/markup" + giteautil "code.gitea.io/gitea/modules/util" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" +) + +func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image, reader text.Reader) { + // Images need two things: + // + // 1. Their src needs to munged to be a real value + // 2. If they're not wrapped with a link they need a link wrapper + + // Check if the destination is a real link + if len(v.Destination) > 0 && !markup.IsFullURLBytes(v.Destination) { + v.Destination = []byte(giteautil.URLJoin( + ctx.Links.ResolveMediaLink(ctx.IsWiki), + strings.TrimLeft(string(v.Destination), "/"), + )) + } + + parent := v.Parent() + // Create a link around image only if parent is not already a link + if _, ok := parent.(*ast.Link); !ok && parent != nil { + next := v.NextSibling() + + // Create a link wrapper + wrap := ast.NewLink() + wrap.Destination = v.Destination + wrap.Title = v.Title + wrap.SetAttributeString("target", []byte("_blank")) + + // Duplicate the current image node + image := ast.NewImage(ast.NewLink()) + image.Destination = v.Destination + image.Title = v.Title + for _, attr := range v.Attributes() { + image.SetAttribute(attr.Name, attr.Value) + } + for child := v.FirstChild(); child != nil; { + next := child.NextSibling() + image.AppendChild(image, child) + child = next + } + + // Append our duplicate image to the wrapper link + wrap.AppendChild(wrap, image) + + // Wire in the next sibling + wrap.SetNextSibling(next) + + // Replace the current node with the wrapper link + parent.ReplaceChild(parent, v, wrap) + + // But most importantly ensure the next sibling is still on the old image too + v.SetNextSibling(next) + } +} diff --git a/modules/markup/markdown/transform_link.go b/modules/markup/markdown/transform_link.go new file mode 100644 index 0000000000..7e305b74bc --- /dev/null +++ b/modules/markup/markdown/transform_link.go @@ -0,0 +1,42 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "path/filepath" + + "code.gitea.io/gitea/modules/markup" + giteautil "code.gitea.io/gitea/modules/util" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" +) + +func (g *ASTTransformer) transformLink(ctx *markup.RenderContext, v *ast.Link, reader text.Reader) { + // Links need their href to munged to be a real value + link := v.Destination + isAnchorFragment := len(link) > 0 && link[0] == '#' + if !isAnchorFragment && !markup.IsFullURLBytes(link) { + base := ctx.Links.Base + if ctx.IsWiki { + if filepath.Ext(string(link)) == "" { + // This link doesn't have a file extension - assume a regular wiki link + base = ctx.Links.WikiLink() + } else if markup.Type(string(link)) != "" { + // If it's a file type we can render, use a regular wiki link + base = ctx.Links.WikiLink() + } else { + // Otherwise, use a raw link instead + base = ctx.Links.WikiRawLink() + } + } else if ctx.Links.HasBranchInfo() { + base = ctx.Links.SrcLink() + } + link = []byte(giteautil.URLJoin(base, string(link))) + } + if isAnchorFragment { + link = []byte("#user-content-" + string(link)[1:]) + } + v.Destination = link +} diff --git a/modules/markup/markdown/transform_list.go b/modules/markup/markdown/transform_list.go new file mode 100644 index 0000000000..6563e2dd64 --- /dev/null +++ b/modules/markup/markdown/transform_list.go @@ -0,0 +1,86 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown + +import ( + "fmt" + + "code.gitea.io/gitea/modules/markup" + + "github.com/yuin/goldmark/ast" + east "github.com/yuin/goldmark/extension/ast" + "github.com/yuin/goldmark/renderer/html" + "github.com/yuin/goldmark/text" + "github.com/yuin/goldmark/util" +) + +func (r *HTMLRenderer) renderTaskCheckBoxListItem(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + n := node.(*TaskCheckBoxListItem) + if entering { + if n.Attributes() != nil { + _, _ = w.WriteString("') + } else { + _, _ = w.WriteString("
    • ") + } + fmt.Fprintf(w, ``) + } else { + _ = w.WriteByte('>') + } + fc := n.FirstChild() + if fc != nil { + if _, ok := fc.(*ast.TextBlock); !ok { + _ = w.WriteByte('\n') + } + } + } else { + _, _ = w.WriteString("
    • \n") + } + return ast.WalkContinue, nil +} + +func (r *HTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + return ast.WalkContinue, nil +} + +func (g *ASTTransformer) transformList(ctx *markup.RenderContext, v *ast.List, reader text.Reader, rc *RenderConfig) { + if v.HasChildren() { + children := make([]ast.Node, 0, v.ChildCount()) + child := v.FirstChild() + for child != nil { + children = append(children, child) + child = child.NextSibling() + } + v.RemoveChildren(v) + + for _, child := range children { + listItem := child.(*ast.ListItem) + if !child.HasChildren() || !child.FirstChild().HasChildren() { + v.AppendChild(v, child) + continue + } + taskCheckBox, ok := child.FirstChild().FirstChild().(*east.TaskCheckBox) + if !ok { + v.AppendChild(v, child) + continue + } + newChild := NewTaskCheckBoxListItem(listItem) + newChild.IsChecked = taskCheckBox.IsChecked + newChild.SetAttributeString("class", []byte("task-list-item")) + segments := newChild.FirstChild().Lines() + if segments.Len() > 0 { + segment := segments.At(0) + newChild.SourcePosition = rc.metaLength + segment.Start + } + v.AppendChild(v, newChild) + } + } + g.applyElementDir(v) +} diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go index 7f253ae5f1..25f8d15ef4 100644 --- a/modules/markup/orgmode/orgmode.go +++ b/modules/markup/orgmode/orgmode.go @@ -142,10 +142,18 @@ func (r *Writer) resolveLink(kind, link string) string { // so we need to try to guess the link kind again here kind = org.RegularLink{URL: link}.Kind() } + base := r.Ctx.Links.Base + if r.Ctx.IsWiki { + base = r.Ctx.Links.WikiLink() + } else if r.Ctx.Links.HasBranchInfo() { + base = r.Ctx.Links.SrcLink() + } + if kind == "image" || kind == "video" { base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsWiki) } + link = util.URLJoin(base, link) } return link diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index 95f53c9cc9..75b60ed81f 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -19,6 +19,30 @@ const AppURL = "http://localhost:3000/" func TestRender_StandardLinks(t *testing.T) { setting.AppURL = AppURL + test := func(input, expected string, isWiki bool) { + buffer, err := RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: "/relative-path", + BranchPath: "branch/main", + }, + IsWiki: isWiki, + }, input) + assert.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) + } + + test("[[https://google.com/]]", + `

      https://google.com/

      `, false) + test("[[WikiPage][The WikiPage Desc]]", + `

      The WikiPage Desc

      `, true) + test("[[ImageLink.svg][The Image Desc]]", + `

      The Image Desc

      `, false) +} + +func TestRender_InternalLinks(t *testing.T) { + setting.AppURL = AppURL + test := func(input, expected string) { buffer, err := RenderString(&markup.RenderContext{ Ctx: git.DefaultContext, @@ -31,12 +55,14 @@ func TestRender_StandardLinks(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - test("[[https://google.com/]]", - `

      https://google.com/

      `) - test("[[WikiPage][The WikiPage Desc]]", - `

      The WikiPage Desc

      `) - test("[[ImageLink.svg][The Image Desc]]", - `

      The Image Desc

      `) + test("[[file:test.org][Test]]", + `

      Test

      `) + test("[[./test.org][Test]]", + `

      Test

      `) + test("[[test.org][Test]]", + `

      Test

      `) + test("[[path/to/test.org][Test]]", + `

      Test

      `) } func TestRender_Media(t *testing.T) { diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go index 5a7adcc553..005fcc278b 100644 --- a/modules/markup/renderer.go +++ b/modules/markup/renderer.go @@ -8,6 +8,7 @@ import ( "context" "errors" "fmt" + "html/template" "io" "net/url" "path/filepath" @@ -33,6 +34,8 @@ type ProcessorHelper struct { IsUsernameMentionable func(ctx context.Context, username string) bool ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute + + RenderRepoFileCodePreview func(ctx context.Context, options RenderCodePreviewOptions) (template.HTML, error) } var DefaultProcessorHelper ProcessorHelper @@ -82,9 +85,17 @@ type RenderContext struct { } type Links struct { - Base string - BranchPath string - TreePath string + AbsolutePrefix bool + Base string + BranchPath string + TreePath string +} + +func (l *Links) Prefix() string { + if l.AbsolutePrefix { + return setting.AppURL + } + return setting.AppSubURL } func (l *Links) HasBranchInfo() bool { diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index ffc33c3b8e..570a1da248 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -60,14 +60,28 @@ func createDefaultPolicy() *bluemonday.Policy { // For JS code copy and Mermaid loading state policy.AllowAttrs("class").Matching(regexp.MustCompile(`^code-block( is-loading)?$`)).OnElements("pre") + // For code preview + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^code-preview-[-\w]+( file-content)?$`)).Globally() + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^lines-num$`)).OnElements("td") + policy.AllowAttrs("data-line-number").OnElements("span") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^lines-code chroma$`)).OnElements("td") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^code-inner$`)).OnElements("div") + + // For code preview (unicode escape) + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^file-view( unicode-escaped)?$`)).OnElements("table") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^lines-escape$`)).OnElements("td") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^toggle-escape-button btn interact-bg$`)).OnElements("a") // don't use button, button might submit a form + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(ambiguous-code-point|escaped-code-point|broken-code-point)$`)).OnElements("span") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^char$`)).OnElements("span") + policy.AllowAttrs("data-tooltip-content", "data-escaped").OnElements("span") + // For color preview policy.AllowAttrs("class").Matching(regexp.MustCompile(`^color-preview$`)).OnElements("span") // For attention - policy.AllowAttrs("class").Matching(regexp.MustCompile(`^gt-py-3 attention attention-\w+$`)).OnElements("blockquote") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-header attention-\w+$`)).OnElements("blockquote") policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-\w+$`)).OnElements("strong") - policy.AllowAttrs("class").Matching(regexp.MustCompile(`^gt-mr-2 gt-vm attention-\w+$`)).OnElements("span", "strong") - policy.AllowAttrs("class").Matching(regexp.MustCompile(`^svg octicon-(\w|-)+$`)).OnElements("svg") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-icon attention-\w+ svg octicon-[\w-]+$`)).OnElements("svg") policy.AllowAttrs("viewBox", "width", "height", "aria-hidden").OnElements("svg") policy.AllowAttrs("fill-rule", "d").OnElements("path") @@ -105,18 +119,12 @@ func createDefaultPolicy() *bluemonday.Policy { // Allow icons policy.AllowAttrs("class").Matching(regexp.MustCompile(`^icon(\s+[\p{L}\p{N}_-]+)+$`)).OnElements("i") - // Allow unlabelled labels - policy.AllowNoAttrs().OnElements("label") - // Allow classes for emojis policy.AllowAttrs("class").Matching(regexp.MustCompile(`emoji`)).OnElements("img") // Allow icons, emojis, chroma syntax and keyword markup on span policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji)|(language-math display)|(language-math inline))$|^([a-z][a-z0-9]{0,2})$|^` + keywordClass + `$`)).OnElements("span") - // Allow 'style' attribute on text elements. - policy.AllowAttrs("style").OnElements("span", "p") - // Allow 'color' and 'background-color' properties for the style attribute on text elements. policy.AllowStyles("color", "background-color").OnElements("span", "p") @@ -144,7 +152,7 @@ func createDefaultPolicy() *bluemonday.Policy { generalSafeElements := []string{ "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "br", "b", "i", "strong", "em", "a", "pre", "code", "img", "tt", - "div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", + "div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", "label", "dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary", "details", "caption", "figure", "figcaption", "abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr", diff --git a/modules/optional/serialization.go b/modules/optional/serialization.go index 6688e78cd1..b120a0edf6 100644 --- a/modules/optional/serialization.go +++ b/modules/optional/serialization.go @@ -35,7 +35,7 @@ func (o *Option[T]) UnmarshalYAML(value *yaml.Node) error { return nil } -func (o Option[T]) MarshalYAML() (interface{}, error) { +func (o Option[T]) MarshalYAML() (any, error) { if !o.Has() { return nil, nil } diff --git a/modules/packages/nuget/metadata.go b/modules/packages/nuget/metadata.go index 3c478b1c02..1e98ddffde 100644 --- a/modules/packages/nuget/metadata.go +++ b/modules/packages/nuget/metadata.go @@ -48,16 +48,18 @@ const maxNuspecFileSize = 3 * 1024 * 1024 // Package represents a Nuget package type Package struct { - PackageType PackageType - ID string - Version string - Metadata *Metadata + PackageType PackageType + ID string + Version string + Metadata *Metadata + NuspecContent *bytes.Buffer } // Metadata represents the metadata of a Nuget package type Metadata struct { Description string `json:"description,omitempty"` ReleaseNotes string `json:"release_notes,omitempty"` + Readme string `json:"readme,omitempty"` Authors string `json:"authors,omitempty"` ProjectURL string `json:"project_url,omitempty"` RepositoryURL string `json:"repository_url,omitempty"` @@ -71,6 +73,7 @@ type Dependency struct { Version string `json:"version"` } +// https://learn.microsoft.com/en-us/nuget/reference/nuspec type nuspecPackage struct { Metadata struct { ID string `xml:"id"` @@ -80,6 +83,7 @@ type nuspecPackage struct { ProjectURL string `xml:"projectUrl"` Description string `xml:"description"` ReleaseNotes string `xml:"releaseNotes"` + Readme string `xml:"readme"` PackageTypes struct { PackageType []struct { Name string `xml:"name,attr"` @@ -89,6 +93,11 @@ type nuspecPackage struct { URL string `xml:"url,attr"` } `xml:"repository"` Dependencies struct { + Dependency []struct { + ID string `xml:"id,attr"` + Version string `xml:"version,attr"` + Exclude string `xml:"exclude,attr"` + } `xml:"dependency"` Group []struct { TargetFramework string `xml:"targetFramework,attr"` Dependency []struct { @@ -122,16 +131,17 @@ func ParsePackageMetaData(r io.ReaderAt, size int64) (*Package, error) { } defer f.Close() - return ParseNuspecMetaData(f) + return ParseNuspecMetaData(archive, f) } } return nil, ErrMissingNuspecFile } // ParseNuspecMetaData parses a Nuspec file to retrieve the metadata of a Nuget package -func ParseNuspecMetaData(r io.Reader) (*Package, error) { +func ParseNuspecMetaData(archive *zip.Reader, r io.Reader) (*Package, error) { + var nuspecBuf bytes.Buffer var p nuspecPackage - if err := xml.NewDecoder(r).Decode(&p); err != nil { + if err := xml.NewDecoder(io.TeeReader(r, &nuspecBuf)).Decode(&p); err != nil { return nil, err } @@ -166,6 +176,28 @@ func ParseNuspecMetaData(r io.Reader) (*Package, error) { Dependencies: make(map[string][]Dependency), } + if p.Metadata.Readme != "" { + f, err := archive.Open(p.Metadata.Readme) + if err == nil { + buf, _ := io.ReadAll(f) + m.Readme = string(buf) + _ = f.Close() + } + } + + if len(p.Metadata.Dependencies.Dependency) > 0 { + deps := make([]Dependency, 0, len(p.Metadata.Dependencies.Dependency)) + for _, dep := range p.Metadata.Dependencies.Dependency { + if dep.ID == "" || dep.Version == "" { + continue + } + deps = append(deps, Dependency{ + ID: dep.ID, + Version: dep.Version, + }) + } + m.Dependencies[""] = deps + } for _, group := range p.Metadata.Dependencies.Group { deps := make([]Dependency, 0, len(group.Dependency)) for _, dep := range group.Dependency { @@ -182,10 +214,11 @@ func ParseNuspecMetaData(r io.Reader) (*Package, error) { } } return &Package{ - PackageType: packageType, - ID: p.Metadata.ID, - Version: toNormalizedVersion(v), - Metadata: m, + PackageType: packageType, + ID: p.Metadata.ID, + Version: toNormalizedVersion(v), + Metadata: m, + NuspecContent: &nuspecBuf, }, nil } diff --git a/modules/packages/nuget/metadata_test.go b/modules/packages/nuget/metadata_test.go index bba2bff4a5..f466492f8a 100644 --- a/modules/packages/nuget/metadata_test.go +++ b/modules/packages/nuget/metadata_test.go @@ -6,7 +6,6 @@ package nuget import ( "archive/zip" "bytes" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -19,6 +18,7 @@ const ( projectURL = "https://gitea.io" description = "Package Description" releaseNotes = "Package Release Notes" + readme = "Readme" repositoryURL = "https://gitea.io/gitea/gitea" targetFramework = ".NETStandard2.1" dependencyID = "System.Text.Json" @@ -36,6 +36,7 @@ const nuspecContent = ` ` + description + ` ` + releaseNotes + ` + README.md @@ -60,17 +61,19 @@ const symbolsNuspecContent = ` ` func TestParsePackageMetaData(t *testing.T) { - createArchive := func(name, content string) []byte { + createArchive := func(files map[string]string) []byte { var buf bytes.Buffer archive := zip.NewWriter(&buf) - w, _ := archive.Create(name) - w.Write([]byte(content)) + for name, content := range files { + w, _ := archive.Create(name) + w.Write([]byte(content)) + } archive.Close() return buf.Bytes() } t.Run("MissingNuspecFile", func(t *testing.T) { - data := createArchive("dummy.txt", "") + data := createArchive(map[string]string{"dummy.txt": ""}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.Nil(t, np) @@ -78,7 +81,7 @@ func TestParsePackageMetaData(t *testing.T) { }) t.Run("MissingNuspecFileInRoot", func(t *testing.T) { - data := createArchive("sub/package.nuspec", "") + data := createArchive(map[string]string{"sub/package.nuspec": ""}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.Nil(t, np) @@ -86,7 +89,7 @@ func TestParsePackageMetaData(t *testing.T) { }) t.Run("InvalidNuspecFile", func(t *testing.T) { - data := createArchive("package.nuspec", "") + data := createArchive(map[string]string{"package.nuspec": ""}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.Nil(t, np) @@ -94,10 +97,10 @@ func TestParsePackageMetaData(t *testing.T) { }) t.Run("InvalidPackageId", func(t *testing.T) { - data := createArchive("package.nuspec", ` + data := createArchive(map[string]string{"package.nuspec": ` - `) + `}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.Nil(t, np) @@ -105,30 +108,34 @@ func TestParsePackageMetaData(t *testing.T) { }) t.Run("InvalidPackageVersion", func(t *testing.T) { - data := createArchive("package.nuspec", ` + data := createArchive(map[string]string{"package.nuspec": ` - `+id+` + ` + id + ` - `) + `}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.Nil(t, np) assert.ErrorIs(t, err, ErrNuspecInvalidVersion) }) - t.Run("Valid", func(t *testing.T) { - data := createArchive("package.nuspec", nuspecContent) + t.Run("MissingReadme", func(t *testing.T) { + data := createArchive(map[string]string{"package.nuspec": nuspecContent}) np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.NoError(t, err) assert.NotNil(t, np) + assert.Empty(t, np.Metadata.Readme) }) -} -func TestParseNuspecMetaData(t *testing.T) { t.Run("Dependency Package", func(t *testing.T) { - np, err := ParseNuspecMetaData(strings.NewReader(nuspecContent)) + data := createArchive(map[string]string{ + "package.nuspec": nuspecContent, + "README.md": readme, + }) + + np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.NoError(t, err) assert.NotNil(t, np) assert.Equal(t, DependencyPackage, np.PackageType) @@ -139,6 +146,7 @@ func TestParseNuspecMetaData(t *testing.T) { assert.Equal(t, projectURL, np.Metadata.ProjectURL) assert.Equal(t, description, np.Metadata.Description) assert.Equal(t, releaseNotes, np.Metadata.ReleaseNotes) + assert.Equal(t, readme, np.Metadata.Readme) assert.Equal(t, repositoryURL, np.Metadata.RepositoryURL) assert.Len(t, np.Metadata.Dependencies, 1) assert.Contains(t, np.Metadata.Dependencies, targetFramework) @@ -148,13 +156,15 @@ func TestParseNuspecMetaData(t *testing.T) { assert.Equal(t, dependencyVersion, deps[0].Version) t.Run("NormalizedVersion", func(t *testing.T) { - np, err := ParseNuspecMetaData(strings.NewReader(` - - - test - 1.04.5.2.5-rc.1+metadata - -`)) + data := createArchive(map[string]string{"package.nuspec": ` + + + test + 1.04.5.2.5-rc.1+metadata + + `}) + + np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.NoError(t, err) assert.NotNil(t, np) assert.Equal(t, "1.4.5.2-rc.1", np.Version) @@ -162,7 +172,9 @@ func TestParseNuspecMetaData(t *testing.T) { }) t.Run("Symbols Package", func(t *testing.T) { - np, err := ParseNuspecMetaData(strings.NewReader(symbolsNuspecContent)) + data := createArchive(map[string]string{"package.nuspec": symbolsNuspecContent}) + + np, err := ParsePackageMetaData(bytes.NewReader(data), int64(len(data))) assert.NoError(t, err) assert.NotNil(t, np) assert.Equal(t, SymbolsPackage, np.PackageType) diff --git a/modules/packages/rubygems/marshal.go b/modules/packages/rubygems/marshal.go index 8878dcf973..4e6a5fc5f8 100644 --- a/modules/packages/rubygems/marshal.go +++ b/modules/packages/rubygems/marshal.go @@ -147,35 +147,35 @@ func (e *MarshalEncoder) marshalIntInternal(i int64) error { return e.w.WriteByte(byte(i - 5)) } - var len int + var length int if 122 < i && i <= 0xff { - len = 1 + length = 1 } else if 0xff < i && i <= 0xffff { - len = 2 + length = 2 } else if 0xffff < i && i <= 0xffffff { - len = 3 + length = 3 } else if 0xffffff < i && i <= 0x3fffffff { - len = 4 + length = 4 } else if -0x100 <= i && i < -123 { - len = -1 + length = -1 } else if -0x10000 <= i && i < -0x100 { - len = -2 + length = -2 } else if -0x1000000 <= i && i < -0x100000 { - len = -3 + length = -3 } else if -0x40000000 <= i && i < -0x1000000 { - len = -4 + length = -4 } else { return ErrInvalidIntRange } - if err := e.w.WriteByte(byte(len)); err != nil { + if err := e.w.WriteByte(byte(length)); err != nil { return err } - if len < 0 { - len = -len + if length < 0 { + length = -length } - for c := 0; c < len; c++ { + for c := 0; c < length; c++ { if err := e.w.WriteByte(byte(i >> uint(8*c) & 0xff)); err != nil { return err } @@ -244,13 +244,13 @@ func (e *MarshalEncoder) marshalArray(arr reflect.Value) error { return err } - len := arr.Len() + length := arr.Len() - if err := e.marshalIntInternal(int64(len)); err != nil { + if err := e.marshalIntInternal(int64(length)); err != nil { return err } - for i := 0; i < len; i++ { + for i := 0; i < length; i++ { if err := e.marshal(arr.Index(i).Interface()); err != nil { return err } diff --git a/modules/private/hook.go b/modules/private/hook.go index cab8c81224..79c3d48229 100644 --- a/modules/private/hook.go +++ b/modules/private/hook.go @@ -11,6 +11,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" ) @@ -32,13 +33,13 @@ const ( ) // Bool checks for a key in the map and parses as a boolean -func (g GitPushOptions) Bool(key string, def bool) bool { +func (g GitPushOptions) Bool(key string) optional.Option[bool] { if val, ok := g[key]; ok { if b, err := strconv.ParseBool(val); err == nil { - return b + return optional.Some(b) } } - return def + return optional.None[bool]() } // HookOptions represents the options for the Hook calls @@ -87,13 +88,17 @@ type HookProcReceiveResult struct { // HookProcReceiveRefResult represents an individual result from ProcReceive type HookProcReceiveRefResult struct { - OldOID string - NewOID string - Ref string - OriginalRef git.RefName - IsForcePush bool - IsNotMatched bool - Err string + OldOID string + NewOID string + Ref string + OriginalRef git.RefName + IsForcePush bool + IsNotMatched bool + Err string + IsCreatePR bool + URL string + ShouldShowMessage bool + HeadBranch string } // HookPreReceive check whether the provided commits are allowed diff --git a/modules/process/manager_stacktraces.go b/modules/process/manager_stacktraces.go index 49bd5071f6..e260893113 100644 --- a/modules/process/manager_stacktraces.go +++ b/modules/process/manager_stacktraces.go @@ -339,7 +339,6 @@ func (pm *Manager) ProcessStacktraces(flat, noSystem bool) ([]*Process, int, int } sort.Slice(processes, after(processes)) if !flat { - var sortChildren func(process *Process) sortChildren = func(process *Process) { diff --git a/modules/queue/backoff.go b/modules/queue/backoff.go index cda7233567..02fc88574a 100644 --- a/modules/queue/backoff.go +++ b/modules/queue/backoff.go @@ -8,7 +8,7 @@ import ( "time" ) -const ( +var ( backoffBegin = 50 * time.Millisecond backoffUpper = 2 * time.Second ) @@ -18,6 +18,14 @@ type ( backoffFuncErr func() (retry bool, err error) ) +func mockBackoffDuration(d time.Duration) func() { + oldBegin, oldUpper := backoffBegin, backoffUpper + backoffBegin, backoffUpper = d, d + return func() { + backoffBegin, backoffUpper = oldBegin, oldUpper + } +} + func backoffRetErr[T any](ctx context.Context, begin, upper time.Duration, end <-chan time.Time, fn backoffFuncRetErr[T]) (ret T, err error) { d := begin for { diff --git a/modules/queue/workergroup.go b/modules/queue/workergroup.go index e3801ef2b2..153123f883 100644 --- a/modules/queue/workergroup.go +++ b/modules/queue/workergroup.go @@ -63,6 +63,8 @@ func (q *WorkerPoolQueue[T]) doDispatchBatchToWorker(wg *workerGroup[T], flushCh // TODO: the logic could be improved in the future, to avoid a data-race between "doStartNewWorker" and "workerNum" // The root problem is that if we skip "doStartNewWorker" here, the "workerNum" might be decreased by other workers later // So ideally, it should check whether there are enough workers by some approaches, and start new workers if necessary. + // This data-race is not serious, as long as a new worker will be started soon to make sure there are enough workers, + // so no need to hugely refactor at the moment. q.workerNumMu.Lock() noWorker := q.workerNum == 0 if full || noWorker { @@ -136,6 +138,14 @@ func (q *WorkerPoolQueue[T]) basePushForShutdown(items ...T) bool { return true } +func resetIdleTicker(t *time.Ticker, dur time.Duration) { + t.Reset(dur) + select { + case <-t.C: + default: + } +} + // doStartNewWorker starts a new worker for the queue, the worker reads from worker's channel and handles the items. func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { wp.wg.Add(1) @@ -146,8 +156,6 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { log.Debug("Queue %q starts new worker", q.GetName()) defer log.Debug("Queue %q stops idle worker", q.GetName()) - atomic.AddInt32(&q.workerStartedCounter, 1) // Only increase counter, used for debugging - t := time.NewTicker(workerIdleDuration) defer t.Stop() @@ -169,11 +177,7 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) { } q.doWorkerHandle(batch) // reset the idle ticker, and drain the tick after reset in case a tick is already triggered - t.Reset(workerIdleDuration) - select { - case <-t.C: - default: - } + resetIdleTicker(t, workerIdleDuration) // key code for TestWorkerPoolQueueWorkerIdleReset case <-t.C: q.workerNumMu.Lock() keepWorking = q.workerNum <= 1 // keep the last worker running diff --git a/modules/queue/workerqueue.go b/modules/queue/workerqueue.go index 4160622d81..b28fd88027 100644 --- a/modules/queue/workerqueue.go +++ b/modules/queue/workerqueue.go @@ -40,8 +40,6 @@ type WorkerPoolQueue[T any] struct { workerMaxNum int workerActiveNum int workerNumMu sync.Mutex - - workerStartedCounter int32 } type flushType chan struct{} diff --git a/modules/queue/workerqueue_test.go b/modules/queue/workerqueue_test.go index e09669c542..d66253ff66 100644 --- a/modules/queue/workerqueue_test.go +++ b/modules/queue/workerqueue_test.go @@ -5,8 +5,10 @@ package queue import ( "context" + "slices" "strconv" "sync" + "sync/atomic" "testing" "time" @@ -250,22 +252,34 @@ func TestWorkerPoolQueueShutdown(t *testing.T) { func TestWorkerPoolQueueWorkerIdleReset(t *testing.T) { defer test.MockVariableValue(&workerIdleDuration, 10*time.Millisecond)() + defer mockBackoffDuration(5 * time.Millisecond)() + var q *WorkerPoolQueue[int] + var handledCount atomic.Int32 + var hasOnlyOneWorkerRunning atomic.Bool handler := func(items ...int) (unhandled []int) { - time.Sleep(50 * time.Millisecond) + handledCount.Add(int32(len(items))) + // make each work have different duration, and check the active worker number periodically + var activeNums []int + for i := 0; i < 5-items[0]%2; i++ { + time.Sleep(workerIdleDuration * 2) + activeNums = append(activeNums, q.GetWorkerActiveNumber()) + } + // When the queue never becomes empty, the existing workers should keep working + // It is not 100% true at the moment because the data-race in workergroup.go is not resolved, see that TODO */ + // If the "active worker numbers" is like [2 2 ... 1 1], it means that an existing worker exited and the no new worker is started. + if slices.Equal([]int{1, 1}, activeNums[len(activeNums)-2:]) { + hasOnlyOneWorkerRunning.Store(true) + } return nil } - - q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false) + q, _ = newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false) stop := runWorkerPoolQueue(q) - for i := 0; i < 20; i++ { + for i := 0; i < 100; i++ { assert.NoError(t, q.Push(i)) } - time.Sleep(500 * time.Millisecond) - assert.EqualValues(t, 2, q.GetWorkerNumber()) - assert.EqualValues(t, 2, q.GetWorkerActiveNumber()) - // when the queue never becomes empty, the existing workers should keep working - assert.EqualValues(t, 2, q.workerStartedCounter) + assert.Greater(t, int(handledCount.Load()), 4) // make sure there are enough items handled during the test + assert.False(t, hasOnlyOneWorkerRunning.Load(), "a slow handler should not block other workers from starting") stop() } diff --git a/modules/repository/temp.go b/modules/repository/temp.go index 53646718e0..04faa9db3d 100644 --- a/modules/repository/temp.go +++ b/modules/repository/temp.go @@ -32,7 +32,6 @@ func CreateTemporaryPath(prefix string) (string, error) { if err != nil { log.Error("Unable to create temporary directory: %s-*.git (%v)", prefix, err) return "", fmt.Errorf("Failed to create dir %s-*.git: %w", prefix, err) - } return basePath, nil } diff --git a/modules/session/mock.go b/modules/session/mock.go new file mode 100644 index 0000000000..95231a3655 --- /dev/null +++ b/modules/session/mock.go @@ -0,0 +1,26 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package session + +import ( + "net/http" + + "gitea.com/go-chi/session" +) + +type MockStore struct { + *session.MemStore +} + +func (m *MockStore) Destroy(writer http.ResponseWriter, request *http.Request) error { + return nil +} + +type mockStoreContextKeyStruct struct{} + +var MockStoreContextKey = mockStoreContextKeyStruct{} + +func NewMockStore(sid string) *MockStore { + return &MockStore{session.NewMemStore(sid)} +} diff --git a/modules/session/store.go b/modules/session/store.go index 4fa4d2848f..09d1ef44dd 100644 --- a/modules/session/store.go +++ b/modules/session/store.go @@ -6,6 +6,8 @@ package session import ( "net/http" + "code.gitea.io/gitea/modules/setting" + "gitea.com/go-chi/session" ) @@ -14,10 +16,33 @@ type Store interface { Get(any) any Set(any, any) error Delete(any) error + ID() string + Release() error + Flush() error + Destroy(http.ResponseWriter, *http.Request) error } // RegenerateSession regenerates the underlying session and returns the new store func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, error) { - s, err := session.RegenerateSession(resp, req) - return s, err + for _, f := range BeforeRegenerateSession { + f(resp, req) + } + if setting.IsInTesting { + if store, ok := req.Context().Value(MockStoreContextKey).(*MockStore); ok { + return store, nil + } + } + return session.RegenerateSession(resp, req) } + +func GetContextSession(req *http.Request) Store { + if setting.IsInTesting { + if store, ok := req.Context().Value(MockStoreContextKey).(*MockStore); ok { + return store + } + } + return session.GetSession(req) +} + +// BeforeRegenerateSession is a list of functions that are called before a session is regenerated. +var BeforeRegenerateSession []func(http.ResponseWriter, *http.Request) diff --git a/modules/setting/admin.go b/modules/setting/admin.go index be214a58ce..8aebc76154 100644 --- a/modules/setting/admin.go +++ b/modules/setting/admin.go @@ -3,13 +3,16 @@ package setting -import "code.gitea.io/gitea/modules/container" +import ( + "code.gitea.io/gitea/modules/container" +) // Admin settings var Admin struct { - DisableRegularOrgCreation bool - DefaultEmailNotification string - UserDisabledFeatures container.Set[string] + DisableRegularOrgCreation bool + DefaultEmailNotification string + UserDisabledFeatures container.Set[string] + ExternalUserDisableFeatures container.Set[string] } func loadAdminFrom(rootCfg ConfigProvider) { @@ -17,6 +20,7 @@ func loadAdminFrom(rootCfg ConfigProvider) { Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false) Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled") Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...) + Admin.ExternalUserDisableFeatures = container.SetOf(sec.Key("EXTERNAL_USER_DISABLE_FEATURES").Strings(",")...) } const ( diff --git a/modules/setting/attachment.go b/modules/setting/attachment.go index 934d4d7f46..0fdabb5032 100644 --- a/modules/setting/attachment.go +++ b/modules/setting/attachment.go @@ -12,7 +12,7 @@ var Attachment = struct { Enabled bool }{ Storage: &Storage{}, - AllowedTypes: ".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip", + AllowedTypes: ".cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip", MaxSize: 2048, MaxFiles: 5, Enabled: true, @@ -25,7 +25,7 @@ func loadAttachmentFrom(rootCfg ConfigProvider) (err error) { return err } - Attachment.AllowedTypes = sec.Key("ALLOWED_TYPES").MustString(".csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip") + Attachment.AllowedTypes = sec.Key("ALLOWED_TYPES").MustString(".cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip") Attachment.MaxSize = sec.Key("MAX_SIZE").MustInt64(2048) Attachment.MaxFiles = sec.Key("MAX_FILES").MustInt(5) Attachment.Enabled = sec.Key("ENABLED").MustBool(true) diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go index 3fa3f3b50b..3138f8a63e 100644 --- a/modules/setting/config_provider.go +++ b/modules/setting/config_provider.go @@ -315,21 +315,25 @@ func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting any) { } } -// DeprecatedWarnings contains the warning message for various deprecations, including: setting option, file/folder, etc -var DeprecatedWarnings []string +// StartupProblems contains the messages for various startup problems, including: setting option, file/folder, etc +var StartupProblems []string + +func LogStartupProblem(skip int, level log.Level, format string, args ...any) { + msg := fmt.Sprintf(format, args...) + log.Log(skip+1, level, "%s", msg) + StartupProblems = append(StartupProblems, msg) +} func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) { if rootCfg.Section(oldSection).HasKey(oldKey) { - msg := fmt.Sprintf("Deprecated config option `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) - log.Error("%v", msg) - DeprecatedWarnings = append(DeprecatedWarnings, msg) + LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) } } // deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini func deprecatedSettingDB(rootCfg ConfigProvider, oldSection, oldKey string) { if rootCfg.Section(oldSection).HasKey(oldKey) { - log.Error("Deprecated `[%s]` `%s` present which has been copied to database table sys_setting", oldSection, oldKey) + LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey) } } diff --git a/modules/setting/indexer.go b/modules/setting/indexer.go index 15f6150242..6877d70e3c 100644 --- a/modules/setting/indexer.go +++ b/modules/setting/indexer.go @@ -58,7 +58,7 @@ func loadIndexerFrom(rootCfg ConfigProvider) { if !filepath.IsAbs(Indexer.IssuePath) { Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath)) } - fatalDuplicatedPath("issue_indexer", Indexer.IssuePath) + checkOverlappedPath("[indexer].ISSUE_INDEXER_PATH", Indexer.IssuePath) } else { Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr) if Indexer.IssueType == "meilisearch" { diff --git a/modules/setting/log.go b/modules/setting/log.go index e404074b72..50c5779994 100644 --- a/modules/setting/log.go +++ b/modules/setting/log.go @@ -185,8 +185,13 @@ func InitLoggersForTest() { initAllLoggers() } +var initLoggerDisabled bool + // initAllLoggers creates all the log services func initAllLoggers() { + if initLoggerDisabled { + return + } initManagedLoggers(log.GetManager(), CfgProvider) golog.SetFlags(0) @@ -194,6 +199,10 @@ func initAllLoggers() { golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info)) } +func DisableLoggerInit() { + initLoggerDisabled = true +} + func initManagedLoggers(manager *log.LoggerManager, cfg ConfigProvider) { loadLogGlobalFrom(cfg) prepareLoggerConfig(cfg) diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go index 4d3bfd3eb6..e59f54420b 100644 --- a/modules/setting/oauth2.go +++ b/modules/setting/oauth2.go @@ -16,17 +16,15 @@ import ( type OAuth2UsernameType string const ( - // OAuth2UsernameUserid oauth2 userid field will be used as gitea name - OAuth2UsernameUserid OAuth2UsernameType = "userid" - // OAuth2UsernameNickname oauth2 nickname field will be used as gitea name - OAuth2UsernameNickname OAuth2UsernameType = "nickname" - // OAuth2UsernameEmail username of oauth2 email field will be used as gitea name - OAuth2UsernameEmail OAuth2UsernameType = "email" + OAuth2UsernameUserid OAuth2UsernameType = "userid" // use user id (sub) field as gitea's username + OAuth2UsernameNickname OAuth2UsernameType = "nickname" // use nickname field + OAuth2UsernameEmail OAuth2UsernameType = "email" // use email field + OAuth2UsernamePreferredUsername OAuth2UsernameType = "preferred_username" // use preferred_username field ) func (username OAuth2UsernameType) isValid() bool { switch username { - case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail: + case OAuth2UsernameUserid, OAuth2UsernameNickname, OAuth2UsernameEmail, OAuth2UsernamePreferredUsername: return true } return false @@ -69,8 +67,8 @@ func loadOAuth2ClientFrom(rootCfg ConfigProvider) { OAuth2Client.EnableAutoRegistration = sec.Key("ENABLE_AUTO_REGISTRATION").MustBool() OAuth2Client.Username = OAuth2UsernameType(sec.Key("USERNAME").MustString(string(OAuth2UsernameNickname))) if !OAuth2Client.Username.isValid() { - log.Warn("Username setting is not valid: '%s', will fallback to '%s'", OAuth2Client.Username, OAuth2UsernameNickname) OAuth2Client.Username = OAuth2UsernameNickname + log.Warn("[oauth2_client].USERNAME setting is invalid, falls back to %q", OAuth2Client.Username) } OAuth2Client.UpdateAvatar = sec.Key("UPDATE_AVATAR").MustBool() OAuth2Client.AccountLinking = OAuth2AccountLinkingType(sec.Key("ACCOUNT_LINKING").MustString(string(OAuth2AccountLinkingLogin))) @@ -118,6 +116,10 @@ func loadOAuth2From(rootCfg ConfigProvider) { return } + if sec.HasKey("DEFAULT_APPLICATIONS") && sec.Key("DEFAULT_APPLICATIONS").String() == "" { + OAuth2.DefaultApplications = nil + } + // Handle the rename of ENABLE to ENABLED deprecatedSetting(rootCfg, "oauth2", "ENABLE", "oauth2", "ENABLED", "v1.23.0") if sec.HasKey("ENABLE") && !sec.HasKey("ENABLED") { @@ -168,7 +170,7 @@ func GetGeneralTokenSigningSecret() []byte { } if generalSigningSecret.CompareAndSwap(old, &jwtSecret) { // FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...) - log.Warn("OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes") + LogStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes") return jwtSecret } return *generalSigningSecret.Load() diff --git a/modules/setting/oauth2_test.go b/modules/setting/oauth2_test.go index d822198619..4403f35892 100644 --- a/modules/setting/oauth2_test.go +++ b/modules/setting/oauth2_test.go @@ -32,3 +32,21 @@ JWT_SECRET = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB assert.Len(t, actual, 32) assert.EqualValues(t, expected, actual) } + +func TestOauth2DefaultApplications(t *testing.T) { + cfg, _ := NewConfigProviderFromData(``) + loadOAuth2From(cfg) + assert.Equal(t, []string{"git-credential-oauth", "git-credential-manager", "tea"}, OAuth2.DefaultApplications) + + cfg, _ = NewConfigProviderFromData(`[oauth2] +DEFAULT_APPLICATIONS = tea +`) + loadOAuth2From(cfg) + assert.Equal(t, []string{"tea"}, OAuth2.DefaultApplications) + + cfg, _ = NewConfigProviderFromData(`[oauth2] +DEFAULT_APPLICATIONS = +`) + loadOAuth2From(cfg) + assert.Nil(t, nil, OAuth2.DefaultApplications) +} diff --git a/modules/setting/other.go b/modules/setting/other.go index 706cb1e3d9..4ba494765b 100644 --- a/modules/setting/other.go +++ b/modules/setting/other.go @@ -8,6 +8,7 @@ import "code.gitea.io/gitea/modules/log" type OtherConfig struct { ShowFooterVersion bool ShowFooterTemplateLoadTime bool + ShowFooterPoweredBy bool EnableFeed bool EnableSitemap bool } @@ -15,6 +16,7 @@ type OtherConfig struct { var Other = OtherConfig{ ShowFooterVersion: true, ShowFooterTemplateLoadTime: true, + ShowFooterPoweredBy: true, EnableSitemap: true, EnableFeed: true, } diff --git a/modules/setting/path.go b/modules/setting/path.go index b2cca0acbf..0fdc305aa1 100644 --- a/modules/setting/path.go +++ b/modules/setting/path.go @@ -66,12 +66,8 @@ func init() { AppWorkPath = filepath.Dir(AppPath) } - fatalDuplicatedPath("app_work_path", AppWorkPath) - appWorkPathBuiltin = AppWorkPath customPathBuiltin = CustomPath - - fatalDuplicatedPath("custom_path", CustomPath) customConfBuiltin = CustomConf } diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 7990021aaa..8656ebc7ec 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -286,7 +286,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) { RepoRootPath = filepath.Clean(RepoRootPath) } - fatalDuplicatedPath("repository.ROOT", RepoRootPath) + checkOverlappedPath("[repository].ROOT", RepoRootPath) defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder)) for _, charset := range Repository.DetectedCharsetsOrder { diff --git a/modules/setting/security.go b/modules/setting/security.go index 380360a696..3d7b1f9ce7 100644 --- a/modules/setting/security.go +++ b/modules/setting/security.go @@ -103,7 +103,7 @@ func generateSaveInternalToken(rootCfg ConfigProvider) { func loadSecurityFrom(rootCfg ConfigProvider) { sec := rootCfg.Section("security") InstallLock = HasInstallLock(rootCfg) - LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7) + LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(31) SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY") if SecretKey == "" { // FIXME: https://github.com/go-gitea/gitea/issues/16832 diff --git a/modules/setting/server.go b/modules/setting/server.go index 0dea4e1ac7..7d6ece2727 100644 --- a/modules/setting/server.go +++ b/modules/setting/server.go @@ -324,7 +324,6 @@ func loadServerFrom(rootCfg ConfigProvider) { if !filepath.IsAbs(AppDataPath) { AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath)) } - fatalDuplicatedPath("app_data_path", AppDataPath) EnableGzip = sec.Key("ENABLE_GZIP").MustBool() EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false) @@ -332,7 +331,7 @@ func loadServerFrom(rootCfg ConfigProvider) { if !filepath.IsAbs(PprofDataPath) { PprofDataPath = filepath.Join(AppWorkPath, PprofDataPath) } - fatalDuplicatedPath("pprof_data_path", PprofDataPath) + checkOverlappedPath("[server].PPROF_DATA_PATH", PprofDataPath) landingPage := sec.Key("LANDING_PAGE").MustString("home") switch landingPage { diff --git a/modules/setting/session.go b/modules/setting/session.go index 70497e5eaa..afe63bfdb7 100644 --- a/modules/setting/session.go +++ b/modules/setting/session.go @@ -46,7 +46,7 @@ func loadSessionFrom(rootCfg ConfigProvider) { SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(filepath.Join(AppDataPath, "sessions")), "\" ") if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) { SessionConfig.ProviderConfig = filepath.Join(AppWorkPath, SessionConfig.ProviderConfig) - fatalDuplicatedPath("session", SessionConfig.ProviderConfig) + checkOverlappedPath("[session].PROVIDER_CONFIG", SessionConfig.ProviderConfig) } SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea") SessionConfig.CookiePath = AppSubURL diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 6e7ce7e67f..f056fbfc6c 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/user" + "code.gitea.io/gitea/modules/util" ) // settings @@ -158,9 +159,11 @@ func loadCommonSettingsFrom(cfg ConfigProvider) error { func loadRunModeFrom(rootCfg ConfigProvider) { rootSec := rootCfg.Section("") RunUser = rootSec.Key("RUN_USER").MustString(user.CurrentUsername()) + // The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches. // Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly. unsafeAllowRunAsRoot := ConfigSectionKeyBool(rootSec, "I_AM_BEING_UNSAFE_RUNNING_AS_ROOT") + unsafeAllowRunAsRoot = unsafeAllowRunAsRoot || util.OptionalBoolParse(os.Getenv("GITEA_I_AM_BEING_UNSAFE_RUNNING_AS_ROOT")).Value() RunMode = os.Getenv("GITEA_RUN_MODE") if RunMode == "" { RunMode = rootSec.Key("RUN_MODE").MustString("prod") @@ -227,11 +230,12 @@ func LoadSettingsForInstall() { loadMailerFrom(CfgProvider) } -var uniquePaths = make(map[string]string) +var configuredPaths = make(map[string]string) -func fatalDuplicatedPath(name, p string) { - if targetName, ok := uniquePaths[p]; ok && targetName != name { - log.Fatal("storage path %q is being used by %q and %q and all storage paths must be unique to prevent data loss.", p, targetName, name) +func checkOverlappedPath(name, path string) { + // TODO: some paths shouldn't overlap (storage.xxx.path), while some could (data path is the base path for storage path) + if targetName, ok := configuredPaths[path]; ok && targetName != name { + LogStartupProblem(1, log.ERROR, "Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name) } - uniquePaths[p] = name + configuredPaths[path] = name } diff --git a/modules/setting/storage.go b/modules/setting/storage.go index 23b08df101..aeb61ac513 100644 --- a/modules/setting/storage.go +++ b/modules/setting/storage.go @@ -240,7 +240,7 @@ func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType, } } - fatalDuplicatedPath("storage."+name, storage.Path) + checkOverlappedPath("[storage."+name+"].PATH", storage.Path) return &storage, nil } diff --git a/modules/setting/time.go b/modules/setting/time.go index 6d2aa80f5b..39acba12ef 100644 --- a/modules/setting/time.go +++ b/modules/setting/time.go @@ -19,9 +19,8 @@ func loadTimeFrom(rootCfg ConfigProvider) { DefaultUILocation, err = time.LoadLocation(zone) if err != nil { log.Fatal("Load time zone failed: %v", err) - } else { - log.Info("Default UI Location is %v", zone) } + log.Info("Default UI Location is %v", zone) } if DefaultUILocation == nil { DefaultUILocation = time.Local diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 2f9eef93c3..93855bca07 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -82,7 +82,6 @@ var UI = struct { ReactionMaxUserNum: 10, MaxDisplayFileSize: 8388608, DefaultTheme: `gitea-auto`, - Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`}, Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`}, CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"}, diff --git a/modules/structs/repo_compare.go b/modules/structs/repo_compare.go new file mode 100644 index 0000000000..8a12498705 --- /dev/null +++ b/modules/structs/repo_compare.go @@ -0,0 +1,10 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +// Compare represents a comparison between two commits. +type Compare struct { + TotalCommits int `json:"total_commits"` // Total number of commits in the comparison. + Commits []*Commit `json:"commits"` // List of commits in the comparison. +} diff --git a/modules/structs/user.go b/modules/structs/user.go index c43558be5d..ca6ab79944 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -20,6 +20,8 @@ type User struct { // the user's authentication sign-in name. // default: empty LoginName string `json:"login_name"` + // The ID of the user's Authentication Source + SourceID int64 `json:"source_id"` // the user's full name FullName string `json:"full_name"` // swagger:strfmt email @@ -132,10 +134,3 @@ type UserBadgeOption struct { // example: ["badge1","badge2"] BadgeSlugs []string `json:"badge_slugs" binding:"Required"` } - -// BadgeList -// swagger:response BadgeList -type BadgeList struct { - // in:body - Body []Badge `json:"body"` -} diff --git a/modules/structs/variable.go b/modules/structs/variable.go new file mode 100644 index 0000000000..cc846cf0ec --- /dev/null +++ b/modules/structs/variable.go @@ -0,0 +1,37 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +// CreateVariableOption the option when creating variable +// swagger:model +type CreateVariableOption struct { + // Value of the variable to create + // + // required: true + Value string `json:"value" binding:"Required"` +} + +// UpdateVariableOption the option when updating variable +// swagger:model +type UpdateVariableOption struct { + // New name for the variable. If the field is empty, the variable name won't be updated. + Name string `json:"name"` + // Value of the variable to update + // + // required: true + Value string `json:"value" binding:"Required"` +} + +// ActionVariable return value of the query API +// swagger:model +type ActionVariable struct { + // the owner to which the variable belongs + OwnerID int64 `json:"owner_id"` + // the repository to which the variable belongs + RepoID int64 `json:"repo_id"` + // the name of the variable + Name string `json:"name"` + // the value of the variable + Data string `json:"data"` +} diff --git a/modules/svg/svg.go b/modules/svg/svg.go index 016e1dc08b..8132978cac 100644 --- a/modules/svg/svg.go +++ b/modules/svg/svg.go @@ -41,6 +41,21 @@ func Init() error { return nil } +func MockIcon(icon string) func() { + if svgIcons == nil { + svgIcons = make(map[string]string) + } + orig, exist := svgIcons[icon] + svgIcons[icon] = fmt.Sprintf(``, icon, defaultSize, defaultSize) + return func() { + if exist { + svgIcons[icon] = orig + } else { + delete(svgIcons, icon) + } + } +} + // RenderHTML renders icons - arguments icon name (string), size (int), class (string) func RenderHTML(icon string, others ...any) template.HTML { size, class := gitea_html.ParseSizeAndClass(defaultSize, "", others...) @@ -55,5 +70,6 @@ func RenderHTML(icon string, others ...any) template.HTML { } return template.HTML(svgStr) } - return "" + // during test (or something wrong happens), there is no SVG loaded, so use a dummy span to tell that the icon is missing + return template.HTML(fmt.Sprintf("%s(%d/%s)", template.HTMLEscapeString(icon), size, template.HTMLEscapeString(class))) } diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 0997239a55..94464fe628 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" + "code.gitea.io/gitea/services/webtheme" ) // NewFuncMap returns functions for injecting to templates @@ -34,11 +35,12 @@ func NewFuncMap() template.FuncMap { // ----------------------------------------------------------------- // html/template related functions "dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names. + "Iif": Iif, "Eval": Eval, "SafeHTML": SafeHTML, "HTMLFormat": HTMLFormat, "HTMLEscape": HTMLEscape, - "QueryEscape": url.QueryEscape, + "QueryEscape": QueryEscape, "JSEscape": JSEscapeSafe, "SanitizeHTML": SanitizeHTML, "URLJoin": util.URLJoin, @@ -53,13 +55,13 @@ func NewFuncMap() template.FuncMap { "JsonUtils": NewJsonUtils, // ----------------------------------------------------------------- - // svg / avatar / icon + // svg / avatar / icon / color "svg": svg.RenderHTML, "EntryIcon": base.EntryIcon, "MigrationIcon": MigrationIcon, "ActionIcon": ActionIcon, - - "SortArrow": SortArrow, + "SortArrow": SortArrow, + "ContrastColor": util.ContrastColor, // ----------------------------------------------------------------- // time / number / format @@ -106,6 +108,9 @@ func NewFuncMap() template.FuncMap { "ShowFooterTemplateLoadTime": func() bool { return setting.Other.ShowFooterTemplateLoadTime }, + "ShowFooterPoweredBy": func() bool { + return setting.Other.ShowFooterPoweredBy + }, "AllowedReactions": func() []string { return setting.UI.Reactions }, @@ -133,12 +138,7 @@ func NewFuncMap() template.FuncMap { "DisableImportLocal": func() bool { return !setting.ImportLocalPaths }, - "ThemeName": func(user *user_model.User) string { - if user == nil || user.Theme == "" { - return setting.UI.DefaultTheme - } - return user.Theme - }, + "UserThemeName": UserThemeName, "NotificationSettings": func() map[string]any { return map[string]any{ "MinTimeout": int(setting.UI.Notification.MinTimeout / time.Millisecond), @@ -226,11 +226,26 @@ func JSEscapeSafe(s string) template.HTML { return template.HTML(template.JSEscapeString(s)) } +func QueryEscape(s string) template.URL { + return template.URL(url.QueryEscape(s)) +} + // DotEscape wraps a dots in names with ZWJ [U+200D] in order to prevent autolinkers from detecting these as urls func DotEscape(raw string) string { return strings.ReplaceAll(raw, ".", "\u200d.\u200d") } +// Iif is an "inline-if", similar util.Iif[T] but templates need the non-generic version, +// and it could be simply used as "{{Iif expr trueVal}}" (omit the falseVal). +func Iif(condition bool, vals ...any) any { + if condition { + return vals[0] + } else if len(vals) > 1 { + return vals[1] + } + return nil +} + // Eval the expression and return the result, see the comment of eval.Expr for details. // To use this helper function in templates, pass each token as a separate parameter. // @@ -242,3 +257,13 @@ func Eval(tokens ...any) (any, error) { n, err := eval.Expr(tokens...) return n.Value, err } + +func UserThemeName(user *user_model.User) string { + if user == nil || user.Theme == "" { + return setting.UI.DefaultTheme + } + if webtheme.IsThemeAvailable(user.Theme) { + return user.Theme + } + return setting.UI.DefaultTheme +} diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 40941285aa..e7e805ed30 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -138,10 +138,9 @@ func wrapTmplErrMsg(msg string) { if setting.IsProd { // in prod mode, Gitea must have correct templates to run log.Fatal("Gitea can't run with template errors: %s", msg) - } else { - // in dev mode, do not need to really exit, because the template errors could be fixed by developer soon and the templates get reloaded - log.Error("There are template errors but Gitea continues to run in dev mode: %s", msg) } + // in dev mode, do not need to really exit, because the template errors could be fixed by developer soon and the templates get reloaded + log.Error("There are template errors but Gitea continues to run in dev mode: %s", msg) } type templateErrorPrettier struct { diff --git a/modules/templates/mailer.go b/modules/templates/mailer.go index f1832cba0e..7c97e1ea89 100644 --- a/modules/templates/mailer.go +++ b/modules/templates/mailer.go @@ -84,9 +84,8 @@ func Mailer(ctx context.Context) (*texttmpl.Template, *template.Template) { if err = buildSubjectBodyTemplate(subjectTemplates, bodyTemplates, tmplName, content); err != nil { if firstRun { log.Fatal("Failed to parse mail template, err: %v", err) - } else { - log.Error("Failed to parse mail template, err: %v", err) } + log.Error("Failed to parse mail template, err: %v", err) } } } diff --git a/modules/templates/util_misc.go b/modules/templates/util_misc.go index 6c1b4ab240..774385483b 100644 --- a/modules/templates/util_misc.go +++ b/modules/templates/util_misc.go @@ -142,35 +142,39 @@ type remoteAddress struct { Password string } -func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress { - a := remoteAddress{} - - remoteURL := m.OriginalURL - if ignoreOriginalURL || remoteURL == "" { - var err error - remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName) - if err != nil { - log.Error("GetRemoteURL %v", err) - return a - } +func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string) remoteAddress { + ret := remoteAddress{} + remoteURL, err := git.GetRemoteAddress(ctx, m.RepoPath(), remoteName) + if err != nil { + log.Error("GetRemoteURL %v", err) + return ret } u, err := giturl.Parse(remoteURL) if err != nil { log.Error("giturl.Parse %v", err) - return a + return ret } if u.Scheme != "ssh" && u.Scheme != "file" { if u.User != nil { - a.Username = u.User.Username() - a.Password, _ = u.User.Password() + ret.Username = u.User.Username() + ret.Password, _ = u.User.Password() } - u.User = nil } - a.Address = u.String() - return a + // The URL stored in the git repo could contain authentication, + // erase it, or it will be shown in the UI. + u.User = nil + ret.Address = u.String() + // Why not use m.OriginalURL to set ret.Address? + // It should be OK to use it, since m.OriginalURL should be the same as the authentication-erased URL from the Git repository. + // However, the old code has already stored authentication in m.OriginalURL when updating mirror settings. + // That means we need to use "giturl.Parse" for m.OriginalURL again to ensure authentication is erased. + // Instead of doing this, why not directly use the authentication-erased URL from the Git repository? + // It should be the same as long as there are no bugs. + + return ret } func FilenameIsImage(filename string) bool { diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go index cdff31698c..659422aee7 100644 --- a/modules/templates/util_render.go +++ b/modules/templates/util_render.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/util" ) @@ -40,7 +41,7 @@ func RenderCommitMessage(ctx context.Context, msg string, metas map[string]strin if len(msgLines) == 0 { return template.HTML("") } - return template.HTML(msgLines[0]) + return RenderCodeBlock(template.HTML(msgLines[0])) } // RenderCommitMessageLinkSubject renders commit message as a XSS-safe link to @@ -67,7 +68,7 @@ func RenderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string, log.Error("RenderCommitMessageSubject: %v", err) return template.HTML("") } - return template.HTML(renderedMessage) + return RenderCodeBlock(template.HTML(renderedMessage)) } // RenderCommitBody extracts the body of a commit message without its title. @@ -118,22 +119,25 @@ func RenderIssueTitle(ctx context.Context, text string, metas map[string]string) } // RenderLabel renders a label -func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML { - labelScope := label.ExclusiveScope() - - textColor := "#111" - r, g, b := util.HexToRBGColor(label.Color) - // Determine if label text should be light or dark to be readable on background color - if util.UseLightTextOnBackground(r, g, b) { - textColor = "#eee" - } +// locale is needed due to an import cycle with our context providing the `Tr` function +func RenderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML { + var ( + archivedCSSClass string + textColor = util.ContrastColor(label.Color) + labelScope = label.ExclusiveScope() + ) description := emoji.ReplaceAliases(template.HTMLEscapeString(label.Description)) + if label.IsArchived() { + archivedCSSClass = "archived-label" + description = fmt.Sprintf("(%s) %s", locale.TrString("archived"), description) + } + if labelScope == "" { // Regular label - s := fmt.Sprintf("
      %s
      ", - textColor, label.Color, description, RenderEmoji(ctx, label.Name)) + s := fmt.Sprintf("
      %s
      ", + archivedCSSClass, textColor, label.Color, description, RenderEmoji(ctx, label.Name)) return template.HTML(s) } @@ -143,7 +147,7 @@ func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML { // Make scope and item background colors slightly darker and lighter respectively. // More contrast needed with higher luminance, empirically tweaked. - luminance := util.GetLuminance(r, g, b) + luminance := util.GetRelativeLuminance(label.Color) contrast := 0.01 + luminance*0.03 // Ensure we add the same amount of contrast also near 0 and 1. darken := contrast + math.Max(luminance+contrast-1.0, 0.0) @@ -152,6 +156,7 @@ func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML { darkenFactor := math.Max(luminance-darken, 0.0) / math.Max(luminance, 1.0/255.0) lightenFactor := math.Min(luminance+lighten, 1.0) / math.Max(luminance, 1.0/255.0) + r, g, b := util.HexToRBGColor(label.Color) scopeBytes := []byte{ uint8(math.Min(math.Round(r*darkenFactor), 255)), uint8(math.Min(math.Round(g*darkenFactor), 255)), @@ -166,11 +171,11 @@ func RenderLabel(ctx context.Context, label *issues_model.Label) template.HTML { itemColor := "#" + hex.EncodeToString(itemBytes) scopeColor := "#" + hex.EncodeToString(scopeBytes) - s := fmt.Sprintf(""+ + s := fmt.Sprintf(""+ "
      %s
      "+ "
      %s
      "+ "
      ", - description, + archivedCSSClass, description, textColor, scopeColor, scopeText, textColor, itemColor, itemText) return template.HTML(s) @@ -211,15 +216,16 @@ func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //n return output } -func RenderLabels(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML { +func RenderLabels(ctx context.Context, locale translation.Locale, labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML { + isPullRequest := issue != nil && issue.IsPull + baseLink := fmt.Sprintf("%s/%s", repoLink, util.Iif(isPullRequest, "pulls", "issues")) htmlCode := `` for _, label := range labels { // Protect against nil value in labels - shouldn't happen but would cause a panic if so if label == nil { continue } - htmlCode += fmt.Sprintf("%s ", - repoLink, label.ID, RenderLabel(ctx, label)) + htmlCode += fmt.Sprintf(`%s`, baseLink, label.ID, RenderLabel(ctx, locale, label)) } htmlCode += "" return template.HTML(htmlCode) diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go index 8648967d38..47c5da6485 100644 --- a/modules/templates/util_render_test.go +++ b/modules/templates/util_render_test.go @@ -7,17 +7,21 @@ import ( "context" "html/template" "os" + "strings" "testing" + "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" + "code.gitea.io/gitea/modules/translation" "github.com/stretchr/testify/assert" ) -const testInput = ` space @mention-user +func testInput() string { + s := ` space @mention-user /just/a/path.bin https://example.com/file.bin [local link](file.bin) @@ -36,8 +40,10 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit mail@domain.com @mention-user test #123 - space + space ` + return strings.ReplaceAll(s, "", " ") +} var testMetas = map[string]string{ "user": "user13", @@ -117,27 +123,27 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a582 com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit 👍 mail@domain.com -@mention-user test -#123 +@mention-user test +#123 space` - assert.EqualValues(t, expected, RenderCommitBody(context.Background(), testInput, testMetas)) + assert.EqualValues(t, expected, RenderCommitBody(context.Background(), testInput(), testMetas)) } func TestRenderCommitMessage(t *testing.T) { - expected := `space @mention-user ` + expected := `space @mention-user ` - assert.EqualValues(t, expected, RenderCommitMessage(context.Background(), testInput, testMetas)) + assert.EqualValues(t, expected, RenderCommitMessage(context.Background(), testInput(), testMetas)) } func TestRenderCommitMessageLinkSubject(t *testing.T) { - expected := `space @mention-user` + expected := `space @mention-user` - assert.EqualValues(t, expected, RenderCommitMessageLinkSubject(context.Background(), testInput, "https://example.com/link", testMetas)) + assert.EqualValues(t, expected, RenderCommitMessageLinkSubject(context.Background(), testInput(), "https://example.com/link", testMetas)) } func TestRenderIssueTitle(t *testing.T) { - expected := ` space @mention-user + expected := ` space @mention-user /just/a/path.bin https://example.com/file.bin [local link](file.bin) @@ -155,14 +161,15 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit 👍 mail@domain.com @mention-user test -#123 - space +#123 + space ` - assert.EqualValues(t, expected, RenderIssueTitle(context.Background(), testInput, testMetas)) + expected = strings.ReplaceAll(expected, "", " ") + assert.EqualValues(t, expected, RenderIssueTitle(context.Background(), testInput(), testMetas)) } func TestRenderMarkdownToHtml(t *testing.T) { - expected := `

      space @mention-user
      + expected := `

      space @mention-user
      /just/a/path.bin https://example.com/file.bin local link @@ -179,9 +186,24 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a582 com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit 👍 mail@domain.com -@mention-user test +@mention-user test #123 space

      ` - assert.EqualValues(t, expected, RenderMarkdownToHtml(context.Background(), testInput)) + assert.EqualValues(t, expected, RenderMarkdownToHtml(context.Background(), testInput())) +} + +func TestRenderLabels(t *testing.T) { + ctx := context.Background() + locale := &translation.MockLocale{} + + label := &issues.Label{ID: 123, Name: "label-name", Color: "label-color"} + issue := &issues.Issue{} + expected := `/owner/repo/issues?labels=123` + assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected) + + label = &issues.Label{ID: 123, Name: "label-name", Color: "label-color"} + issue = &issues.Issue{IsPull: true} + expected = `/owner/repo/pulls?labels=123` + assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected) } diff --git a/modules/timeutil/datetime.go b/modules/timeutil/datetime.go index 62b94f7cf4..c089173560 100644 --- a/modules/timeutil/datetime.go +++ b/modules/timeutil/datetime.go @@ -13,6 +13,8 @@ import ( // DateTime renders an absolute time HTML element by datetime. func DateTime(format string, datetime any, extraAttrs ...string) template.HTML { + // TODO: remove the extraAttrs argument, it's not used in any call to DateTime + if p, ok := datetime.(*time.Time); ok { datetime = *p } @@ -51,18 +53,16 @@ func DateTime(format string, datetime any, extraAttrs ...string) template.HTML { attrs := make([]string, 0, 10+len(extraAttrs)) attrs = append(attrs, extraAttrs...) - attrs = append(attrs, `data-tooltip-content`, `data-tooltip-interactive="true"`) - attrs = append(attrs, `format="datetime"`, `weekday=""`, `year="numeric"`) + attrs = append(attrs, `weekday=""`, `year="numeric"`) switch format { - case "short": - attrs = append(attrs, `month="short"`, `day="numeric"`) - case "long": - attrs = append(attrs, `month="long"`, `day="numeric"`) - case "full": - attrs = append(attrs, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`) + case "short", "long": // date only + attrs = append(attrs, `month="`+format+`"`, `day="numeric"`) + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) + case "full": // full date including time + attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`) + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) default: panic(fmt.Sprintf("Unsupported format %s", format)) } - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) } diff --git a/modules/timeutil/datetime_test.go b/modules/timeutil/datetime_test.go index 26494b8475..ac2ce35ba2 100644 --- a/modules/timeutil/datetime_test.go +++ b/modules/timeutil/datetime_test.go @@ -18,6 +18,7 @@ func TestDateTime(t *testing.T) { defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() refTimeStr := "2018-01-01T00:00:00Z" + refDateStr := "2018-01-01" refTime, _ := time.Parse(time.RFC3339, refTimeStr) refTimeStamp := TimeStamp(refTime.Unix()) @@ -27,17 +28,20 @@ func TestDateTime(t *testing.T) { assert.EqualValues(t, "-", DateTime("short", TimeStamp(0))) actual := DateTime("short", "invalid") - assert.EqualValues(t, `invalid`, actual) + assert.EqualValues(t, `invalid`, actual) actual = DateTime("short", refTimeStr) - assert.EqualValues(t, `2018-01-01T00:00:00Z`, actual) + assert.EqualValues(t, `2018-01-01T00:00:00Z`, actual) actual = DateTime("short", refTime) - assert.EqualValues(t, `2018-01-01`, actual) + assert.EqualValues(t, `2018-01-01`, actual) + + actual = DateTime("short", refDateStr) + assert.EqualValues(t, `2018-01-01`, actual) actual = DateTime("short", refTimeStamp) - assert.EqualValues(t, `2017-12-31`, actual) + assert.EqualValues(t, `2017-12-31`, actual) actual = DateTime("full", refTimeStamp) - assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) + assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) } diff --git a/modules/timeutil/since.go b/modules/timeutil/since.go index dfaa0e3e3a..dba42c793a 100644 --- a/modules/timeutil/since.go +++ b/modules/timeutil/since.go @@ -126,7 +126,7 @@ func timeSinceUnix(then, now time.Time, _ translation.Locale) template.HTML { } // declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip - htm := fmt.Sprintf(`%s`, + htm := fmt.Sprintf(`%s`, attrs, then.Format(time.RFC3339), friendlyText) return template.HTML(htm) } @@ -134,7 +134,7 @@ func timeSinceUnix(then, now time.Time, _ translation.Locale) template.HTML { // TimeSince renders relative time HTML given a time.Time func TimeSince(then time.Time, lang translation.Locale) template.HTML { if setting.UI.PreferredTimestampTense == "absolute" { - return DateTime("full", then, `class="time-since"`) + return DateTime("full", then) } return timeSinceUnix(then, time.Now(), lang) } diff --git a/modules/timeutil/timestamp.go b/modules/timeutil/timestamp.go index 27a80b6682..e77652b24f 100644 --- a/modules/timeutil/timestamp.go +++ b/modules/timeutil/timestamp.go @@ -21,8 +21,9 @@ var ( ) // MockSet sets the time to a mocked time.Time -func MockSet(now time.Time) { +func MockSet(now time.Time) func() { mockNow = now + return MockUnset } // MockUnset will unset the mocked time.Time diff --git a/modules/translation/mock.go b/modules/translation/mock.go index 18fbc1044a..f457271ea5 100644 --- a/modules/translation/mock.go +++ b/modules/translation/mock.go @@ -6,6 +6,7 @@ package translation import ( "fmt" "html/template" + "strings" ) // MockLocale provides a mocked locale without any translations @@ -19,18 +20,25 @@ func (l MockLocale) Language() string { return "en" } -func (l MockLocale) TrString(s string, _ ...any) string { - return s +func (l MockLocale) TrString(s string, args ...any) string { + return sprintAny(s, args...) } -func (l MockLocale) Tr(s string, a ...any) template.HTML { - return template.HTML(s) +func (l MockLocale) Tr(s string, args ...any) template.HTML { + return template.HTML(sprintAny(s, args...)) } func (l MockLocale) TrN(cnt any, key1, keyN string, args ...any) template.HTML { - return template.HTML(key1) + return template.HTML(sprintAny(key1, args...)) } func (l MockLocale) PrettyNumber(v any) string { return fmt.Sprint(v) } + +func sprintAny(s string, args ...any) string { + if len(args) == 0 { + return s + } + return s + ":" + fmt.Sprintf(strings.Repeat(",%v", len(args))[1:], args...) +} diff --git a/modules/util/color.go b/modules/util/color.go index 240b045c28..9c520dce78 100644 --- a/modules/util/color.go +++ b/modules/util/color.go @@ -4,22 +4,10 @@ package util import ( "fmt" - "math" "strconv" "strings" ) -// Check similar implementation in web_src/js/utils/color.js and keep synchronization - -// Return R, G, B values defined in reletive luminance -func getLuminanceRGB(channel float64) float64 { - sRGB := channel / 255 - if sRGB <= 0.03928 { - return sRGB / 12.92 - } - return math.Pow((sRGB+0.055)/1.055, 2.4) -} - // Get color as RGB values in 0..255 range from the hex color string (with or without #) func HexToRBGColor(colorString string) (float64, float64, float64) { hexString := colorString @@ -47,19 +35,23 @@ func HexToRBGColor(colorString string) (float64, float64, float64) { return r, g, b } -// return luminance given RGB channels -// Reference from: https://www.w3.org/WAI/GL/wiki/Relative_luminance -func GetLuminance(r, g, b float64) float64 { - R := getLuminanceRGB(r) - G := getLuminanceRGB(g) - B := getLuminanceRGB(b) - luminance := 0.2126*R + 0.7152*G + 0.0722*B - return luminance +// Returns relative luminance for a SRGB color - https://en.wikipedia.org/wiki/Relative_luminance +// Keep this in sync with web_src/js/utils/color.js +func GetRelativeLuminance(color string) float64 { + r, g, b := HexToRBGColor(color) + return (0.2126729*r + 0.7151522*g + 0.0721750*b) / 255 } -// Reference from: https://firsching.ch/github_labels.html -// In the future WCAG 3 APCA may be a better solution. -// Check if text should use light color based on RGB of background -func UseLightTextOnBackground(r, g, b float64) bool { - return GetLuminance(r, g, b) < 0.453 +func UseLightText(backgroundColor string) bool { + return GetRelativeLuminance(backgroundColor) < 0.453 +} + +// Given a background color, returns a black or white foreground color that the highest +// contrast ratio. In the future, the APCA contrast function, or CSS `contrast-color` will be better. +// https://github.com/color-js/color.js/blob/eb7b53f7a13bb716ec8b28c7a56f052cd599acd9/src/contrast/APCA.js#L42 +func ContrastColor(backgroundColor string) string { + if UseLightText(backgroundColor) { + return "#fff" + } + return "#000" } diff --git a/modules/util/color_test.go b/modules/util/color_test.go index d96ac36730..be6e6b122a 100644 --- a/modules/util/color_test.go +++ b/modules/util/color_test.go @@ -33,33 +33,31 @@ func Test_HexToRBGColor(t *testing.T) { } } -func Test_UseLightTextOnBackground(t *testing.T) { +func Test_UseLightText(t *testing.T) { cases := []struct { - r float64 - g float64 - b float64 - expected bool + color string + expected string }{ - {215, 58, 74, true}, - {0, 117, 202, true}, - {207, 211, 215, false}, - {162, 238, 239, false}, - {112, 87, 255, true}, - {0, 134, 114, true}, - {228, 230, 105, false}, - {216, 118, 227, true}, - {255, 255, 255, false}, - {43, 134, 133, true}, - {43, 135, 134, true}, - {44, 135, 134, true}, - {59, 182, 179, true}, - {124, 114, 104, true}, - {126, 113, 108, true}, - {129, 112, 109, true}, - {128, 112, 112, true}, + {"#d73a4a", "#fff"}, + {"#0075ca", "#fff"}, + {"#cfd3d7", "#000"}, + {"#a2eeef", "#000"}, + {"#7057ff", "#fff"}, + {"#008672", "#fff"}, + {"#e4e669", "#000"}, + {"#d876e3", "#000"}, + {"#ffffff", "#000"}, + {"#2b8684", "#fff"}, + {"#2b8786", "#fff"}, + {"#2c8786", "#000"}, + {"#3bb6b3", "#000"}, + {"#7c7268", "#fff"}, + {"#7e716c", "#fff"}, + {"#81706d", "#fff"}, + {"#807070", "#fff"}, + {"#84b6eb", "#000"}, } for n, c := range cases { - result := UseLightTextOnBackground(c.r, c.g, c.b) - assert.Equal(t, c.expected, result, "case %d: error should match", n) + assert.Equal(t, c.expected, ContrastColor(c.color), "case %d: error should match", n) } } diff --git a/modules/util/slice.go b/modules/util/slice.go index a7073fedee..9c878c24be 100644 --- a/modules/util/slice.go +++ b/modules/util/slice.go @@ -53,3 +53,21 @@ func Sorted[S ~[]E, E cmp.Ordered](values S) S { slices.Sort(values) return values } + +// TODO: Replace with "maps.Values" once available, current it only in golang.org/x/exp/maps but not in standard library +func ValuesOfMap[K comparable, V any](m map[K]V) []V { + values := make([]V, 0, len(m)) + for _, v := range m { + values = append(values, v) + } + return values +} + +// TODO: Replace with "maps.Keys" once available, current it only in golang.org/x/exp/maps but not in standard library +func KeysOfMap[K comparable, V any](m map[K]V) []K { + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + return keys +} diff --git a/modules/util/util.go b/modules/util/util.go index 5c75158196..44b5a6ed81 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -212,3 +212,29 @@ func ToFloat64(number any) (float64, error) { func ToPointer[T any](val T) *T { return &val } + +// Iif is an "inline-if", it returns "trueVal" if "condition" is true, otherwise "falseVal" +func Iif[T any](condition bool, trueVal, falseVal T) T { + if condition { + return trueVal + } + return falseVal +} + +// IfZero returns "def" if "v" is a zero value, otherwise "v" +func IfZero[T comparable](v, def T) T { + var zero T + if v == zero { + return def + } + return v +} + +func ReserveLineBreakForTextarea(input string) string { + // Since the content is from a form which is a textarea, the line endings are \r\n. + // It's a standard behavior of HTML. + // But we want to store them as \n like what GitHub does. + // And users are unlikely to really need to keep the \r. + // Other than this, we should respect the original content, even leading or trailing spaces. + return strings.ReplaceAll(input, "\r\n", "\n") +} diff --git a/modules/util/util_test.go b/modules/util/util_test.go index 819e12ee91..de8f065cad 100644 --- a/modules/util/util_test.go +++ b/modules/util/util_test.go @@ -121,9 +121,9 @@ func Test_NormalizeEOL(t *testing.T) { } func Test_RandomInt(t *testing.T) { - int, err := CryptoRandomInt(255) - assert.True(t, int >= 0) - assert.True(t, int <= 255) + randInt, err := CryptoRandomInt(255) + assert.True(t, randInt >= 0) + assert.True(t, randInt <= 255) assert.NoError(t, err) } @@ -235,3 +235,8 @@ func TestToPointer(t *testing.T) { val123 := 123 assert.False(t, &val123 == ToPointer(val123)) } + +func TestReserveLineBreakForTextarea(t *testing.T) { + assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata"), "test\ndata") + assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata\r\n"), "test\ndata\n") +} diff --git a/modules/web/handler.go b/modules/web/handler.go index 26b7428016..1812c664b3 100644 --- a/modules/web/handler.go +++ b/modules/web/handler.go @@ -128,6 +128,16 @@ func hasResponseBeenWritten(argsIn []reflect.Value) bool { return false } +func wrapHandlerProvider[T http.Handler](hp func(next http.Handler) T, funcInfo *routing.FuncInfo) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + h := hp(next) // this handle could be dynamically generated, so we can't use it for debug info + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + routing.UpdateFuncInfo(req.Context(), funcInfo) + h.ServeHTTP(resp, req) + }) + } +} + // toHandlerProvider converts a handler to a handler provider // A handler provider is a function that takes a "next" http.Handler, it can be used as a middleware func toHandlerProvider(handler any) func(next http.Handler) http.Handler { @@ -138,13 +148,9 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler { } if hp, ok := handler.(func(next http.Handler) http.Handler); ok { - return func(next http.Handler) http.Handler { - h := hp(next) // this handle could be dynamically generated, so we can't use it for debug info - return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - routing.UpdateFuncInfo(req.Context(), funcInfo) - h.ServeHTTP(resp, req) - }) - } + return wrapHandlerProvider(hp, funcInfo) + } else if hp, ok := handler.(func(http.Handler) http.HandlerFunc); ok { + return wrapHandlerProvider(hp, funcInfo) } provider := func(next http.Handler) http.Handler { diff --git a/modules/web/middleware/cookie.go b/modules/web/middleware/cookie.go index 621640895b..ec6b06f993 100644 --- a/modules/web/middleware/cookie.go +++ b/modules/web/middleware/cookie.go @@ -9,6 +9,7 @@ import ( "net/url" "strings" + "code.gitea.io/gitea/modules/session" "code.gitea.io/gitea/modules/setting" ) @@ -45,10 +46,40 @@ func SetSiteCookie(resp http.ResponseWriter, name, value string, maxAge int) { SameSite: setting.SessionConfig.SameSite, } resp.Header().Add("Set-Cookie", cookie.String()) - if maxAge < 0 { - // There was a bug in "setting.SessionConfig.CookiePath" code, the old default value of it was empty "". - // So we have to delete the cookie on path="" again, because some old code leaves cookies on path="". - cookie.Path = strings.TrimSuffix(setting.SessionConfig.CookiePath, "/") - resp.Header().Add("Set-Cookie", cookie.String()) - } + // Previous versions would use a cookie path with a trailing /. + // These are more specific than cookies without a trailing /, so + // we need to delete these if they exist. + deleteLegacySiteCookie(resp, name) +} + +// deleteLegacySiteCookie deletes the cookie with the given name at the cookie +// path with a trailing /, which would unintentionally override the cookie. +func deleteLegacySiteCookie(resp http.ResponseWriter, name string) { + if setting.SessionConfig.CookiePath == "" || strings.HasSuffix(setting.SessionConfig.CookiePath, "/") { + // If the cookie path ends with /, no legacy cookies will take + // precedence, so do nothing. The exception is that cookies with no + // path could override other cookies, but it's complicated and we don't + // currently handle that. + return + } + + cookie := &http.Cookie{ + Name: name, + Value: "", + MaxAge: -1, + Path: setting.SessionConfig.CookiePath + "/", + Domain: setting.SessionConfig.Domain, + Secure: setting.SessionConfig.Secure, + HttpOnly: true, + SameSite: setting.SessionConfig.SameSite, + } + resp.Header().Add("Set-Cookie", cookie.String()) +} + +func init() { + session.BeforeRegenerateSession = append(session.BeforeRegenerateSession, func(resp http.ResponseWriter, _ *http.Request) { + // Ensure that a cookie with a trailing slash does not take precedence over + // the cookie written by the middleware. + deleteLegacySiteCookie(resp, setting.SessionConfig.CookieName) + }) } diff --git a/options/license/AMD-newlib b/options/license/AMD-newlib new file mode 100644 index 0000000000..1b2f1abd6f --- /dev/null +++ b/options/license/AMD-newlib @@ -0,0 +1,11 @@ +Copyright 1989, 1990 Advanced Micro Devices, Inc. + +This software is the property of Advanced Micro Devices, Inc (AMD) which +specifically grants the user the right to modify, use and distribute this +software provided this notice is not removed or altered. All other rights +are reserved by AMD. + +AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS +SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL +DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR +USE OF THIS SOFTWARE. diff --git a/options/license/APL-1.0 b/options/license/APL-1.0 index 261f2d687c..0748f90cd9 100644 --- a/options/license/APL-1.0 +++ b/options/license/APL-1.0 @@ -210,21 +210,21 @@ PART 1: INITIAL CONTRIBUTOR AND DESIGNATED WEB SITE The Initial Contributor is: ____________________________________________________ -  + [Enter full name of Initial Contributor] Address of Initial Contributor: ________________________________________________ -  + ________________________________________________ -  + ________________________________________________ -  + [Enter address above] The Designated Web Site is: __________________________________________________ -  + [Enter URL for Designated Web Site of Initial Contributor] NOTE: The Initial Contributor is to complete this Part 1, along with Parts 2, 3, and 5, and, if applicable, Parts 4 and 6. @@ -237,27 +237,27 @@ The date on which the Initial Work was first available under this License: _____ PART 3: GOVERNING JURISDICTION -For the purposes of this License, the Governing Jurisdiction is _________________________________________________. 
[Initial Contributor to Enter Governing Jurisdiction here] +For the purposes of this License, the Governing Jurisdiction is _________________________________________________. [Initial Contributor to Enter Governing Jurisdiction here] PART 4: THIRD PARTIES For the purposes of this License, "Third Party" has the definition set forth below in the ONE paragraph selected by the Initial Contributor from paragraphs A, B, C, D and E when the Initial Work is distributed or otherwise made available by the Initial Contributor. To select one of the following paragraphs, the Initial Contributor must place an "X" or "x" in the selection box alongside the one respective paragraph selected. SELECTION -  + BOX PARAGRAPH -[  ] A. "THIRD PARTY" means any third party. -  -  -[  ] B. "THIRD PARTY" means any third party except for any of the following: (a) a wholly owned subsidiary of the Subsequent Contributor in question; (b) a legal entity (the "PARENT") that wholly owns the Subsequent Contributor in question; or (c) a wholly owned subsidiary of the wholly owned subsidiary in (a) or of the Parent in (b). -  -  -[  ] C. "THIRD PARTY" means any third party except for any of the following: (a) any Person directly or indirectly owning a majority of the voting interest in the Subsequent Contributor or (b) any Person in which the Subsequent Contributor directly or indirectly owns a majority voting interest. -  -  -[  ] D. "THIRD PARTY" means any third party except for any Person directly or indirectly controlled by the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise. -  -  -[  ] E. "THIRD PARTY" means any third party except for any Person directly or indirectly controlling, controlled by, or under common control with the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise. +[ ] A. "THIRD PARTY" means any third party. + + +[ ] B. "THIRD PARTY" means any third party except for any of the following: (a) a wholly owned subsidiary of the Subsequent Contributor in question; (b) a legal entity (the "PARENT") that wholly owns the Subsequent Contributor in question; or (c) a wholly owned subsidiary of the wholly owned subsidiary in (a) or of the Parent in (b). + + +[ ] C. "THIRD PARTY" means any third party except for any of the following: (a) any Person directly or indirectly owning a majority of the voting interest in the Subsequent Contributor or (b) any Person in which the Subsequent Contributor directly or indirectly owns a majority voting interest. + + +[ ] D. "THIRD PARTY" means any third party except for any Person directly or indirectly controlled by the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise. + + +[ ] E. "THIRD PARTY" means any third party except for any Person directly or indirectly controlling, controlled by, or under common control with the Subsequent Contributor. For purposes of this definition, "control" shall mean the power to direct or cause the direction of, the management and policies of such Person whether through the ownership of voting interests, by contract, or otherwise. The default definition of "THIRD PARTY" is the definition set forth in paragraph A, if NONE OR MORE THAN ONE of paragraphs A, B, C, D or E in this Part 4 are selected by the Initial Contributor. PART 5: NOTICE @@ -271,8 +271,8 @@ PART 6: PATENT LICENSING TERMS For the purposes of this License, paragraphs A, B, C, D and E of this Part 6 of Exhibit A are only incorporated and form part of the terms of the License if the Initial Contributor places an "X" or "x" in the selection box alongside the YES answer to the question immediately below. Is this a Patents-Included License pursuant to Section 2.2 of the License? -YES [      ] -NO [      ] +YES [ ] +NO [ ] By default, if YES is not selected by the Initial Contributor, the answer is NO. diff --git a/options/license/BSD-2-clause-first-lines b/options/license/BSD-2-clause-first-lines new file mode 100644 index 0000000000..3774caf24a --- /dev/null +++ b/options/license/BSD-2-clause-first-lines @@ -0,0 +1,27 @@ +Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone +Corporation). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer as the first lines of this file unmodified. + +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY NTT "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/options/license/HPND-UC-export-US b/options/license/HPND-UC-export-US new file mode 100644 index 0000000000..015556c5f9 --- /dev/null +++ b/options/license/HPND-UC-export-US @@ -0,0 +1,10 @@ +Copyright (C) 1985, 1990 Regents of the University of California. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies. The University of California +makes no representations about the suitability of this +software for any purpose. It is provided "as is" without +express or implied warranty. Export of this software outside +of the United States of America may require an export license. diff --git a/options/license/IBM-pibs b/options/license/IBM-pibs index 49454b8b1e..ee9c7be36d 100644 --- a/options/license/IBM-pibs +++ b/options/license/IBM-pibs @@ -4,5 +4,5 @@ Any user of this software should understand that IBM cannot provide technical su Any person who transfers this source code or any derivative work must include the IBM copyright notice, this paragraph, and the preceding two paragraphs in the transferred software. -COPYRIGHT   I B M   CORPORATION 2002 -LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M +COPYRIGHT I B M CORPORATION 2002 +LICENSED MATERIAL - PROGRAM PROPERTY OF I B M diff --git a/options/license/NCGL-UK-2.0 b/options/license/NCGL-UK-2.0 index 31fbad6f83..15c4f63c22 100644 --- a/options/license/NCGL-UK-2.0 +++ b/options/license/NCGL-UK-2.0 @@ -12,15 +12,15 @@ The Licensor grants you a worldwide, royalty-free, perpetual, non-exclusive lice This licence does not affect your freedom under fair dealing or fair use or any other copyright or database right exceptions and limitations. You are free to: - copy, publish, distribute and transmit the Information; + copy, publish, distribute and transmit the Information; adapt the Information; exploit the Information for Non-Commercial purposes for example, by combining it with other information in your own product or application. You are not permitted to: - exercise any of the rights granted to you by this licence in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. + exercise any of the rights granted to you by this licence in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. You must, where you do any of the above: - acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence; + acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence; If the Information Provider does not provide a specific attribution statement, you must use the following: Contains information licensed under the Non-Commercial Government Licence v2.0. diff --git a/options/license/NCL b/options/license/NCL new file mode 100644 index 0000000000..3bfb658c26 --- /dev/null +++ b/options/license/NCL @@ -0,0 +1,32 @@ +Copyright (c) 2004 the University Corporation for Atmospheric +Research ("UCAR"). All rights reserved. Developed by NCAR's +Computational and Information Systems Laboratory, UCAR, +www.cisl.ucar.edu. + +Redistribution and use of the Software in source and binary forms, +with or without modification, is permitted provided that the +following conditions are met: + +- Neither the names of NCAR's Computational and Information Systems +Laboratory, the University Corporation for Atmospheric Research, +nor the names of its sponsors or contributors may be used to +endorse or promote products derived from this Software without +specific prior written permission. + +- Redistributions of source code must retain the above copyright +notices, this list of conditions, and the disclaimer below. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions, and the disclaimer below in the +documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/options/license/NPL-1.1 b/options/license/NPL-1.1 index 62c5296400..0d5457ff04 100644 --- a/options/license/NPL-1.1 +++ b/options/license/NPL-1.1 @@ -2,7 +2,7 @@ Netscape Public LIcense version 1.1 AMENDMENTS -The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla Public License Version 1.1 with the following Amendments, including Exhibit A-Netscape Public License.  Files identified with "Exhibit A-Netscape Public License" are governed by the Netscape Public License Version 1.1. +The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla Public License Version 1.1 with the following Amendments, including Exhibit A-Netscape Public License. Files identified with "Exhibit A-Netscape Public License" are governed by the Netscape Public License Version 1.1. Additional Terms applicable to the Netscape Public License. @@ -28,7 +28,7 @@ Additional Terms applicable to the Netscape Public License. Notwithstanding the limitations of Section 11 above, the provisions regarding litigation in Section 11(a), (b) and (c) of the License shall apply to all disputes relating to this License. EXHIBIT A-Netscape Public License. -   + "The contents of this file are subject to the Netscape Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/NPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. @@ -37,8 +37,8 @@ The Original Code is Mozilla Communicator client code, released March 31, 1998. The Initial Developer of the Original Code is Netscape Communications Corporation. Portions created by Netscape are Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights Reserved. Contributor(s): ______________________________________. -   -Alternatively, the contents of this file may be used under the terms of the _____ license (the  "[___] License"), in which case the provisions of [______] License are applicable  instead of those above.  If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the NPL, indicate your decision by deleting  the provisions above and replace  them with the notice and other provisions required by the [___] License.  If you do not delete the provisions above, a recipient may use your version of this file under either the NPL or the [___] License." + +Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the NPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the NPL or the [___] License." Mozilla Public License Version 1.1 diff --git a/options/license/OAR b/options/license/OAR new file mode 100644 index 0000000000..ca5c4b9617 --- /dev/null +++ b/options/license/OAR @@ -0,0 +1,12 @@ +COPYRIGHT (c) 1989-2013, 2015. +On-Line Applications Research Corporation (OAR). + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION +OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS +SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. diff --git a/options/license/OCCT-PL b/options/license/OCCT-PL index 85df3c73c5..9b6fccc1c9 100644 --- a/options/license/OCCT-PL +++ b/options/license/OCCT-PL @@ -6,7 +6,7 @@ OPEN CASCADE releases and makes publicly available the source code of the softwa It is not the purpose of this license to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this license has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. Please read this license carefully and completely before downloading this software. By downloading, using, modifying, distributing and sublicensing this software, you indicate your acceptance to be bound by the terms and conditions of this license. If you do not want to accept or cannot accept for any reasons the terms and conditions of this license, please do not download or use in any manner this software. -  + 1. Definitions Unless there is something in the subject matter or in the context inconsistent therewith, the capitalized terms used in this License shall have the following meaning. @@ -26,13 +26,13 @@ Unless there is something in the subject matter or in the context inconsistent t "Software": means the Original Code, the Modifications, the combination of Original Code and any Modifications or any respective portions thereof. "You" or "Your": means an individual or a legal entity exercising rights under this License -  + 2. Acceptance of license By using, reproducing, modifying, distributing or sublicensing the Software or any portion thereof, You expressly indicate Your acceptance of the terms and conditions of this License and undertake to act in accordance with all the provisions of this License applicable to You. -  + 3. Scope and purpose This License applies to the Software and You may not use, reproduce, modify, distribute, sublicense or circulate the Software, or any portion thereof, except as expressly provided under this License. Any attempt to otherwise use, reproduce, modify, distribute or sublicense the Software is void and will automatically terminate Your rights under this License. -  + 4. Contributor license Subject to the terms and conditions of this License, the Initial Developer and each of the Contributors hereby grant You a world-wide, royalty-free, irrevocable and non-exclusive license under the Applicable Intellectual Property Rights they own or control, to use, reproduce, modify, distribute and sublicense the Software provided that: diff --git a/options/license/OGL-UK-1.0 b/options/license/OGL-UK-1.0 index a761c9916f..867c0e353b 100644 --- a/options/license/OGL-UK-1.0 +++ b/options/license/OGL-UK-1.0 @@ -10,20 +10,20 @@ The Licensor grants you a worldwide, royalty-free, perpetual, non-exclusive lice This licence does not affect your freedom under fair dealing or fair use or any other copyright or database right exceptions and limitations. You are free to: - copy, publish, distribute and transmit the Information; + copy, publish, distribute and transmit the Information; adapt the Information; exploit the Information commercially for example, by combining it with other Information, or by including it in your own product or application. You must, where you do any of the above: - acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence; -  If the Information Provider does not provide a specific attribution statement, or if you are using Information from several Information Providers and multiple attributions are not practical in your product or application, you may consider using the following:
 Contains public sector information licensed under the Open Government Licence v1.0. + acknowledge the source of the Information by including any attribution statement specified by the Information Provider(s) and, where possible, provide a link to this licence; + If the Information Provider does not provide a specific attribution statement, or if you are using Information from several Information Providers and multiple attributions are not practical in your product or application, you may consider using the following: Contains public sector information licensed under the Open Government Licence v1.0. ensure that you do not use the Information in a way that suggests any official status or that the Information Provider endorses you or your use of the Information; ensure that you do not mislead others or misrepresent the Information or its source; ensure that your use of the Information does not breach the Data Protection Act 1998 or the Privacy and Electronic Communications (EC Directive) Regulations 2003. These are important conditions of this licence and if you fail to comply with them the rights granted to you under this licence, or any similar licence granted by the Licensor, will end automatically. - Exemptions + Exemptions This licence does not cover the use of: - personal data in the Information; @@ -48,22 +48,22 @@ Definitions In this licence, the terms below have the following meanings: -‘Information’
means information protected by copyright or by database right (for example, literary and artistic works, content, data and source code) offered for use under the terms of this licence. +‘Information’ means information protected by copyright or by database right (for example, literary and artistic works, content, data and source code) offered for use under the terms of this licence. -‘Information Provider’
means the person or organisation providing the Information under this licence. +‘Information Provider’ means the person or organisation providing the Information under this licence. -‘Licensor’
means any Information Provider which has the authority to offer Information under the terms of this licence or the Controller of Her Majesty’s Stationery Office, who has the authority to offer Information subject to Crown copyright and Crown database rights and Information subject to copyright and database right that has been assigned to or acquired by the Crown, under the terms of this licence. +‘Licensor’ means any Information Provider which has the authority to offer Information under the terms of this licence or the Controller of Her Majesty’s Stationery Office, who has the authority to offer Information subject to Crown copyright and Crown database rights and Information subject to copyright and database right that has been assigned to or acquired by the Crown, under the terms of this licence. -‘Use’
as a verb, means doing any act which is restricted by copyright or database right, whether in the original medium or in any other medium, and includes without limitation distributing, copying, adapting, modifying as may be technically necessary to use it in a different mode or format. +‘Use’ as a verb, means doing any act which is restricted by copyright or database right, whether in the original medium or in any other medium, and includes without limitation distributing, copying, adapting, modifying as may be technically necessary to use it in a different mode or format. -‘You’
means the natural or legal person, or body of persons corporate or incorporate, acquiring rights under this licence. +‘You’ means the natural or legal person, or body of persons corporate or incorporate, acquiring rights under this licence. About the Open Government Licence The Controller of Her Majesty’s Stationery Office (HMSO) has developed this licence as a tool to enable Information Providers in the public sector to license the use and re-use of their Information under a common open licence. The Controller invites public sector bodies owning their own copyright and database rights to permit the use of their Information under this licence. -The Controller of HMSO has authority to license Information subject to copyright and database right owned by the Crown. The extent of the Controller’s offer to license this Information under the terms of this licence is set out in the UK Government Licensing Framework. +The Controller of HMSO has authority to license Information subject to copyright and database right owned by the Crown. The extent of the Controller’s offer to license this Information under the terms of this licence is set out in the UK Government Licensing Framework. This is version 1.0 of the Open Government Licence. The Controller of HMSO may, from time to time, issue new versions of the Open Government Licence. However, you may continue to use Information licensed under this version should you wish to do so. These terms have been aligned to be interoperable with any Creative Commons Attribution Licence, which covers copyright, and Open Data Commons Attribution License, which covers database rights and applicable copyrights. -Further context, best practice and guidance can be found in the UK Government Licensing Framework section on The National Archives website. +Further context, best practice and guidance can be found in the UK Government Licensing Framework section on The National Archives website. diff --git a/options/license/OSET-PL-2.1 b/options/license/OSET-PL-2.1 index 15f0c7758c..e0ed2e1398 100644 --- a/options/license/OSET-PL-2.1 +++ b/options/license/OSET-PL-2.1 @@ -100,7 +100,8 @@ If it is impossible for You to comply with any of the terms of this License with 5.1 Failure to Comply The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60-days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30-days after Your receipt of the notice. - 5.2 Patent Infringement Claims
 If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. + 5.2 Patent Infringement Claims + If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3 Additional Compliance Terms Notwithstanding the foregoing in this Section 5, for purposes of this Section, if You breach Section 3.1 (Distribution of Source Form), Section 3.2 (Distribution of Executable Form), Section 3.3 (Distribution of a Larger Work), or Section 3.4 (Notices), then becoming compliant as described in Section 5.1 must also include, no later than 30 days after receipt by You of notice of such violation by a Contributor, making the Covered Software available in Source Code Form as required by this License on a publicly available computer network for a period of no less than three (3) years. diff --git a/options/license/SHL-2.0 b/options/license/SHL-2.0 index e522a396fe..9218b47a72 100644 --- a/options/license/SHL-2.0 +++ b/options/license/SHL-2.0 @@ -1,22 +1,22 @@ # Solderpad Hardware Licence Version 2.0 -This licence (the “Licence”) operates as a wraparound licence to the Apache License Version 2.0 (the “Apache License”) and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in italics indicate changes rom the Apache License, but are indicative and not to be taken into account in interpretation. +This licence (the “Licence”) operates as a wraparound licence to the Apache License Version 2.0 (the “Apache License”) and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in italics indicate changes rom the Apache License, but are indicative and not to be taken into account in interpretation. 1. The definitions set out in the Apache License are modified as follows: -Copyright any reference to ‘copyright’ (whether capitalised or not) includes ‘Rights’ (as defined below). +Copyright any reference to ‘copyright’ (whether capitalised or not) includes ‘Rights’ (as defined below). -Contribution also includes any design, as well as any work of authorship. +Contribution also includes any design, as well as any work of authorship. -Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the interfaces of the Work and Derivative Works thereof. +Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the interfaces of the Work and Derivative Works thereof. -Object form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works). +Object form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works). -Rights means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks). +Rights means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks). -Source form shall mean the preferred form for making modifications, including but not limited to source code, net lists, board layouts, CAD files, documentation source, and configuration files. -Work also includes a design or work of authorship, whether in Source form or other Object form. +Source form shall mean the preferred form for making modifications, including but not limited to source code, net lists, board layouts, CAD files, documentation source, and configuration files. +Work also includes a design or work of authorship, whether in Source form or other Object form. 2. Grant of Licence -2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under the Rights to reproduce, prepare Derivative Works of, make, adapt, repair, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form and do anything in relation to the Work as if the Rights did not exist. +2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under the Rights to reproduce, prepare Derivative Works of, make, adapt, repair, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form and do anything in relation to the Work as if the Rights did not exist. diff --git a/options/license/SHL-2.1 b/options/license/SHL-2.1 index 4815a9e5ed..c9ae53741f 100644 --- a/options/license/SHL-2.1 +++ b/options/license/SHL-2.1 @@ -19,7 +19,7 @@ The following definitions shall replace the corresponding definitions in the Apa "License" shall mean this Solderpad Hardware License version 2.1, being the terms and conditions for use, manufacture, instantiation, adaptation, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the Rights owner or entity authorized by the Rights owner that is granting the License. -  + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship or design. For the purposes of this License, Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the Work and Derivative Works thereof. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object or material and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works). diff --git a/options/license/SISSL b/options/license/SISSL index 7d6ad9d66c..af38d02d92 100644 --- a/options/license/SISSL +++ b/options/license/SISSL @@ -36,13 +36,13 @@ Sun Industry Standards Source License - Version 1.1 2.0 SOURCE CODE LICENSE - 2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:  + 2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. - (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications.  + (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications. 3.0 DISTRIBUTION OBLIGATIONS @@ -92,14 +92,14 @@ This License represents the complete agreement concerning subject matter hereof. EXHIBIT A - Sun Standards License -"The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________. +"The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________. -Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either  +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is ______________________________________. -The Initial Developer of the Original Code is:  +The Initial Developer of the Original Code is: Sun Microsystems, Inc.. Portions created by: _______________________________________ diff --git a/options/license/Sun-PPP-2000 b/options/license/Sun-PPP-2000 new file mode 100644 index 0000000000..914c19544a --- /dev/null +++ b/options/license/Sun-PPP-2000 @@ -0,0 +1,13 @@ +Copyright (c) 2000 by Sun Microsystems, Inc. +All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation is hereby granted, provided that the above copyright +notice appears in all copies. + +SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF +THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR +ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES diff --git a/options/license/W3C-19980720 b/options/license/W3C-19980720 index a8554039ef..134879044d 100644 --- a/options/license/W3C-19980720 +++ b/options/license/W3C-19980720 @@ -4,7 +4,7 @@ Copyright (c) 1994-2002 World Wide Web Consortium, (Massachusetts Institute of T This W3C work (including software, documents, or other related items) is being provided by the copyright holders under the following license. By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions: -Permission to use, copy, modify, and distribute this software and its documentation, with or without modification,  for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make: +Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make: 1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. diff --git a/options/license/pkgconf b/options/license/pkgconf new file mode 100644 index 0000000000..b8b2ffd996 --- /dev/null +++ b/options/license/pkgconf @@ -0,0 +1,7 @@ +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +This software is provided 'as is' and without any warranty, express or +implied. In no event shall the authors be liable for any damages arising +from the use of this software. diff --git a/options/license/threeparttable b/options/license/threeparttable new file mode 100644 index 0000000000..498b728226 --- /dev/null +++ b/options/license/threeparttable @@ -0,0 +1,3 @@ +This file may be distributed, modified, and used in other works with just +one restriction: modified versions must clearly indicate the modification +(a name change, or a displayed message, or ?). diff --git a/options/license/xzoom b/options/license/xzoom new file mode 100644 index 0000000000..f312dedbc2 --- /dev/null +++ b/options/license/xzoom @@ -0,0 +1,12 @@ +Copyright Itai Nahshon 1995, 1996. +This program is distributed with no warranty. + +Source files for this program may be distributed freely. +Modifications to this file are okay as long as: + a. This copyright notice and comment are preserved and + left at the top of the file. + b. The man page is fixed to reflect the change. + c. The author of this change adds his name and change + description to the list of changes below. +Executable files may be distributed with sources, or with +exact location where the source code can be obtained. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 2a421b1172..82d7867168 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -25,6 +25,7 @@ enable_javascript=Tato stránka vyžaduje JavaScript. toc=Obsah licenses=Licence return_to_gitea=Vrátit se do Gitea +more_items=Více položek username=Uživatelské jméno email=E-mailová adresa @@ -75,7 +76,7 @@ collaborative=Spolupráce forks=Rozštěpení activities=Aktivity -pull_requests=Požadavky na natažení +pull_requests=Pull requesty issues=Úkoly milestones=Milníky @@ -113,6 +114,7 @@ loading=Načítá se… error=Chyba error404=Stránka, kterou se snažíte zobrazit, buď neexistuje, nebo nemáte oprávnění ji zobrazit. go_back=Zpět +invalid_data=Neplatná data: %v never=Nikdy unknown=Neznámý @@ -142,6 +144,41 @@ confirm_delete_selected=Potvrdit odstranění všech vybraných položek? name=Název value=Hodnota +filter=Filtr +filter.clear=Vymazat filtr +filter.is_archived=Archivováno +filter.not_archived=Nearchivované +filter.is_fork=Rozštěpený +filter.not_fork=Není rozštěpený +filter.is_mirror=Zrcadlen +filter.not_mirror=Není zrcadleno +filter.is_template=Šablona +filter.not_template=Není šablona +filter.public=Veřejná +filter.private=Soukromý + +no_results_found=Nebyly nalezeny žádné výsledky. + +[search] +search=Hledat... +type_tooltip=Druh vyhledávání +fuzzy=Fuzzy +fuzzy_tooltip=Zahrnout výsledky, které také úzce odpovídají hledanému výrazu +repo_kind=Hledat repozitáře... +user_kind=Hledat uživatele... +org_kind=Hledat organizace... +team_kind=Hledat týmy... +code_kind=Hledat kód... +code_search_unavailable=Vyhledávání kódu není momentálně dostupné. Obraťte se na správce webu. +code_search_by_git_grep=Aktuální výsledky vyhledávání kódu jsou poskytovány pomocí „git grep“. Pokud správce webu povolí index repozitáře, mohou být výsledky lepší. +package_kind=Hledat balíčky... +project_kind=Hledat projekty... +branch_kind=Hledat větve... +commit_kind=Hledat commity... +runner_kind=Hledat runnery... +no_results=Nebyly nalezeny žádné odpovídající výsledky. +keyword_search_unavailable=Hledání podle klíčového slova není momentálně dostupné. Obraťte se na správce webu. + [aria] navbar=Navigační lišta footer=Patička @@ -247,6 +284,7 @@ email_title=Nastavení e-mailu smtp_addr=Server SMTP smtp_port=Port SMTP smtp_from=Odeslat e-mail jako +smtp_from_invalid=Adresa "Odeslat e-mail jako" je neplatná smtp_from_helper=E-mailová adresa, kterou bude Gitea používat. Zadejte běžnou e-mailovou adresu, nebo použijte formát "Jméno". mailer_user=Uživatelské jméno SMTP mailer_password=Heslo pro SMTP @@ -306,6 +344,7 @@ env_config_keys=Konfigurace prostředí env_config_keys_prompt=Následující proměnné prostředí budou také použity pro váš konfigurační soubor: [home] +nav_menu=Navigační menu uname_holder=Uživatelské jméno nebo e-mailová adresa password_holder=Heslo switch_dashboard_context=Přepnout kontext přehledu @@ -315,7 +354,6 @@ collaborative_repos=Společné repozitáře my_orgs=Mé organizace my_mirrors=Má zrcadla view_home=Zobrazit %s -search_repos=Nalézt repozitář… filter=Ostatní filtry filter_by_team_repositories=Filtrovat podle repozitářů týmu feed_of=Kanál z „%s“ @@ -336,20 +374,8 @@ issues.in_your_repos=Ve vašich repozitářích repos=Repozitáře users=Uživatelé organizations=Organizace -search=Vyhledat go_to=Přejít na code=Kód -search.type.tooltip=Druh vyhledávání -search.fuzzy=Fuzzy -search.fuzzy.tooltip=Zahrnout výsledky, které také úzce odpovídají hledanému výrazu -search.match=Shoda -search.match.tooltip=Zahrnout pouze výsledky, které odpovídají přesnému hledanému výrazu -code_search_unavailable=V současné době není vyhledávání kódu dostupné. Obraťte se na správce webu. -repo_no_results=Nebyly nalezeny žádné odpovídající repozitáře. -user_no_results=Nebyly nalezeni žádní odpovídající uživatelé. -org_no_results=Nebyly nalezeny žádné odpovídající organizace. -code_no_results=Nebyl nalezen žádný zdrojový kód odpovídající hledanému výrazu. -code_search_results=Výsledky hledání pro „%s“ code_last_indexed_at=Naposledy indexováno %s relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty. relevant_repositories=Zobrazují se pouze relevantní repositáře, zobrazit nefiltrované výsledky. @@ -367,7 +393,7 @@ forgot_password_title=Zapomenuté heslo forgot_password=Zapomenuté heslo? sign_up_now=Potřebujete účet? Zaregistrujte se. sign_up_successful=Účet byl úspěšně vytvořen. Vítejte! -confirmation_mail_sent_prompt=Na adresu %s byl zaslán nový potvrzovací e-mail. Zkontrolujte prosím vaši doručenou poštu během následujících %s, abyste dokončili proces registrace. +confirmation_mail_sent_prompt_ex=Nový potvrzovací e-mail byl odeslán na %s. Zkontrolujte prosím svou doručenou poštu během následujících %s a dokončete proces registrace. Pokud je Vaše registrační e-mailová adresa nesprávná, můžete se znovu přihlásit a změnit ji. must_change_password=Aktualizujte své heslo allow_password_change=Vyžádat od uživatele změnu hesla (doporučeno) reset_password_mail_sent_prompt=Na adresu %s byl zaslán potvrzovací e-mail. Zkontrolujte prosím vaši doručenou poštu během následujících %s, abyste dokončili proces obnovení účtu. @@ -377,6 +403,7 @@ prohibit_login=Přihlášení zakázáno prohibit_login_desc=Vašemu účtu je zakázáno se přihlásit, kontaktujte prosím správce webu. resent_limit_prompt=Omlouváme se, ale před chvílí jste požádal o zaslání aktivačního e-mailu. Počkejte prosím 3 minuty a pak to zkuste znovu. has_unconfirmed_mail=Zdravím, %s, máte nepotvrzenou e-mailovou adresu (%s). Pokud jste nedostali e-mail pro potvrzení nebo potřebujete zaslat nový, klikněte prosím na tlačítku níže. +change_unconfirmed_mail_address=Pokud je Vaše registrační e-mailová adresa nesprávná, můžete ji zde změnit a znovu odeslat nový potvrzovací e-mail. resend_mail=Klikněte zde pro odeslání aktivačního e-mailu email_not_associate=Tato e-mailová adresa není spojena s žádným účtem. send_reset_mail=Zaslat e-mail pro obnovení účtu @@ -453,7 +480,7 @@ reset_password.text=Klikněte prosím na následující odkaz pro obnovení vaš register_success=Registrace byla úspěšná -issue_assigned.pull=@%[1]s vás přiřadil/a k požadavku na natažení %[2]s repozitáři %[3]s. +issue_assigned.pull=@%[1]s vás přiřadil/a k pull requestu %[2]s v repozitáři %[3]s. issue_assigned.issue=@%[1]s vás přiřadil/a k úkolu %[2]s repozitáři %[3]s. issue.x_mentioned_you=@%s vás zmínil/a: @@ -463,11 +490,11 @@ issue.action.push_n=@%[1]s nahrál/a %[3]d commity do %[2]s issue.action.close=@%[1]s uzavřel/a #%[2]d. issue.action.reopen=@%[1]s znovu otevřel/a #%[2]d. issue.action.merge=@%[1]s sloučil/a #%[2]d do %[3]s. -issue.action.approve=@%[1]s schválil/a tento požadavek na natažení. -issue.action.reject=@%[1]s požadoval/a změny v tomto požadavku na natažení. -issue.action.review=@%[1]s okomentoval/a tento požadavek na natažení. -issue.action.review_dismissed=@%[1]s odmítl/a poslední kontrolu z %[2]s pro tento požadavek na natažení. -issue.action.ready_for_review=@%[1]s označil/a tento požadavek na natažení jako připravený ke kontrole. +issue.action.approve=@%[1]s schválil/a tento pull request. +issue.action.reject=@%[1]s požadoval/a změny v tomto pull requestu. +issue.action.review=@%[1]s okomentoval/a tento pull request. +issue.action.review_dismissed=@%[1]s odmítl/a poslední kontrolu z %[2]s pro tento pull request. +issue.action.ready_for_review=@%[1]s označil/a tento pull request jako připravený ke kontrole. issue.action.new=@%[1]s vytvořil/a #%[2]d. issue.in_tree_path=V %s: @@ -557,6 +584,7 @@ team_name_been_taken=Název týmu je již použit. team_no_units_error=Povolit přístup alespoň do jedné sekce repozitáře. email_been_used=Tato e-mailová adresa je již používána. email_invalid=Emailová adresa je neplatná. +email_domain_is_not_allowed=Doména uživatelského e-mailu %s je v rozporu s EMAIL_DOMAIN_ALLOWLIST nebo EMAIL_DOMAIN_BLOCKLIST. Ujistěte se, že je Vaše operace očekávána. openid_been_used=OpenID addresa „%s“ je již použita. username_password_incorrect=Uživatelské jméno nebo heslo není správné. password_complexity=Heslo nesplňuje požadavky na složitost: @@ -568,6 +596,8 @@ enterred_invalid_repo_name=Zadaný název repozitáře není správný. enterred_invalid_org_name=Zadaný název organizace není správný. enterred_invalid_owner_name=Nové jméno vlastníka není správné. enterred_invalid_password=Zadané heslo není správné. +unset_password=Přihlášený uživatel nenastavil heslo. +unsupported_login_type=Typ přihlášení není podporován pro odstranění účtu. user_not_exist=Tento uživatel neexistuje. team_not_exist=Tento tým neexistuje. last_org_owner=Nemůžete odstranit posledního uživatele z týmu „vlastníci“. Musí existovat alespoň jeden vlastník pro organizaci. @@ -617,6 +647,30 @@ form.name_reserved=Uživatelské jméno „%s“ je rezervováno. form.name_pattern_not_allowed=Vzor „%s“ není povolen v uživatelském jméně. form.name_chars_not_allowed=Uživatelské jméno „%s“ obsahuje neplatné znaky. +block.block=Blokovat +block.block.user=Zablokovat Uživatele +block.block.org=Blokovat uživatele pro organizaci +block.block.failure=Nepodařilo se zablokovat uživatele: %s +block.unblock=Odblokovat +block.unblock.failure=Nepodařilo se odblokovat uživatele: %s +block.blocked=Zablokovali jste tohoto uživatele. +block.title=Zablokovat Uživatele +block.info=Blokování uživatele brání v interakci s repozitáři, jako je otevírání nebo komentování pull requestů nebo úkolů. Další informace o blokování uživatele. +block.info_1=Zablokování uživatele zabrání následujícím akcím na vašem účtu a repozirářích: +block.info_2=sledují váš účet +block.info_3=pošle vám oznámení pomocí @zmínění vašeho uživatelského jména +block.info_4=pozváním vás jako spolupracovníka do jejich repozitářů +block.info_5=oblíbení, rozštěpení nebo sledování repozitářů +block.info_6=otevření a komentování úkolů nebo pull requestů +block.info_7=reagovat na své komentáře v úkolech nebo pull requestů +block.user_to_block=Uživatel k blokování +block.note=Poznámka +block.note.title=Volitelná poznámka: +block.note.info=Poznámka není pro blokovaného uživatele viditelná. +block.note.edit=Upravit poznámku +block.list=Blokovaní uživatelé +block.list.none=Nemáte blokované žádné uživatele. + [settings] profile=Profil account=Účet @@ -658,7 +712,6 @@ cancel=Zrušit language=Jazyk ui=Motiv vzhledu hidden_comment_types=Skryté typy komentářů -hidden_comment_types_description=Zde zkontrolované typy komentářů nebudou zobrazeny na stránkách problémů. Zaškrtnutí „Štítek“ například odstraní všechny komentáře „ přidal/odstranil