2
0

Compare commits

..

1 Commits

Author SHA1 Message Date
Grzegorz Alibożek
4563148a61 Upgrade Alpine from 3.13 to 3.15 (#18050)
* Upgrade alpine to 3.15

* Add executability test to entrypoint for too old dockers

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Update docker/rootless/usr/local/bin/docker-entrypoint.sh

Co-authored-by: zeripath <art27@cantab.net>
2022-01-19 16:55:17 -05:00
149 changed files with 1076 additions and 2512 deletions

View File

@@ -13,25 +13,12 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
steps:
- name: deps-frontend
pull: always
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.17
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- make node_modules
- name: lint-frontend
image: node:16
@@ -40,17 +27,17 @@ steps:
depends_on: [deps-frontend]
- name: lint-backend
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [deps-backend]
- name: lint-backend-windows
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make golangci-lint vet
@@ -60,9 +47,9 @@ steps:
TAGS: bindata sqlite sqlite_unlock_notify
GOOS: windows
GOARCH: amd64
depends_on: [deps-backend]
- name: lint-backend-gogit
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-backend
@@ -70,7 +57,6 @@ steps:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on: [deps-backend]
- name: checks-frontend
image: node:16
@@ -79,13 +65,11 @@ steps:
depends_on: [deps-frontend]
- name: checks-backend
pull: always
image: golang:1.17
commands:
- make checks-backend
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
depends_on: [lint-backend]
- name: test-frontend
image: node:16
@@ -100,17 +84,14 @@ steps:
depends_on: [test-frontend]
- name: build-backend-no-gcc
image: golang:1.16 # this step is kept as the lowest version of golang that we support
pull: always
image: golang:1.16 # this step is kept as the lowest version of golang that we support
environment:
GO111MODULE: on
GOPROXY: https://goproxy.cn
commands:
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
depends_on: [checks-backend]
- name: build-backend-arm64
image: golang:1.17
@@ -123,10 +104,7 @@ steps:
commands:
- make backend # test cross compile
- rm ./gitea # clean
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
depends_on: [checks-backend]
- name: build-backend-windows
image: golang:1.17
@@ -138,10 +116,7 @@ steps:
TAGS: bindata gogit
commands:
- go build -o gitea_windows
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
depends_on: [checks-backend]
- name: build-backend-386
image: golang:1.17
@@ -152,10 +127,7 @@ steps:
GOARCH: 386
commands:
- go build -o gitea_linux_386 # test if compatible with 32 bit
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
depends_on: [checks-backend]
---
kind: pipeline
@@ -175,28 +147,21 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
services:
- name: mysql
image: mysql:5.7
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test
- name: mysql8
image: mysql:8
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: testgitea
- name: mssql
image: mcr.microsoft.com/mssql/server:latest
pull: always
environment:
ACCEPT_EULA: Y
MSSQL_PID: Standard
@@ -204,17 +169,14 @@ services:
- name: ldap
image: gitea/test-openldap:latest
pull: always
- name: elasticsearch
image: elasticsearch:7.5.0
pull: always
environment:
discovery.type: single-node
image: elasticsearch:7.5.0
- name: minio
image: minio/minio:RELEASE.2021-03-12T00-00-47Z
pull: always
commands:
- minio server /data
environment:
@@ -224,7 +186,6 @@ services:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
@@ -232,28 +193,19 @@ steps:
exclude:
- pull_request
- name: deps-backend
image: golang:1.17
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: tag-pre-condition
image: drone/git
pull: always
image: drone/git
commands:
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
- name: prepare-test-env
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
@@ -263,10 +215,8 @@ steps:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
depends_on:
- prepare-test-env
- name: unit-test
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -279,12 +229,9 @@ steps:
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: unit-test-gogit
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
@@ -295,10 +242,6 @@ steps:
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-mysql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -312,10 +255,8 @@ steps:
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
depends_on: [build]
volumes:
- name: deps
path: /go
depends_on:
- build
- name: test-mysql8
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -328,10 +269,8 @@ steps:
RACE_ENABLED: true
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
depends_on:
- build
- name: test-mssql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -344,10 +283,8 @@ steps:
RACE_ENABLED: true
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
depends_on:
- build
- name: generate-coverage
image: golang:1.17
@@ -356,7 +293,9 @@ steps:
environment:
GOPROXY: https://goproxy.cn
TAGS: bindata
depends_on: [unit-test, test-mysql]
depends_on:
- unit-test
- test-mysql
when:
branch:
- main
@@ -365,14 +304,15 @@ steps:
- pull_request
- name: coverage-codecov
image: woodpeckerci/plugin-codecov:next-alpine
pull: always
image: plugins/codecov
settings:
files:
- coverage.all
token:
from_secret: codecov_token
depends_on: [generate-coverage]
depends_on:
- generate-coverage
when:
branch:
- main
@@ -397,10 +337,6 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
services:
- name: pgsql
pull: default
@@ -416,7 +352,6 @@ services:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
@@ -424,22 +359,13 @@ steps:
exclude:
- pull_request
- name: deps-backend
image: golang:1.17
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
pull: always
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
@@ -449,10 +375,8 @@ steps:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
depends_on:
- prepare-test-env
- name: test-sqlite
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
@@ -465,10 +389,8 @@ steps:
RACE_ENABLED: true
TEST_TAGS: gogit sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
depends_on:
- build
- name: test-pgsql
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
@@ -482,10 +404,8 @@ steps:
TEST_TAGS: gogit
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
depends_on:
- build
---
kind: pipeline
@@ -505,8 +425,8 @@ trigger:
steps:
- name: download
image: jonasfranz/crowdin
pull: always
image: jonasfranz/crowdin
settings:
download: true
export_dir: options/locale/
@@ -517,14 +437,14 @@ steps:
from_secret: crowdin_key
- name: update
pull: default
image: alpine:3.13
pull: always
commands:
- ./build/update-locales.sh
- name: push
image: appleboy/drone-git-push
pull: always
image: appleboy/drone-git-push
settings:
author_email: "teabot@gitea.io"
author_name: GiteaBot
@@ -537,8 +457,8 @@ steps:
from_secret: git_push_ssh_key
- name: upload_translations
image: jonasfranz/crowdin
pull: always
image: jonasfranz/crowdin
settings:
files:
locale_en-US.ini: options/locale/locale_en-US.ini
@@ -568,13 +488,12 @@ trigger:
steps:
- name: download
image: golang:1.17
pull: always
commands:
- timeout -s ABRT 40m make generate-license generate-gitignore
- name: push
image: appleboy/drone-git-push
pull: always
image: appleboy/drone-git-push
settings:
author_email: "teabot@gitea.io"
author_name: GiteaBot
@@ -610,35 +529,15 @@ depends_on:
- testing-amd64
- testing-arm64
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: deps-frontend
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.17
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: static
image: techknowlogick/xgo:go-1.17.x
pull: always
image: techknowlogick/xgo:go-1.17.x
commands:
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
- export PATH=$PATH:$GOPATH/bin
@@ -646,13 +545,10 @@ steps:
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
volumes:
- name: deps
path: /go
- name: gpg-sign
image: plugins/gpgsign:1
pull: always
image: plugins/gpgsign:1
settings:
detach_sign: true
excludes:
@@ -666,12 +562,12 @@ steps:
from_secret: gpgsign_passphrase
- name: release-branch
image: woodpeckerci/plugin-s3:latest
pull: always
image: woodpeckerci/plugin-s3:latest
settings:
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
endpoint: https://storage.gitea.io
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
@@ -692,7 +588,7 @@ steps:
settings:
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
endpoint: https://storage.gitea.io
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
@@ -728,35 +624,16 @@ depends_on:
- testing-arm64
- testing-amd64
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
pull: default
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: deps-frontend
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.17
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: static
image: techknowlogick/xgo:go-1.17.x
pull: always
image: techknowlogick/xgo:go-1.17.x
commands:
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
- export PATH=$PATH:$GOPATH/bin
@@ -764,14 +641,10 @@ steps:
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [fetch-tags]
volumes:
- name: deps
path: /go
- name: gpg-sign
image: plugins/gpgsign:1
pull: always
image: plugins/gpgsign:1
settings:
detach_sign: true
excludes:
@@ -783,15 +656,14 @@ steps:
from_secret: gpgsign_key
GPGSIGN_PASSPHRASE:
from_secret: gpgsign_passphrase
depends_on: [static]
- name: release-tag
image: woodpeckerci/plugin-s3:latest
pull: always
image: woodpeckerci/plugin-s3:latest
settings:
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
endpoint: https://storage.gitea.io
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
@@ -801,18 +673,16 @@ steps:
from_secret: aws_access_key_id
AWS_SECRET_ACCESS_KEY:
from_secret: aws_secret_access_key
depends_on: [gpg-sign]
- name: github
image: plugins/github-release:1
pull: always
image: plugins/github-release:1
settings:
files:
- "dist/release/*"
environment:
GITHUB_TOKEN:
from_secret: github_token
depends_on: [gpg-sign]
---
kind: pipeline
@@ -834,16 +704,16 @@ trigger:
steps:
- name: build-docs
image: plugins/hugo:latest
pull: always
image: plugins/hugo:latest
commands:
- apk add --no-cache make bash curl
- cd docs
- make trans-copy clean build
- name: publish-docs
image: techknowlogick/drone-netlify:latest
pull: always
image: techknowlogick/drone-netlify:latest
settings:
path: docs/public/
site_id: d2260bae-7861-4c02-8646-8f6440b12672
@@ -879,13 +749,12 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
image: techknowlogick/drone-docker:latest
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
@@ -942,13 +811,12 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
image: techknowlogick/drone-docker:latest
settings:
auto_tag: false
tags: dev-linux-amd64
@@ -982,68 +850,6 @@ steps:
exclude:
- pull_request
---
kind: pipeline
name: docker-linux-amd64-release-branch
platform:
os: linux
arch: amd64
depends_on:
- testing-amd64
- testing-arm64
trigger:
ref:
- "refs/heads/release/v*"
event:
exclude:
- cron
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: techknowlogick/drone-docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
@@ -1062,8 +868,8 @@ trigger:
steps:
- name: dryrun
image: techknowlogick/drone-docker:latest
pull: always
image: techknowlogick/drone-docker:latest
settings:
dry_run: true
repo: gitea/gitea
@@ -1100,13 +906,12 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
image: techknowlogick/drone-docker:latest
settings:
auto_tag: true
auto_tag_suffix: linux-arm64
@@ -1163,13 +968,12 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
image: techknowlogick/drone-docker:latest
settings:
auto_tag: false
tags: dev-linux-arm64
@@ -1202,69 +1006,6 @@ steps:
event:
exclude:
- pull_request
---
kind: pipeline
name: docker-linux-arm64-release-branch
platform:
os: linux
arch: arm64
depends_on:
- testing-amd64
- testing-arm64
trigger:
ref:
- "refs/heads/release/v*"
event:
exclude:
- cron
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: techknowlogick/drone-docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
@@ -1276,8 +1017,8 @@ platform:
steps:
- name: manifest-rootless
image: plugins/manifest
pull: always
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
@@ -1322,7 +1063,6 @@ steps:
- name: manifest-rootless
pull: always
image: plugins/manifest
pull: always
settings:
auto_tag: false
ignore_missing: true
@@ -1346,7 +1086,6 @@ steps:
trigger:
ref:
- refs/heads/main
- "refs/heads/release/v*"
event:
exclude:
- cron
@@ -1354,8 +1093,6 @@ trigger:
depends_on:
- docker-linux-amd64-release
- docker-linux-arm64-release
- docker-linux-amd64-release-branch
- docker-linux-arm64-release-branch
---
kind: pipeline
@@ -1389,16 +1126,14 @@ depends_on:
- docker-linux-arm64-release
- docker-linux-amd64-release-version
- docker-linux-arm64-release-version
- docker-linux-amd64-release-branch
- docker-linux-arm64-release-branch
- docker-manifest
- docker-manifest-version
- docs
steps:
- name: discord
image: appleboy/drone-discord:1.2.4
pull: always
image: appleboy/drone-discord:1.2.4
settings:
message: "{{#success build.status}} ✅ Build #{{build.number}} of `{{repo.name}}` succeeded.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{else}} ❌ Build #{{build.number}} of `{{repo.name}}` failed.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{/success}}\n"
webhook_id:

2
.gitignore vendored
View File

@@ -36,8 +36,6 @@ _testmain.go
coverage.all
cpu.out
/modules/migration/bindata.go
/modules/migration/bindata.go.hash
/modules/options/bindata.go
/modules/options/bindata.go.hash
/modules/public/bindata.go

View File

@@ -23,10 +23,6 @@ linters:
run:
timeout: 3m
skip-dirs:
- node_modules
- public
- web_src
linters-settings:
gocritic:

View File

@@ -4,93 +4,13 @@ This changelog goes through all 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.io).
## [1.16.2](https://github.com/go-gitea/gitea/releases/tag/v1.16.2) - 2022-02-24
* ENHANCEMENTS
* Show fullname on issue edits and gpg/ssh signing info (#18828)
* Immediately Hammer if second kill is sent (#18823) (#18826)
* Allow mermaid render error to wrap (#18791)
* BUGFIXES
* Fix ldap user sync missed email in email_address table (#18786) (#18876)
* Update assignees check to include any writing team and change org sidebar (#18680) (#18873)
* Don't report signal: killed errors in serviceRPC (#18850) (#18865)
* Fix bug where certain LDAP settings were reverted (#18859)
* Update go-org to 1.6.0 (#18824) (#18839)
* Fix login with email for ldap users (#18800) (#18836)
* Fix bug for get user by email (#18834)
* Fix panic in EscapeReader (#18820) (#18821)
* Fix ldap loginname (#18789) (#18804)
* Remove redundant call to UpdateRepoStats during migration (#18591) (#18794)
* In disk_channel queues synchronously push to disk on shutdown (#18415) (#18788)
* Fix template bug of LFS lock (#18784) (#18787)
* Attempt to fix the webauthn migration again - part 3 (#18770) (#18771)
* Send mail to issue/pr assignee/reviewer also when OnMention is set (#18707) (#18765)
* Fix a broken link in commits_list_small.tmpl (#18763) (#18764)
* Increase the size of the webauthn_credential credential_id field (#18739) (#18756)
* Prevent dangling GetAttribute calls (#18754) (#18755)
* Fix isempty detection of git repository (#18746) (#18750)
* Fix source code line highlighting on external tracker (#18729) (#18740)
* Prevent double encoding of branch names in delete branch (#18714) (#18738)
* Always set PullRequestWorkInProgressPrefixes in PrepareViewPullInfo (#18713) (#18737)
* Fix forked repositories missed tags (#18719) (#18735)
* Fix release typo (#18728) (#18731)
* Separate the details links of commit-statuses in headers (#18661) (#18730)
* Update object repo with the migrated repository (#18684) (#18726)
* Fix bug for version update hint (#18701) (#18705)
* Fix issue with docker-rootless shimming script (#18690) (#18699)
* Let `MinUnitAccessMode` return correct perm (#18675) (#18689)
* Prevent security failure due to bad APP_ID (#18678) (#18682)
* Restart zero worker if there is still work to do (#18658) (#18672)
* If rendering has failed due to a net.OpError stop rendering (#18642) (#18645)
* TESTING
* Ensure git tag tests and others create test repos in tmpdir (#18447) (#18767)
* BUILD
* Reduce CI go module downloads, add make targets (#18708, #18475, #18443) (#18741)
* MISC
* Put buttons back in org dashboard (#18817) (#18825)
* Various Mermaid improvements (#18776) (#18780)
* C preprocessor colors improvement (#18671) (#18696)
* Fix the missing i18n key for update checker (#18646) (#18665)
## [1.16.1](https://github.com/go-gitea/gitea/releases/tag/v1.16.1) - 2022-02-06
* SECURITY
* Update JS dependencies, fix lint (#18389) (#18540)
* ENHANCEMENTS
* Add dropdown icon to label set template dropdown (#18564) (#18571)
* BUGFIXES
* Comments on migrated issues/prs must link to the comment ID (#18630) (#18637)
* Stop logging an error when notes are not found (#18626) (#18635)
* Ensure that blob-excerpt links work for wiki (#18587) (#18624)
* Only attempt to flush queue if the underlying worker pool is not finished (#18593) (#18620)
* Ensure commit-statuses box is sized correctly in headers (#18538) (#18606)
* Prevent merge messages from being sorted to the top of email chains (#18566) (#18588)
* Prevent panic on prohibited user login with oauth2 (#18562) (#18563)
* Collaborator trust model should trust collaborators (#18539) (#18557)
* Detect conflicts with 3way merge (#18536) (#18537)
* In docker rootless use $GITEA_APP_INI if provided (#18524) (#18535)
* Add `GetUserTeams` (#18499) (#18531)
* Fix review excerpt (#18502) (#18530)
* Fix for AvatarURL database type (#18487) (#18529)
* Use `ImagedProvider` for gplus oauth2 provider (#18504) (#18505)
* Fix OAuth Source Edit Page (#18495) (#18503)
* Use "read" value for General Access (#18496) (#18500)
* Prevent NPE on partial match of compare URL and allow short SHA1 compare URLs (#18472) (#18473)
* BUILD
* Make docker gitea/gitea:v1.16-dev etc refer to the latest build on that branch (#18551) (#18569)
* DOCS
* Update 1.16.0 changelog to set #17846 as breaking (#18533) (#18534)
## [1.16.0](https://github.com/go-gitea/gitea/releases/tag/v1.16.0) - 2022-01-30
## [1.16.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.16.0-rc1) - 2022-01-19
* BREAKING
* Remove golang vendored directory (#18277)
* Paginate releases page & set default page size to 10 (#16857)
* Use shadowing script for docker (#17846)
* Only allow webhook to send requests to allowed hosts (#17482)
* SECURITY
* Disable content sniffing on `PlainTextBytes` (#18359) (#18365)
* Only view milestones from current repo (#18414) (#18417)
* Sanitize user-input on file name (#17666)
* Use `hostmatcher` to replace `matchlist` to improve blocking of bad hosts in Webhooks (#17605)
* FEATURES
@@ -308,16 +228,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* Add left padding for chunk header of split diff view (#13397)
* Allow U2F 2FA without TOTP (#11573)
* BUGFIXES
* GitLab reviews may not have the updated_at field set (#18450) (#18461)
* Fix detection of no commits when the default branch is not master (#18422) (#18423)
* Fix broken oauth2 authentication source edit page (#18412) (#18419)
* Place inline diff comment dialogs on split diff in 4th and 8th columns (#18403) (#18404)
* Fix restore without topic failure (#18387) (#18400)
* Fix commit's time (#18375) (#18392)
* Fix partial cloning a repo (#18373) (#18377)
* Stop trimming preceding and suffixing spaces from editor filenames (#18334)
* Prevent showing webauthn error for every time visiting `/user/settings/security` (#18386)
* Fix mime-type detection for HTTP server (#18370) (#18371)
* Stop trimming preceding and suffixing spaces from editor filenames (#18334)
* Restore propagation of ErrDependenciesLeft (#18325)
* Fix PR comments UI (#18323)
@@ -385,22 +295,10 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* BUILD
* Add lockfile-check (#18285)
* Don't store assets modified time into generated files (#18193)
* Use shadowing script for docker (#17846)
* MISC
* Update JS dependencies (#17611)
## [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

View File

@@ -1,7 +1,5 @@
###################################
#Build stage - temporarily using techknowlogick image until we upgrade to latest official alpine/go image
FROM techknowlogick/go:1.17-alpine3.13 AS build-env
#Build stage
FROM golang:1.17-alpine3.15 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
@@ -25,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
# Begin env-to-ini build
RUN go build contrib/environment-to-ini/environment-to-ini.go
FROM alpine:3.13
FROM alpine:3.15
LABEL maintainer="maintainers@gitea.io"
EXPOSE 22 3000

View File

@@ -1,7 +1,5 @@
###################################
#Build stage - temporarily using techknowlogick image until we upgrade to latest official alpine/go image
FROM techknowlogick/go:1.17-alpine3.13 AS build-env
#Build stage
FROM golang:1.17-alpine3.15 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
@@ -25,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
# Begin env-to-ini build
RUN go build contrib/environment-to-ini/environment-to-ini.go
FROM alpine:3.13
FROM alpine:3.15
LABEL maintainer="maintainers@gitea.io"
EXPOSE 2222 3000

View File

@@ -166,9 +166,6 @@ help:
@echo " - watch-backend watch backend files and continuously rebuild"
@echo " - clean delete backend and integration files"
@echo " - clean-all delete backend, frontend and integration files"
@echo " - deps install dependencies"
@echo " - deps-frontend install frontend dependencies"
@echo " - deps-backend install backend dependencies"
@echo " - lint lint everything"
@echo " - lint-frontend lint frontend files"
@echo " - lint-backend lint backend files"
@@ -399,11 +396,6 @@ test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test
.PHONY: test-sqlite-migration\#%
test-sqlite-migration\#%: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test -test.run $(subst .,/,$*)
generate-ini-mysql:
sed -e 's|{{TEST_MYSQL_HOST}}|${TEST_MYSQL_HOST}|g' \
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
@@ -664,16 +656,6 @@ docs:
fi
cd docs; make trans-copy clean build-offline;
.PHONY: deps
deps: deps-frontend deps-backend
.PHONY: deps-frontend
deps-frontend: node_modules
.PHONY: deps-backend
deps-backend:
$(GO) mod download
node_modules: package-lock.json
npm install --no-save
@touch node_modules

View File

@@ -33,8 +33,10 @@ for i in "$@"; do
done
if [ -z "$APP_INI_SET" ]; then
CONF_ARG=("-c" "${GITEA_APP_INI:-$APP_INI}")
CONF_ARG="-c \"$APP_INI\""
fi
# Provide FHS compliant defaults
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" "${CONF_ARG[@]}" "$@"
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" $CONF_ARG "$@"

View File

@@ -1,4 +1,4 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-rootless
{{#if build.tags}}
tags:
{{#each build.tags}}
@@ -8,12 +8,12 @@ tags:
{{/if}}
manifests:
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-linux-amd64-rootless
platform:
architecture: amd64
os: linux
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64-rootless
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}-linux-arm64-rootless
platform:
architecture: arm64
os: linux

View File

@@ -1,4 +1,4 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}dev{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
@@ -8,13 +8,13 @@ tags:
{{/if}}
manifests:
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{else}}dev-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{else}}dev-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
variant: v8
variant: v8

View File

@@ -1,5 +1,11 @@
#!/bin/sh
# Protect against buggy runc in docker <20.10.6 causing problems in with Alpine >= 3.14
if [ ! -x /bin/sh ]; then
echo "Executable test for /bin/sh failed. Your Docker version is too old to run Alpine 3.14+ and Gitea. You must upgrade Docker.";
exit 1;
fi
if [ "${USER}" != "git" ]; then
# rename user
sed -i -e "s/^git\:/${USER}\:/g" /etc/passwd

View File

@@ -1,5 +1,11 @@
#!/bin/sh
# Protect against buggy runc in docker <20.10.6 causing problems in with Alpine >= 3.14
if [ ! -x /bin/sh ]; then
echo "Executable test for /bin/sh failed. Your Docker version is too old to run Alpine 3.14+ and Gitea. You must upgrade Docker.";
exit 1;
fi
if [ -x /usr/local/bin/docker-setup.sh ]; then
/usr/local/bin/docker-setup.sh || { echo 'docker setup failed' ; exit 1; }
fi

View File

@@ -32,9 +32,11 @@ for i in "$@"; do
done
if [ -z "$APP_INI_SET" ]; then
CONF_ARG=("-c" "${GITEA_APP_INI:-$APP_INI}")
CONF_ARG="-c \"$APP_INI\""
fi
# Provide docker defaults
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" "${CONF_ARG[@]}" "$@"
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" $CONF_ARG "$@"

View File

@@ -18,7 +18,7 @@ params:
description: Git with a cup of tea
author: The Gitea Authors
website: https://docs.gitea.io
version: 1.16.0
version: 1.15.10
minGoVersion: 1.16
goVersion: 1.17
minNodeVersion: 12.17

View File

@@ -32,7 +32,7 @@ image as a service. Since there is no database available, one can be initialized
Create a directory for `data` and `config` then paste the following content into a file named `docker-compose.yml`.
Note that the volume should be owned by the user/group with the UID/GID specified in the config file. By default Gitea in docker will use uid:1000 gid:1000. If needed you can set ownership on those folders with the command: `sudo chown 1000:1000 config/ data/`
If you don't give the volume correct permissions, the container may not start.
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:dev-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev-rootless`)
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:dev-rootless` would be an appropriate tag.
```yaml
version: "2"

View File

@@ -34,7 +34,7 @@ image as a service. Since there is no database available, one can be initialized
Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`.
Note that the volume should be owned by the user/group with the UID/GID specified in the config file.
If you don't give the volume correct permissions, the container may not start.
For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:dev` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev`)
For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:dev` tag.
```yaml
version: "3"

12
go.mod
View File

@@ -30,7 +30,7 @@ require (
github.com/denisenkom/go-mssqldb v0.10.0
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
github.com/duo-labs/webauthn v0.0.0-20220122034320-81aea484c951
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b
github.com/dustin/go-humanize v1.0.0
github.com/editorconfig/editorconfig-core-go/v2 v2.4.2
github.com/emirpasic/gods v1.12.0
@@ -54,7 +54,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.2.0
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-github/v39 v39.2.0
github.com/google/uuid v1.3.0
github.com/google/uuid v1.2.0
github.com/gorilla/feeds v1.1.1
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/sessions v1.2.1
@@ -85,7 +85,7 @@ require (
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/msteinert/pam v0.0.0-20201130170657-e61372126161
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/niklasfasching/go-org v1.6.0
github.com/niklasfasching/go-org v1.5.0
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/oliamb/cutter v0.2.2
github.com/olivere/elastic/v7 v7.0.25
@@ -122,9 +122,9 @@ require (
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1
golang.org/x/text v0.3.7
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect
golang.org/x/tools v0.1.0
@@ -145,6 +145,8 @@ replace github.com/markbates/goth v1.68.0 => github.com/zeripath/goth v1.68.1-0.
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
replace github.com/duo-labs/webauthn => github.com/authelia/webauthn v0.0.0-20211225121951-80d1f2a572e4
replace github.com/satori/go.uuid v1.2.0 => github.com/gofrs/uuid v4.2.0+incompatible
exclude github.com/gofrs/uuid v3.2.0+incompatible

26
go.sum
View File

@@ -131,6 +131,8 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:o
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/authelia/webauthn v0.0.0-20211225121951-80d1f2a572e4 h1:u3eFvgr4A8IjlAokbFt6XY6VdurX7DEYnQMQ4K2yobc=
github.com/authelia/webauthn v0.0.0-20211225121951-80d1f2a572e4/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
@@ -202,7 +204,6 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chaseadamsio/goorgeous v2.0.0+incompatible/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0=
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=
@@ -275,8 +276,6 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/duo-labs/webauthn v0.0.0-20220122034320-81aea484c951 h1:17esZ09oW+29rklBtCVphIguql2u3NxYH2OasFPPZoo=
github.com/duo-labs/webauthn v0.0.0-20220122034320-81aea484c951/go.mod h1:nHy3JdztZWcsjenDeBuE8gn171OAwg12LBN027UP5AE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -492,6 +491,7 @@ 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.7.4 h1:B44qRUFwz/vxPKPISQ1KhvzRi9kZ28RAf6YtjriBZ5k=
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -585,8 +585,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.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=
@@ -913,8 +913,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/niklasfasching/go-org v1.6.0 h1:NCWpmDDNjHNsrei6VmnYXzOiyZUxV8LVU19REGQ8dKA=
github.com/niklasfasching/go-org v1.6.0/go.mod h1:gSHyFcAbr2thIpfljLsP/BB8uwAMyooq6ydIrUDdOCs=
github.com/niklasfasching/go-org v1.5.0 h1:V8IwoSPm/d61bceyWFxxnQLtlvNT+CjiYIhtZLdnMF0=
github.com/niklasfasching/go-org v1.5.0/go.mod h1:sSb8ylwnAG+h8MGFDB3R1D5bxf8wA08REfhjShg3kjA=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
@@ -1033,9 +1033,8 @@ github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -1355,9 +1354,8 @@ golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5o
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1463,13 +1461,11 @@ golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -8,7 +8,6 @@ import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
@@ -263,26 +262,23 @@ func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64)
return func(t *testing.T) {
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge?token=%s",
owner, repo, index, ctx.Token)
req := NewRequestWithJSON(t, http.MethodPost, urlStr, &forms.MergePullRequestForm{
MergeMessageField: "doAPIMergePullRequest Merge",
Do: string(repo_model.MergeStyleMerge),
})
var req *http.Request
var resp *httptest.ResponseRecorder
resp := ctx.Session.MakeRequest(t, req, NoExpectedStatus)
for i := 0; i < 6; i++ {
req = NewRequestWithJSON(t, http.MethodPost, urlStr, &forms.MergePullRequestForm{
MergeMessageField: "doAPIMergePullRequest Merge",
Do: string(repo_model.MergeStyleMerge),
})
resp = ctx.Session.MakeRequest(t, req, NoExpectedStatus)
if resp.Code != http.StatusMethodNotAllowed {
break
}
if resp.Code == http.StatusMethodNotAllowed {
err := api.APIError{}
DecodeJSON(t, resp, &err)
assert.EqualValues(t, "Please try again later", err.Message)
queue.GetManager().FlushAll(context.Background(), 5*time.Second)
<-time.After(1 * time.Second)
req = NewRequestWithJSON(t, http.MethodPost, urlStr, &forms.MergePullRequestForm{
MergeMessageField: "doAPIMergePullRequest Merge",
Do: string(repo_model.MergeStyleMerge),
})
resp = ctx.Session.MakeRequest(t, req, NoExpectedStatus)
}
expected := ctx.ExpectedCode

View File

@@ -123,17 +123,6 @@ func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
}
}
func doPartialGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
return func(t *testing.T) {
assert.NoError(t, git.CloneWithArgs(context.Background(), u.String(), dstLocalPath, allowLFSFilters(), git.CloneRepoOptions{
Filter: "blob:none",
}))
exist, err := util.IsExist(filepath.Join(dstLocalPath, "README.md"))
assert.NoError(t, err)
assert.True(t, exist)
}
}
func doGitCloneFail(u *url.URL) func(*testing.T) {
return func(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "doGitCloneFail")

View File

@@ -69,12 +69,6 @@ func testGit(t *testing.T, u *url.URL) {
t.Run("Clone", doGitClone(dstPath, u))
dstPath2, err := os.MkdirTemp("", httpContext.Reponame)
assert.NoError(t, err)
defer util.RemoveAll(dstPath2)
t.Run("Partial Clone", doPartialGitClone(dstPath2, u))
little, big := standardCommitAndPushTest(t, dstPath)
littleLFS, bigLFS := lfsCommitAndPushTest(t, dstPath)
rawTest(t, &httpContext, little, big, littleLFS, bigLFS)

View File

@@ -83,7 +83,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mssql/data/sessions
[log]
MODE = test,file
ROOT_PATH = {{REPO_TEST_DIR}}mssql-log
ROOT_PATH = mssql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -101,7 +101,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mysql/data/sessions
[log]
MODE = test,file
ROOT_PATH = {{REPO_TEST_DIR}}mysql-log
ROOT_PATH = mysql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -80,7 +80,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mysql8/data/sessions
[log]
MODE = test,file
ROOT_PATH = {{REPO_TEST_DIR}}mysql8-log
ROOT_PATH = mysql8-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -84,7 +84,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-pgsql/data/sessions
[log]
MODE = test,file
ROOT_PATH = {{REPO_TEST_DIR}}pgsql-log
ROOT_PATH = pgsql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -51,6 +51,8 @@ func TestSignin(t *testing.T) {
{username: "wrongUsername", password: "password", message: i18n.Tr("en", "form.username_password_incorrect")},
{username: "user15", password: "wrongPassword", message: i18n.Tr("en", "form.username_password_incorrect")},
{username: "user1@example.com", password: "wrongPassword", message: i18n.Tr("en", "form.username_password_incorrect")},
// test for duplicate email
{username: "user2@example.com", password: "password", message: i18n.Tr("en", "form.email_been_used")},
}
for _, s := range samples {

View File

@@ -79,7 +79,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-sqlite/data/sessions
[log]
MODE = test,file
ROOT_PATH = {{REPO_TEST_DIR}}sqlite-log
ROOT_PATH = sqlite-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -71,7 +71,7 @@ const (
)
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error)) []*SignCommit {
func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isCodeReader func(*user_model.User) (bool, error)) []*SignCommit {
newCommits := make([]*SignCommit, 0, len(oldCommits))
keyMap := map[string]bool{}
@@ -81,7 +81,7 @@ func ParseCommitsWithSignature(oldCommits []*user_model.UserCommit, repoTrustMod
Verification: ParseCommitWithSignature(c.Commit),
}
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isOwnerMemberCollaborator, &keyMap)
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isCodeReader, &keyMap)
newCommits = append(newCommits, signCommit)
}
@@ -455,7 +455,7 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *use
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
// There are several trust models in Gitea
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error), keyMap *map[string]bool) (err error) {
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isCodeReader func(*user_model.User) (bool, error), keyMap *map[string]bool) (err error) {
if !verification.Verified {
return
}
@@ -500,11 +500,11 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
var has bool
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
if !has {
isMember, err = isOwnerMemberCollaborator(verification.SigningUser)
isMember, err = isCodeReader(verification.SigningUser)
(*keyMap)[verification.SigningKey.KeyID] = isMember
}
} else {
isMember, err = isOwnerMemberCollaborator(verification.SigningUser)
isMember, err = isCodeReader(verification.SigningUser)
}
if !isMember {

View File

@@ -43,7 +43,7 @@ type WebAuthnCredential struct {
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX VARCHAR(410)"`
CredentialID string `xorm:"INDEX"`
PublicKey []byte
AttestationType string
AAGUID []byte

View File

@@ -18,7 +18,7 @@ func ConvertFromGitCommit(commits []*git.Commit, repo *repo_model.Repository) []
user_model.ValidateCommitsWithEmails(commits),
repo.GetTrustModel(),
func(user *user_model.User) (bool, error) {
return IsOwnerMemberCollaborator(repo, user.ID)
return IsUserRepoAdmin(repo, user)
},
),
repo,

View File

@@ -134,6 +134,22 @@ func GetMilestoneByRepoIDANDName(repoID int64, name string) (*Milestone, error)
return &mile, nil
}
// GetMilestoneByID returns the milestone via id .
func GetMilestoneByID(id int64) (*Milestone, error) {
return getMilestoneByID(db.GetEngine(db.DefaultContext), id)
}
func getMilestoneByID(e db.Engine, id int64) (*Milestone, error) {
var m Milestone
has, err := e.ID(id).Get(&m)
if err != nil {
return nil, err
} else if !has {
return nil, ErrMilestoneNotExist{ID: id, RepoID: 0}
}
return &m, nil
}
// UpdateMilestone updates information of given milestone.
func UpdateMilestone(m *Milestone, oldIsClosed bool) error {
ctx, committer, err := db.TxContext()

View File

@@ -137,7 +137,6 @@ func QueryIssueContentHistoryEditedCountMap(dbCtx context.Context, issueID int64
type IssueContentListItem struct {
UserID int64
UserName string
UserFullName string
UserAvatarLink string
HistoryID int64
@@ -149,7 +148,7 @@ type IssueContentListItem struct {
// FetchIssueContentHistoryList fetch list
func FetchIssueContentHistoryList(dbCtx context.Context, issueID, commentID int64) ([]*IssueContentListItem, error) {
res := make([]*IssueContentListItem, 0)
err := db.GetEngine(dbCtx).Select("u.id as user_id, u.name as user_name, u.full_name as user_full_name,"+
err := db.GetEngine(dbCtx).Select("u.id as user_id, u.name as user_name,"+
"h.id as history_id, h.edited_unix, h.is_first_created, h.is_deleted").
Table([]string{"issue_content_history", "h"}).
Join("LEFT", []string{"user", "u"}, "h.poster_id = u.id").

View File

@@ -43,9 +43,8 @@ func TestContentHistory(t *testing.T) {
when the refactor of models are done, this test will be possible to be run then with a real `User` model.
*/
type User struct {
ID int64
Name string
FullName string
ID int64
Name string
}
_ = dbEngine.Sync2(&User{})

View File

@@ -52,6 +52,10 @@ func InsertIssues(issues ...*Issue) error {
return err
}
}
err = UpdateRepoStats(ctx, issues[0].RepoID)
if err != nil {
return err
}
return committer.Commit()
}
@@ -143,6 +147,11 @@ func InsertPullRequests(prs ...*PullRequest) error {
return err
}
}
err = UpdateRepoStats(ctx, prs[0].Issue.RepoID)
if err != nil {
return err
}
return committer.Commit()
}

View File

@@ -32,9 +32,8 @@ func TestMigrate_InsertMilestones(t *testing.T) {
unittest.CheckConsistencyFor(t, &Milestone{})
}
func assertCreateIssues(t *testing.T, isPull bool) {
func assertCreateIssues(t *testing.T, reponame string, isPull bool) {
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User)
label := unittest.AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
@@ -64,14 +63,38 @@ func assertCreateIssues(t *testing.T, isPull bool) {
i := unittest.AssertExistsAndLoadBean(t, &Issue{Title: title}).(*Issue)
unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: owner.ID, IssueID: i.ID})
labelModified := unittest.AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
assert.EqualValues(t, label.NumIssues+1, labelModified.NumIssues)
assert.EqualValues(t, label.NumClosedIssues+1, labelModified.NumClosedIssues)
milestoneModified := unittest.AssertExistsAndLoadBean(t, &Milestone{ID: milestone.ID}).(*Milestone)
assert.EqualValues(t, milestone.NumIssues+1, milestoneModified.NumIssues)
assert.EqualValues(t, milestone.NumClosedIssues+1, milestoneModified.NumClosedIssues)
}
func TestMigrate_CreateIssuesIsPullFalse(t *testing.T) {
assertCreateIssues(t, false)
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
assertCreateIssues(t, reponame, false)
repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}).(*repo_model.Repository)
assert.EqualValues(t, repo.NumIssues+1, repoModified.NumIssues)
assert.EqualValues(t, repo.NumClosedIssues+1, repoModified.NumClosedIssues)
}
func TestMigrate_CreateIssuesIsPullTrue(t *testing.T) {
assertCreateIssues(t, true)
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
assertCreateIssues(t, reponame, true)
repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}).(*repo_model.Repository)
assert.EqualValues(t, repo.NumPulls+1, repoModified.NumPulls)
assert.EqualValues(t, repo.NumClosedPulls+1, repoModified.NumClosedPulls)
}
func TestMigrate_InsertIssueComments(t *testing.T) {

View File

@@ -1,12 +0,0 @@
-
id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 2
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 3
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 4
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="

View File

@@ -1,21 +0,0 @@
-
id: 1
name: "u2fkey-correctly-migrated"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 2
name: "u2fkey-incorrectly-migrated"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 3
name: "u2fkey-deleted"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 4
name: "u2fkey-wrong-user-id"
user_id: 2
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0

View File

@@ -1,30 +0,0 @@
-
id: 1
lower_name: "u2fkey-correctly-migrated"
name: "u2fkey-correctly-migrated"
user_id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false
-
id: 2
lower_name: "u2fkey-incorrectly-migrated"
name: "u2fkey-incorrectly-migrated"
user_id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8A"
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false
-
id: 4
lower_name: "u2fkey-wrong-user-id"
name: "u2fkey-wrong-user-id"
user_id: 1
credential_id: "THIS SHOULD CHANGE"
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false

View File

@@ -367,13 +367,9 @@ var migrations = []Migration{
// v206 -> v207
NewMigration("Add authorize column to team_unit table", addAuthorizeColForTeamUnit),
// v207 -> v208
NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", addWebAuthnCred),
NewMigration("Add webauthn table and migrate u2f data to webauthn", addWebAuthnCred),
// v208 -> v209
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", useBase32HexForCredIDInWebAuthnCredential),
// v209 -> v210
NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", increaseCredentialIDTo410),
// v210 -> v211
NewMigration("v208 was completely broken - remigrate", remigrateU2FCredentials),
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive", useBase32HexForCredIDInWebAuthnCredential),
}
// GetCurrentDBVersion returns the current db version
@@ -454,12 +450,9 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
// Downgrading Gitea's database version not supported
if int(v-minDBVersion) > len(migrations) {
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gita, you can not use the newer database for this old Gitea release (%d).", v, minDBVersion+len(migrations))
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
if !setting.IsProd {
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations))
}
_, _ = fmt.Fprintln(os.Stderr, msg)
msg := fmt.Sprintf("Downgrading database version from '%d' to '%d' is not supported and may result in loss of data integrity.\nIf you really know what you're doing, execute `UPDATE version SET version=%d WHERE id=1;`\n",
v, minDBVersion+len(migrations), minDBVersion+len(migrations))
fmt.Fprint(os.Stderr, msg)
log.Fatal(msg)
return nil
}

View File

@@ -5,11 +5,87 @@
package migrations
import (
"crypto/elliptic"
"encoding/base64"
"strings"
"code.gitea.io/gitea/modules/timeutil"
"github.com/tstranex/u2f"
"xorm.io/xorm"
)
func addWebAuthnCred(x *xorm.Engine) error {
// NO-OP Don't migrate here - let v210 do this.
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX"`
PublicKey []byte
AttestationType string
AAGUID []byte
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
// Now migrate the old u2f registrations to the new format
type u2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
var start int
regs := make([]*u2fRegistration, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
for _, reg := range regs {
parsed := new(u2f.Registration)
err = parsed.UnmarshalBinary(reg.Raw)
if err != nil {
continue
}
c := &webauthnCredential{
ID: reg.ID,
Name: reg.Name,
LowerName: strings.ToLower(reg.Name),
UserID: reg.UserID,
CredentialID: base64.RawStdEncoding.EncodeToString(parsed.KeyHandle),
PublicKey: elliptic.Marshal(elliptic.P256(), parsed.PubKey.X, parsed.PubKey.Y),
AttestationType: "fido-u2f",
AAGUID: []byte{},
SignCount: reg.Counter,
}
_, err := x.Insert(c)
if err != nil {
return err
}
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
return nil
}

View File

@@ -5,10 +5,47 @@
package migrations
import (
"encoding/base32"
"encoding/base64"
"xorm.io/xorm"
)
func useBase32HexForCredIDInWebAuthnCredential(x *xorm.Engine) error {
// noop
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
CredentialID string `xorm:"INDEX"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
var start int
regs := make([]*webauthnCredential, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
for _, reg := range regs {
credID, _ := base64.RawStdEncoding.DecodeString(reg.CredentialID)
reg.CredentialID = base32.HexEncoding.EncodeToString(credID)
_, err := x.Update(reg)
if err != nil {
return err
}
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
return nil
}

View File

@@ -1,17 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"xorm.io/xorm"
)
func increaseCredentialIDTo410(x *xorm.Engine) error {
// no-op
// V208 is badly broken
// So now we have to no-op again.
return nil
}

View File

@@ -1,172 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"crypto/elliptic"
"encoding/base32"
"fmt"
"strings"
"code.gitea.io/gitea/modules/timeutil"
"github.com/tstranex/u2f"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
// v208 migration was completely broken
func remigrateU2FCredentials(x *xorm.Engine) error {
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
PublicKey []byte
AttestationType string
AAGUID []byte
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
switch x.Dialect().URI().DBType {
case schemas.MYSQL:
_, err := x.Exec("ALTER TABLE webauthn_credential MODIFY COLUMN credential_id VARCHAR(410)")
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.
sess := x.NewSession()
if err := sess.Begin(); err != nil {
_ = sess.Close()
return err
}
if err := recreateTable(sess, new(webauthnCredential)); err != nil {
_ = sess.Close()
return err
}
if err := sess.Commit(); err != nil {
_ = sess.Close()
return err
}
if err := sess.Close(); err != nil {
return err
}
case schemas.POSTGRES:
_, err := x.Exec("ALTER TABLE webauthn_credential ALTER COLUMN credential_id TYPE VARCHAR(410)")
if err != nil {
return err
}
default:
// SQLite doesn't support ALTER COLUMN, and it already makes String _TEXT_ by default so no migration needed
// nor is there any need to re-migrate
}
exist, err := x.IsTableExist("u2f_registration")
if err != nil {
return err
}
if !exist {
return nil
}
// Now migrate the old u2f registrations to the new format
type u2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
var start int
regs := make([]*u2fRegistration, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
err = func() error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return fmt.Errorf("unable to allow start session. Error: %w", err)
}
if x.Dialect().URI().DBType == schemas.MSSQL {
if _, err := sess.Exec("SET IDENTITY_INSERT `webauthn_credential` ON"); err != nil {
return fmt.Errorf("unable to allow identity insert on webauthn_credential. Error: %w", err)
}
}
for _, reg := range regs {
parsed := new(u2f.Registration)
err = parsed.UnmarshalBinary(reg.Raw)
if err != nil {
continue
}
remigrated := &webauthnCredential{
ID: reg.ID,
Name: reg.Name,
LowerName: strings.ToLower(reg.Name),
UserID: reg.UserID,
CredentialID: base32.HexEncoding.EncodeToString(parsed.KeyHandle),
PublicKey: elliptic.Marshal(elliptic.P256(), parsed.PubKey.X, parsed.PubKey.Y),
AttestationType: "fido-u2f",
AAGUID: []byte{},
SignCount: reg.Counter,
UpdatedUnix: reg.UpdatedUnix,
CreatedUnix: reg.CreatedUnix,
}
has, err := sess.ID(reg.ID).Where("id = ?", reg.ID).Get(new(webauthnCredential))
if err != nil {
return fmt.Errorf("unable to get webauthn_credential[%d]. Error: %w", reg.ID, err)
}
if !has {
_, err = sess.Insert(remigrated)
if err != nil {
return fmt.Errorf("unable to (re)insert webauthn_credential[%d]. Error: %w", reg.ID, err)
}
continue
}
_, err = sess.ID(remigrated.ID).AllCols().Update(remigrated)
if err != nil {
return fmt.Errorf("unable to update webauthn_credential[%d]. Error: %w", reg.ID, err)
}
}
return sess.Commit()
}()
if err != nil {
return err
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
return nil
}

View File

@@ -1,74 +0,0 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"testing"
"code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert"
"xorm.io/xorm/schemas"
)
func Test_remigrateU2FCredentials(t *testing.T) {
// Create webauthnCredential table
type WebauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
PublicKey []byte
AttestationType string
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
}
// Now migrate the old u2f registrations to the new format
type U2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
type ExpectedWebauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
}
// Prepare and load the testing database
x, deferable := prepareTestEnv(t, 0, new(WebauthnCredential), new(U2fRegistration), new(ExpectedWebauthnCredential))
if x == nil || t.Failed() {
defer deferable()
return
}
defer deferable()
if x.Dialect().URI().DBType == schemas.SQLITE {
return
}
// Run the migration
if err := remigrateU2FCredentials(x); err != nil {
assert.NoError(t, err)
return
}
expected := []ExpectedWebauthnCredential{}
if err := x.Table("expected_webauthn_credential").Asc("id").Find(&expected); !assert.NoError(t, err) {
return
}
got := []ExpectedWebauthnCredential{}
if err := x.Table("webauthn_credential").Select("id, credential_id").Asc("id").Find(&got); !assert.NoError(t, err) {
return
}
assert.EqualValues(t, expected, got)
}

View File

@@ -49,67 +49,22 @@ func init() {
db.RegisterModel(new(TeamUnit))
}
// SearchOrgTeamOptions holds the search options
type SearchOrgTeamOptions struct {
// SearchTeamOptions holds the search options
type SearchTeamOptions struct {
db.ListOptions
UserID int64
Keyword string
OrgID int64
IncludeDesc bool
}
// GetUserTeamOptions holds the search options.
type GetUserTeamOptions struct {
db.ListOptions
UserID int64
}
// SearchMembersOptions holds the search options
type SearchMembersOptions struct {
db.ListOptions
}
// GetUserTeams search for org teams. Caller is responsible to check permissions.
func GetUserTeams(opts *GetUserTeamOptions) ([]*Team, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}
if opts.PageSize == 0 {
// Default limit
opts.PageSize = 10
}
sess := db.GetEngine(db.DefaultContext)
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id").
And("team_user.uid=?", opts.UserID)
count, err := sess.
Count(new(Team))
if err != nil {
return nil, 0, err
}
if opts.PageSize == -1 {
opts.PageSize = int(count)
} else {
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id").
And("team_user.uid=?", opts.UserID)
teams := make([]*Team, 0, opts.PageSize)
if err = sess.
OrderBy("lower_name").
Find(&teams); err != nil {
return nil, 0, err
}
return teams, count, nil
}
// SearchOrgTeams search for org teams. Caller is responsible to check permissions.
func SearchOrgTeams(opts *SearchOrgTeamOptions) ([]*Team, int64, error) {
// SearchTeam search for teams. Caller is responsible to check permissions.
func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}
@@ -241,7 +196,7 @@ func (t *Team) getRepositories(e db.Engine) error {
}
// GetRepositories returns paginated repositories in team of organization.
func (t *Team) GetRepositories(opts *SearchOrgTeamOptions) error {
func (t *Team) GetRepositories(opts *SearchTeamOptions) error {
if opts.Page == 0 {
return t.getRepositories(db.GetEngine(db.DefaultContext))
}
@@ -761,7 +716,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
// DeleteTeam deletes given team.
// It's caller's responsibility to assign organization ID.
func DeleteTeam(t *Team) error {
if err := t.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
if err := t.GetRepositories(&SearchTeamOptions{}); err != nil {
return err
}
@@ -903,7 +858,7 @@ func AddTeamMember(team *Team, userID int64) error {
}
// Get team and its repositories.
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
if err := team.GetRepositories(&SearchTeamOptions{}); err != nil {
return err
}

View File

@@ -46,7 +46,7 @@ func TestTeam_GetRepositories(t *testing.T) {
test := func(teamID int64) {
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
assert.NoError(t, team.GetRepositories(&SearchOrgTeamOptions{}))
assert.NoError(t, team.GetRepositories(&SearchTeamOptions{}))
assert.Len(t, team.Repos, team.NumRepos)
for _, repo := range team.Repos {
unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID})
@@ -292,7 +292,7 @@ func TestGetTeamMembers(t *testing.T) {
func TestGetUserTeams(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
test := func(userID int64) {
teams, _, err := GetUserTeams(&GetUserTeamOptions{UserID: userID})
teams, _, err := SearchTeam(&SearchTeamOptions{UserID: userID})
assert.NoError(t, err)
for _, team := range teams {
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})

View File

@@ -150,56 +150,27 @@ func getRepoAssignees(ctx context.Context, repo *repo_model.Repository) (_ []*us
}
e := db.GetEngine(ctx)
userIDs := make([]int64, 0, 10)
if err = e.Table("access").
accesses := make([]*Access, 0, 10)
if err = e.
Where("repo_id = ? AND mode >= ?", repo.ID, perm.AccessModeWrite).
Select("id").
Find(&userIDs); err != nil {
Find(&accesses); err != nil {
return nil, err
}
additionalUserIDs := make([]int64, 0, 10)
if err = e.Table("team_user").
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
Where("`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?", repo.ID, perm.AccessModeWrite).
Distinct("`team_user`.uid").
Select("`team_user`.uid").
Find(&additionalUserIDs); err != nil {
return nil, err
}
uidMap := map[int64]bool{}
i := 0
for _, uid := range userIDs {
if uidMap[uid] {
continue
}
uidMap[uid] = true
userIDs[i] = uid
i++
}
userIDs = userIDs[:i]
userIDs = append(userIDs, additionalUserIDs...)
for _, uid := range additionalUserIDs {
if uidMap[uid] {
continue
}
userIDs[i] = uid
i++
}
userIDs = userIDs[:i]
// Leave a seat for owner itself to append later, but if owner is an organization
// and just waste 1 unit is cheaper than re-allocate memory once.
users := make([]*user_model.User, 0, len(userIDs)+1)
if len(userIDs) > 0 {
users := make([]*user_model.User, 0, len(accesses)+1)
if len(accesses) > 0 {
userIDs := make([]int64, len(accesses))
for i := 0; i < len(accesses); i++ {
userIDs[i] = accesses[i].UserID
}
if err = e.In("id", userIDs).Find(&users); err != nil {
return nil, err
}
}
if !repo.Owner.IsOrganization() && !uidMap[repo.OwnerID] {
if !repo.Owner.IsOrganization() {
users = append(users, repo.Owner)
}

View File

@@ -328,12 +328,7 @@ func AllUnitKeyNames() []string {
// MinUnitAccessMode returns the minial permission of the permission map
func MinUnitAccessMode(unitsMap map[Type]perm.AccessMode) perm.AccessMode {
res := perm.AccessModeNone
for t, mode := range unitsMap {
// Don't allow `TypeExternal{Tracker,Wiki}` to influence this as they can only be set to READ perms.
if t == TypeExternalTracker || t == TypeExternalWiki {
continue
}
for _, mode := range unitsMap {
// get the minial permission great than AccessModeNone except all are AccessModeNone
if mode > perm.AccessModeNone && (res == perm.AccessModeNone || mode < res) {
res = mode

View File

@@ -60,7 +60,7 @@ type ExternalLoginUser struct {
LastName string
NickName string
Description string
AvatarURL string `xorm:"TEXT"`
AvatarURL string
Location string
AccessToken string `xorm:"TEXT"`
AccessTokenSecret string `xorm:"TEXT"`

View File

@@ -827,9 +827,8 @@ func validateUser(u *User) error {
return ValidateEmail(u.Email)
}
func updateUser(ctx context.Context, u *User, changePrimaryEmail bool, cols ...string) error {
err := validateUser(u)
if err != nil {
func updateUser(ctx context.Context, u *User, changePrimaryEmail bool) error {
if err := validateUser(u); err != nil {
return err
}
@@ -861,35 +860,15 @@ func updateUser(ctx context.Context, u *User, changePrimaryEmail bool, cols ...s
}); err != nil {
return err
}
} else { // check if primary email in email_address table
primaryEmailExist, err := e.Where("uid=? AND is_primary=?", u.ID, true).Exist(&EmailAddress{})
if err != nil {
return err
}
if !primaryEmailExist {
if _, err = e.Insert(&EmailAddress{
Email: u.Email,
UID: u.ID,
IsActivated: true,
IsPrimary: true,
}); err != nil {
return err
}
}
}
if len(cols) == 0 {
_, err = e.ID(u.ID).AllCols().Update(u)
} else {
_, err = e.ID(u.ID).Cols(cols...).Update(u)
}
_, err := e.ID(u.ID).AllCols().Update(u)
return err
}
// UpdateUser updates user's information.
func UpdateUser(u *User, emailChanged bool, cols ...string) error {
return updateUser(db.DefaultContext, u, emailChanged, cols...)
func UpdateUser(u *User, emailChanged bool) error {
return updateUser(db.DefaultContext, u, emailChanged)
}
// UpdateUserCols update user according special columns
@@ -1125,9 +1104,19 @@ func GetUserByEmailContext(ctx context.Context, email string) (*User, error) {
}
email = strings.ToLower(email)
// First try to find the user by primary email
user := &User{Email: email}
has, err := db.GetEngine(ctx).Get(user)
if err != nil {
return nil, err
}
if has {
return user, nil
}
// Otherwise, check in alternative list for activated email addresses
emailAddress := &EmailAddress{LowerEmail: email, IsActivated: true}
has, err := db.GetEngine(ctx).Get(emailAddress)
emailAddress := &EmailAddress{Email: email, IsActivated: true}
has, err = db.GetEngine(ctx).Get(emailAddress)
if err != nil {
return nil, err
}

View File

@@ -235,20 +235,6 @@ func TestCreateUserInvalidEmail(t *testing.T) {
assert.True(t, IsErrEmailInvalid(err))
}
func TestCreateUserEmailAlreadyUsed(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
// add new user with user2's email
user.Name = "testuser"
user.LowerName = strings.ToLower(user.Name)
user.ID = 0
err := CreateUser(user)
assert.Error(t, err)
assert.True(t, IsErrEmailAlreadyUsed(err))
}
func TestGetUserIDsByNames(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

View File

@@ -74,7 +74,6 @@ readingloop:
for err == nil {
n, err = text.Read(buf[readStart:])
bs := buf[:n+readStart]
n = len(bs)
i := 0
for i < len(bs) {

View File

@@ -200,12 +200,3 @@ func TestEscapeControlReader(t *testing.T) {
})
}
}
func TestEscapeControlReader_panic(t *testing.T) {
bs := make([]byte, 0, 20479)
bs = append(bs, 'A')
for i := 0; i < 6826; i++ {
bs = append(bs, []byte("—")...)
}
_, _ = EscapeControlBytes(bs)
}

View File

@@ -9,11 +9,9 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"html"
"html/template"
"io"
"net"
"net/http"
"net/url"
"path"
@@ -266,12 +264,6 @@ func (ctx *Context) ServerError(logMsg string, logErr error) {
func (ctx *Context) serverErrorInternal(logMsg string, logErr error) {
if logErr != nil {
log.ErrorWithSkip(2, "%s: %v", logMsg, logErr)
if errors.Is(logErr, &net.OpError{}) {
// This is an error within the underlying connection
// and further rendering will not work so just return
return
}
if !setting.IsProd {
ctx.Data["ErrorMsg"] = logErr
}
@@ -299,7 +291,6 @@ func (ctx *Context) PlainTextBytes(status int, bs []byte) {
}
ctx.Resp.WriteHeader(status)
ctx.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8")
ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff")
if _, err := ctx.Resp.Write(bs); err != nil {
log.Error("Write bytes failed: %v", err)
}

View File

@@ -16,25 +16,20 @@ import (
"github.com/stretchr/testify/assert"
)
const (
testReposDir = "tests/repos/"
)
const testReposDir = "tests/repos/"
const benchmarkReposDir = "benchmark/repos/"
func cloneRepo(url, name string) (string, error) {
repoDir, err := os.MkdirTemp("", name)
if err != nil {
return "", err
func cloneRepo(url, dir, name string) (string, error) {
repoDir := filepath.Join(dir, name)
if _, err := os.Stat(repoDir); err == nil {
return repoDir, nil
}
if err := Clone(url, repoDir, CloneRepoOptions{
return repoDir, Clone(url, repoDir, CloneRepoOptions{
Mirror: false,
Bare: false,
Quiet: true,
Timeout: 5 * time.Minute,
}); err != nil {
_ = util.RemoveAll(repoDir)
return "", err
}
return repoDir, nil
})
}
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
@@ -64,35 +59,20 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
for _, testCase := range testCases {
commit, err := repo1.GetCommit(testCase.CommitID)
if err != nil {
assert.NoError(t, err, "Unable to get commit: %s from testcase due to error: %v", testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
assert.NoError(t, err)
assert.NotNil(t, commit)
assert.NotNil(t, commit.Tree)
assert.NotNil(t, commit.Tree.repo)
tree, err := commit.Tree.SubTree(testCase.Path)
if err != nil {
assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NoError(t, err)
entries, err := tree.ListEntries()
if err != nil {
assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
// FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain.
commitsInfo, treeCommit, err := entries.GetCommitsInfo(context.TODO(), commit, testCase.Path, nil)
assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
assert.NoError(t, err)
commitsInfo, treeCommit, err := entries.GetCommitsInfo(context.Background(), commit, testCase.Path, nil)
assert.NoError(t, err)
if err != nil {
t.FailNow()
}
@@ -118,52 +98,40 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
testGetCommitsInfo(t, bareRepo1)
clonedPath, err := cloneRepo(bareRepo1Path, "repo1_TestEntries_GetCommitsInfo")
if err != nil {
assert.NoError(t, err)
}
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestEntries_GetCommitsInfo")
assert.NoError(t, err)
defer util.RemoveAll(clonedPath)
clonedRepo1, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
}
assert.NoError(t, err)
defer clonedRepo1.Close()
testGetCommitsInfo(t, clonedRepo1)
}
func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
type benchmarkType struct {
benchmarks := []struct {
url string
name string
}
benchmarks := []benchmarkType{
}{
{url: "https://github.com/go-gitea/gitea.git", name: "gitea"},
{url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"},
{url: "https://github.com/moby/moby.git", name: "moby"},
{url: "https://github.com/golang/go.git", name: "go"},
{url: "https://github.com/torvalds/linux.git", name: "linux"},
}
doBenchmark := func(benchmark benchmarkType) {
for _, benchmark := range benchmarks {
var commit *Commit
var entries Entries
var repo *Repository
repoPath, err := cloneRepo(benchmark.url, benchmark.name)
if err != nil {
if repoPath, err := cloneRepo(benchmark.url, benchmarkReposDir, benchmark.name); err != nil {
b.Fatal(err)
}
defer util.RemoveAll(repoPath)
if repo, err = OpenRepository(repoPath); err != nil {
} else if repo, err = OpenRepository(repoPath); err != nil {
b.Fatal(err)
}
defer repo.Close()
if commit, err = repo.GetBranchCommit("master"); err != nil {
} else if commit, err = repo.GetBranchCommit("master"); err != nil {
repo.Close()
b.Fatal(err)
} else if entries, err = commit.Tree.ListEntries(); err != nil {
repo.Close()
b.Fatal(err)
}
entries.Sort()
@@ -176,9 +144,6 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
}
}
})
}
for _, benchmark := range benchmarks {
doBenchmark(benchmark)
repo.Close()
}
}

View File

@@ -59,28 +59,27 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
ctx, _, finished := process.GetManager().AddContext(repo.Ctx, fmt.Sprintf("GetRawDiffForFile: [repo_path: %s]", repo.Path))
defer finished()
cmd := exec.CommandContext(ctx, GitExecutable, GlobalCommandArgs...)
var cmd *exec.Cmd
switch diffType {
case RawDiffNormal:
if len(startCommit) != 0 {
cmd.Args = append(cmd.Args, append([]string{"diff", "-M", startCommit, endCommit}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"diff", "-M", startCommit, endCommit}, fileArgs...)...)
} else if commit.ParentCount() == 0 {
cmd.Args = append(cmd.Args, append([]string{"show", endCommit}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"show", endCommit}, fileArgs...)...)
} else {
c, _ := commit.Parent(0)
cmd.Args = append(cmd.Args, append([]string{"diff", "-M", c.ID.String(), endCommit}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"diff", "-M", c.ID.String(), endCommit}, fileArgs...)...)
}
case RawDiffPatch:
if len(startCommit) != 0 {
query := fmt.Sprintf("%s...%s", endCommit, startCommit)
cmd.Args = append(cmd.Args, append([]string{"format-patch", "--no-signature", "--stdout", "--root", query}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", query}, fileArgs...)...)
} else if commit.ParentCount() == 0 {
cmd.Args = append(cmd.Args, append([]string{"format-patch", "--no-signature", "--stdout", "--root", endCommit}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", endCommit}, fileArgs...)...)
} else {
c, _ := commit.Parent(0)
query := fmt.Sprintf("%s...%s", endCommit, c.ID.String())
cmd.Args = append(cmd.Args, append([]string{"format-patch", "--no-signature", "--stdout", query}, fileArgs...)...)
cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", query}, fileArgs...)...)
}
default:
return fmt.Errorf("invalid diffType: %s", diffType)

View File

@@ -22,9 +22,6 @@ func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note)
log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path)
notes, err := repo.GetCommit(NotesRef)
if err != nil {
if IsErrNotExist(err) {
return err
}
log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err)
return err
}

View File

@@ -21,9 +21,6 @@ func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note)
log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path)
notes, err := repo.GetCommit(NotesRef)
if err != nil {
if IsErrNotExist(err) {
return err
}
log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err)
return err
}

View File

@@ -79,20 +79,16 @@ func InitRepository(repoPath string, bare bool) error {
// IsEmpty Check if repository is empty.
func (repo *Repository) IsEmpty() (bool, error) {
var errbuf, output strings.Builder
if err := NewCommandContext(repo.Ctx, "show-ref", "--head", "^HEAD$").RunWithContext(&RunContext{
Timeout: -1,
Dir: repo.Path,
Stdout: &output,
Stderr: &errbuf,
}); err != nil {
if err.Error() == "exit status 1" && errbuf.String() == "" {
var errbuf strings.Builder
if err := NewCommand("log", "-1").RunInDirPipeline(repo.Path, nil, &errbuf); err != nil {
if strings.Contains(errbuf.String(), "fatal: bad default revision 'HEAD'") ||
strings.Contains(errbuf.String(), "fatal: your current branch 'master' does not have any commits yet") {
return true, nil
}
return true, fmt.Errorf("check empty: %v - %s", err, errbuf.String())
}
return strings.TrimSpace(output.String()) == "", nil
return false, nil
}
// CloneRepoOptions options when clone a repository
@@ -105,7 +101,6 @@ type CloneRepoOptions struct {
Shared bool
NoCheckout bool
Depth int
Filter string
}
// Clone clones original repository to target path.
@@ -146,9 +141,7 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
if opts.Depth > 0 {
cmd.AddArguments("--depth", strconv.Itoa(opts.Depth))
}
if opts.Filter != "" {
cmd.AddArguments("--filter", opts.Filter)
}
if len(opts.Branch) > 0 {
cmd.AddArguments("-b", opts.Branch)
}

View File

@@ -87,7 +87,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
return nil, fmt.Errorf("wrong number of fields in return from check-attr")
}
name2attribute2info := make(map[string]map[string]string)
var name2attribute2info = make(map[string]map[string]string)
for i := 0; i < (len(fields) / 3); i++ {
filename := string(fields[3*i])
@@ -179,21 +179,17 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
// Run run cmd
func (c *CheckAttributeReader) Run() error {
defer func() {
_ = c.stdinReader.Close()
_ = c.stdOut.Close()
_ = c.Close()
}()
stdErr := new(bytes.Buffer)
err := c.cmd.RunInDirTimeoutEnvFullPipelineFunc(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader, func(_ context.Context, _ context.CancelFunc) error {
select {
case <-c.running:
default:
close(c.running)
}
close(c.running)
return nil
})
if err != nil && c.ctx.Err() != nil && err.Error() != "signal: killed" {
return fmt.Errorf("failed to run attr-check. Error: %w\nStderr: %s", err, stdErr.String())
}
return nil
}
@@ -233,8 +229,10 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
// Close close pip after use
func (c *CheckAttributeReader) Close() error {
c.cancel()
err := c.stdinWriter.Close()
_ = c.stdinReader.Close()
_ = c.stdOut.Close()
c.cancel()
select {
case <-c.running:
default:

View File

@@ -17,33 +17,17 @@ import (
func TestGetFormatPatch(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, "repo1_TestGetFormatPatch")
if err != nil {
assert.NoError(t, err)
return
}
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestGetFormatPatch")
defer util.RemoveAll(clonedPath)
assert.NoError(t, err)
repo, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
defer repo.Close()
assert.NoError(t, err)
rd := &bytes.Buffer{}
err = repo.GetPatch("8d92fc95^", "8d92fc95", rd)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
patchb, err := io.ReadAll(rd)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
patch := string(patchb)
assert.Regexp(t, "^From 8d92fc95", patch)
assert.Contains(t, patch, "Subject: [PATCH] Add file2.txt")
@@ -53,25 +37,17 @@ func TestReadPatch(t *testing.T) {
// Ensure we can read the patch files
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
if err != nil {
assert.NoError(t, err)
return
}
defer repo.Close()
assert.NoError(t, err)
// This patch doesn't exist
noFile, err := repo.ReadPatchCommit(0)
assert.Error(t, err)
// This patch is an empty one (sometimes it's a 404)
noCommit, err := repo.ReadPatchCommit(1)
assert.Error(t, err)
// This patch is legit and should return a commit
oldCommit, err := repo.ReadPatchCommit(2)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.Empty(t, noFile)
assert.Empty(t, noCommit)
@@ -82,45 +58,23 @@ func TestReadPatch(t *testing.T) {
func TestReadWritePullHead(t *testing.T) {
// Ensure we can write SHA1 head corresponding to PR and open them
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
// As we are writing we should clone the repository first
clonedPath, err := cloneRepo(bareRepo1Path, "TestReadWritePullHead")
if err != nil {
assert.NoError(t, err)
return
}
defer util.RemoveAll(clonedPath)
repo, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
repo, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err)
defer repo.Close()
// Try to open non-existing Pull
_, err = repo.GetRefCommitID(PullPrefix + "0/head")
assert.Error(t, err)
// Write a fake sha1 with only 40 zeros
newCommit := "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"
err = repo.SetReference(PullPrefix+"1/head", newCommit)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
// Remove file after the test
defer func() {
_ = repo.RemoveReference(PullPrefix + "1/head")
}()
// Read the file created
headContents, err := repo.GetRefCommitID(PullPrefix + "1/head")
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.Len(t, string(headContents), 40)
assert.True(t, string(headContents) == newCommit)
// Remove file after the test
err = repo.RemoveReference(PullPrefix + "1/head")
assert.NoError(t, err)
}

View File

@@ -88,10 +88,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
}
}()
}
defer func() {
_ = checker.Close()
cancel()
}()
defer cancel()
}
}

View File

@@ -16,17 +16,11 @@ import (
func TestRepository_GetTags(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
defer bareRepo1.Close()
tags, total, err := bareRepo1.GetTagInfos(0, 0)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.Len(t, tags, 1)
assert.Equal(t, len(tags), total)
assert.EqualValues(t, "test", tags[0].Name)
@@ -37,75 +31,40 @@ func TestRepository_GetTags(t *testing.T) {
func TestRepository_GetTag(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, "TestRepository_GetTag")
if err != nil {
assert.NoError(t, err)
return
}
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag")
assert.NoError(t, err)
defer util.RemoveAll(clonedPath)
bareRepo1, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
defer bareRepo1.Close()
// LIGHTWEIGHT TAGS
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
lTagName := "lightweightTag"
bareRepo1.CreateTag(lTagName, lTagCommitID)
// Create the lightweight tag
err = bareRepo1.CreateTag(lTagName, lTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the lightweight tag: %s for ID: %s. Error: %v", lTagName, lTagCommitID, err)
return
}
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
aTagName := "annotatedTag"
aTagMessage := "my annotated message \n - test two line"
bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
aTagID, _ := bareRepo1.GetTagID(aTagName)
// and try to get the Tag for lightweight tag
lTag, err := bareRepo1.GetTag(lTagName)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.NotNil(t, lTag)
if lTag == nil {
assert.NotNil(t, lTag)
assert.FailNow(t, "nil lTag: %s", lTagName)
return
}
assert.EqualValues(t, lTagName, lTag.Name)
assert.EqualValues(t, lTagCommitID, lTag.ID.String())
assert.EqualValues(t, lTagCommitID, lTag.Object.String())
assert.EqualValues(t, "commit", lTag.Type)
// ANNOTATED TAGS
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
aTagName := "annotatedTag"
aTagMessage := "my annotated message \n - test two line"
// Create the annotated tag
err = bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the annotated tag: %s for ID: %s. Error: %v", aTagName, aTagCommitID, err)
return
}
// Now try to get the tag for the annotated Tag
aTagID, err := bareRepo1.GetTagID(aTagName)
if err != nil {
assert.NoError(t, err)
return
}
aTag, err := bareRepo1.GetTag(aTagName)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.NotNil(t, aTag)
if aTag == nil {
assert.NotNil(t, aTag)
assert.FailNow(t, "nil aTag: %s", aTagName)
return
}
assert.EqualValues(t, aTagName, aTag.Name)
assert.EqualValues(t, aTagID, aTag.ID.String())
@@ -113,47 +72,26 @@ func TestRepository_GetTag(t *testing.T) {
assert.EqualValues(t, aTagCommitID, aTag.Object.String())
assert.EqualValues(t, "tag", aTag.Type)
// RELEASE TAGS
rTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
rTagName := "release/" + lTagName
err = bareRepo1.CreateTag(rTagName, rTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the tag: %s for ID: %s. Error: %v", rTagName, rTagCommitID, err)
return
}
bareRepo1.CreateTag(rTagName, rTagCommitID)
rTagID, err := bareRepo1.GetTagID(rTagName)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.EqualValues(t, rTagCommitID, rTagID)
oTagID, err := bareRepo1.GetTagID(lTagName)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.EqualValues(t, lTagCommitID, oTagID)
}
func TestRepository_GetAnnotatedTag(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, "TestRepository_GetAnnotatedTag")
if err != nil {
assert.NoError(t, err)
return
}
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag")
assert.NoError(t, err)
defer util.RemoveAll(clonedPath)
bareRepo1, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
defer bareRepo1.Close()
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
@@ -168,10 +106,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
// Try an annotated tag
tag, err := bareRepo1.GetAnnotatedTag(aTagID)
if err != nil {
assert.NoError(t, err)
return
}
assert.NoError(t, err)
assert.NotNil(t, tag)
assert.EqualValues(t, aTagName, tag.Name)
assert.EqualValues(t, aTagID, tag.ID.String())

View File

@@ -117,7 +117,7 @@ func (graph *Graph) LoadAndProcessCommits(repository *repo_model.Repository, git
c.Verification = asymkey_model.ParseCommitWithSignature(c.Commit)
_ = asymkey_model.CalculateTrustStatus(c.Verification, repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
return models.IsOwnerMemberCollaborator(repository, user.ID)
return models.IsUserRepoAdmin(repository, user)
}, &keyMap)
statuses, _, err := models.GetLatestCommitStatus(repository.ID, c.Commit.ID.String(), db.ListOptions{})

View File

@@ -192,7 +192,6 @@ func (g *Manager) RunAtHammer(hammer func()) {
}
func (g *Manager) doShutdown() {
if !g.setStateTransition(stateRunning, stateShuttingDown) {
g.DoImmediateHammer()
return
}
g.lock.Lock()

View File

@@ -168,12 +168,8 @@ func (g *Manager) DoGracefulRestart() {
if setting.GracefulRestartable {
log.Info("PID: %d. Forking...", os.Getpid())
err := g.doFork()
if err != nil {
if err.Error() == "another process already forked. Ignoring this one" {
g.DoImmediateHammer()
} else {
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
}
if err != nil && err.Error() != "another process already forked. Ignoring this one" {
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
}
} else {
log.Info("PID: %d. Not set restartable. Shutting down...", os.Getpid())

View File

@@ -55,7 +55,7 @@ var (
anySHA1Pattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,40})(\.\.\.?)([0-9a-f]{7,40})?(#[-+~_%.a-zA-Z0-9]+)?`)
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40})(\.\.\.?)([0-9a-f]{40})?(#[-+~_%.a-zA-Z0-9]+)?`)
validLinksPattern = regexp.MustCompile(`^[a-z][\w-]+://`)
@@ -944,13 +944,6 @@ func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
return
}
// Ensure that every group (m[0]...m[7]) has a match
for i := 0; i < 8; i++ {
if m[i] == -1 {
return
}
}
urlFull := node.Data[m[0]:m[1]]
text1 := base.ShortSha(node.Data[m[2]:m[3]])
textDots := base.ShortSha(node.Data[m[4]:m[5]])

View File

@@ -546,16 +546,3 @@ func TestFuzz(t *testing.T) {
assert.NoError(t, err)
}
func TestIssue18471(t *testing.T) {
data := `http://domain/org/repo/compare/783b039...da951ce`
var res strings.Builder
err := PostProcess(&RenderContext{
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
assert.NoError(t, err)
assert.Equal(t, res.String(), "<a href=\"http://domain/org/repo/compare/783b039...da951ce\" class=\"compare\"><code class=\"nohighlight\">783b039...da951ce</code></a>")
}

View File

@@ -115,7 +115,7 @@ func (m *mailNotifier) NotifyPullRequestCodeComment(pr *models.PullRequest, comm
func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *models.Issue, assignee *user_model.User, removed bool, comment *models.Comment) {
// mail only sent to added assignees and not self-assignee
if !removed && doer.ID != assignee.ID && (assignee.EmailNotifications() == user_model.EmailNotificationsEnabled || assignee.EmailNotifications() == user_model.EmailNotificationsOnMention) {
if !removed && doer.ID != assignee.ID && assignee.EmailNotifications() == user_model.EmailNotificationsEnabled {
ct := fmt.Sprintf("Assigned #%d.", issue.Index)
if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{assignee}); err != nil {
log.Error("Error in SendIssueAssignedMail for issue[%d] to assignee[%d]: %v", issue.ID, assignee.ID, err)
@@ -124,7 +124,7 @@ func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *m
}
func (m *mailNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *models.Issue, reviewer *user_model.User, isRequest bool, comment *models.Comment) {
if isRequest && doer.ID != reviewer.ID && (reviewer.EmailNotifications() == user_model.EmailNotificationsEnabled || reviewer.EmailNotifications() == user_model.EmailNotificationsOnMention) {
if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotifications() == user_model.EmailNotificationsEnabled {
ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL())
if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil {
log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err)

View File

@@ -1,41 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package public
import "strings"
// wellKnownMimeTypesLower comes from Golang's builtin mime package: `builtinTypesLower`, see the comment of detectWellKnownMimeType
var wellKnownMimeTypesLower = map[string]string{
".avif": "image/avif",
".css": "text/css; charset=utf-8",
".gif": "image/gif",
".htm": "text/html; charset=utf-8",
".html": "text/html; charset=utf-8",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".js": "text/javascript; charset=utf-8",
".json": "application/json",
".mjs": "text/javascript; charset=utf-8",
".pdf": "application/pdf",
".png": "image/png",
".svg": "image/svg+xml",
".wasm": "application/wasm",
".webp": "image/webp",
".xml": "text/xml; charset=utf-8",
// well, there are some types missing from the builtin list
".txt": "text/plain; charset=utf-8",
}
// detectWellKnownMimeType will return the mime-type for a well-known file ext name
// The purpose of this function is to bypass the unstable behavior of Golang's mime.TypeByExtension
// mime.TypeByExtension would use OS's mime-type config to overwrite the well-known types (see its document).
// If the user's OS has incorrect mime-type config, it would make Gitea can not respond a correct Content-Type to browsers.
// For example, if Gitea returns `text/plain` for a `.js` file, the browser couldn't run the JS due to security reasons.
// detectWellKnownMimeType makes the Content-Type for well-known files stable.
func detectWellKnownMimeType(ext string) string {
ext = strings.ToLower(ext)
return wellKnownMimeTypesLower[ext]
}

View File

@@ -95,15 +95,6 @@ func parseAcceptEncoding(val string) map[string]bool {
return types
}
// setWellKnownContentType will set the Content-Type if the file is a well-known type.
// See the comments of detectWellKnownMimeType
func setWellKnownContentType(w http.ResponseWriter, file string) {
mimeType := detectWellKnownMimeType(filepath.Ext(file))
if mimeType != "" {
w.Header().Set("Content-Type", mimeType)
}
}
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.FileSystem, file string) bool {
// use clean to keep the file is a valid path with no . or ..
f, err := fs.Open(path.Clean(file))
@@ -134,8 +125,6 @@ func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.Fi
return true
}
setWellKnownContentType(w, file)
serveContent(w, req, fi, fi.ModTime(), f)
return true
}

View File

@@ -9,12 +9,15 @@ package public
import (
"bytes"
"compress/gzip"
"io"
"mime"
"net/http"
"os"
"path/filepath"
"time"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
)
@@ -63,16 +66,24 @@ func serveContent(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modt
encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding"))
if encodings["gzip"] {
if cf, ok := fi.(*vfsgen۰CompressedFileInfo); ok {
rdGzip := bytes.NewReader(cf.GzipBytes())
// all static files are managed by Gitea, so we can make sure every file has the correct ext name
// then we can get the correct Content-Type, we do not need to do http.DetectContentType on the decompressed data
mimeType := detectWellKnownMimeType(filepath.Ext(fi.Name()))
if mimeType == "" {
mimeType = "application/octet-stream"
}
w.Header().Set("Content-Type", mimeType)
rd := bytes.NewReader(cf.GzipBytes())
w.Header().Set("Content-Encoding", "gzip")
http.ServeContent(w, req, fi.Name(), modtime, rdGzip)
ctype := mime.TypeByExtension(filepath.Ext(fi.Name()))
if ctype == "" {
// read a chunk to decide between utf-8 text and binary
var buf [512]byte
grd, _ := gzip.NewReader(rd)
n, _ := io.ReadFull(grd, buf[:])
ctype = http.DetectContentType(buf[:n])
_, err := rd.Seek(0, io.SeekStart) // rewind to output whole file
if err != nil {
log.Error("rd.Seek error: %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
}
w.Header().Set("Content-Type", ctype)
http.ServeContent(w, req, fi.Name(), modtime, rd)
return
}
}

View File

@@ -72,8 +72,6 @@ type ManagedPool interface {
BoostWorkers() int
// SetPoolSettings sets the user updatable settings for the pool
SetPoolSettings(maxNumberOfWorkers, boostWorkers int, timeout time.Duration)
// Done returns a channel that will be closed when the Pool's baseCtx is closed
Done() <-chan struct{}
}
// ManagedQueueList implements the sort.Interface
@@ -143,6 +141,7 @@ func (m *Manager) Remove(qid int64) {
delete(m.Queues, qid)
m.mutex.Unlock()
log.Trace("Queue Manager removed: QID: %d", qid)
}
// GetManagedQueue by qid
@@ -194,17 +193,6 @@ func (m *Manager) FlushAll(baseCtx context.Context, timeout time.Duration) error
wg.Done()
continue
}
if pool, ok := mq.Managed.(ManagedPool); ok {
// No point into flushing pools when their base's ctx is already done.
select {
case <-pool.Done():
wg.Done()
continue
default:
}
}
allEmpty = false
if flushable, ok := mq.Managed.(Flushable); ok {
log.Debug("Flushing (flushable) queue: %s", mq.Name)
@@ -237,6 +225,7 @@ func (m *Manager) FlushAll(baseCtx context.Context, timeout time.Duration) error
wg.Wait()
}
return nil
}
// ManagedQueues returns the managed queues

View File

@@ -195,11 +195,9 @@ loop:
}
}
var (
errQueueEmpty = fmt.Errorf("empty queue")
errEmptyBytes = fmt.Errorf("empty bytes")
errUnmarshal = fmt.Errorf("failed to unmarshal")
)
var errQueueEmpty = fmt.Errorf("empty queue")
var errEmptyBytes = fmt.Errorf("empty bytes")
var errUnmarshal = fmt.Errorf("failed to unmarshal")
func (q *ByteFIFOQueue) doPop() error {
q.lock.Lock()

View File

@@ -173,6 +173,7 @@ func (q *PersistableChannelQueue) Run(atShutdown, atTerminate func(func())) {
q.internal.(*LevelQueue).Shutdown()
GetManager().Remove(q.internal.(*LevelQueue).qid)
}
}
// Flush flushes the queue and blocks till the queue is empty
@@ -251,13 +252,14 @@ func (q *PersistableChannelQueue) Shutdown() {
q.channelQueue.Wait()
q.internal.(*LevelQueue).Wait()
// Redirect all remaining data in the chan to the internal channel
log.Trace("PersistableChannelQueue: %s Redirecting remaining data", q.delayedStarter.name)
close(q.channelQueue.dataChan)
for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data)
atomic.AddInt64(&q.channelQueue.numInQueue, -1)
}
log.Trace("PersistableChannelQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
go func() {
log.Trace("PersistableChannelQueue: %s Redirecting remaining data", q.delayedStarter.name)
for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data)
atomic.AddInt64(&q.channelQueue.numInQueue, -1)
}
log.Trace("PersistableChannelQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
}()
log.Debug("PersistableChannelQueue: %s Shutdown", q.delayedStarter.name)
}

View File

@@ -188,4 +188,5 @@ func TestPersistableChannelQueue(t *testing.T) {
for _, callback := range callbacks {
callback()
}
}

View File

@@ -238,12 +238,13 @@ func (q *PersistableChannelUniqueQueue) Shutdown() {
q.channelQueue.Wait()
q.internal.(*LevelUniqueQueue).Wait()
// Redirect all remaining data in the chan to the internal channel
close(q.channelQueue.dataChan)
log.Trace("PersistableChannelUniqueQueue: %s Redirecting remaining data", q.delayedStarter.name)
for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data)
}
log.Trace("PersistableChannelUniqueQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
go func() {
log.Trace("PersistableChannelUniqueQueue: %s Redirecting remaining data", q.delayedStarter.name)
for data := range q.channelQueue.dataChan {
_ = q.internal.Push(data)
}
log.Trace("PersistableChannelUniqueQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
}()
log.Debug("PersistableChannelUniqueQueue: %s Shutdown", q.delayedStarter.name)
}

View File

@@ -65,11 +65,6 @@ func NewWorkerPool(handle HandlerFunc, config WorkerPoolConfiguration) *WorkerPo
return pool
}
// Done returns when this worker pool's base context has been cancelled
func (p *WorkerPool) Done() <-chan struct{} {
return p.baseCtx.Done()
}
// Push pushes the data to the internal channel
func (p *WorkerPool) Push(data Data) {
atomic.AddInt64(&p.numInQueue, 1)
@@ -87,20 +82,6 @@ func (p *WorkerPool) Push(data Data) {
}
}
// HasNoWorkerScaling will return true if the queue has no workers, and has no worker boosting
func (p *WorkerPool) HasNoWorkerScaling() bool {
p.lock.Lock()
defer p.lock.Unlock()
return p.hasNoWorkerScaling()
}
func (p *WorkerPool) hasNoWorkerScaling() bool {
return p.numberOfWorkers == 0 && (p.boostTimeout == 0 || p.boostWorkers == 0 || p.maxNumberOfWorkers == 0)
}
// zeroBoost will add a temporary boost worker for a no worker queue
// p.lock must be locked at the start of this function BUT it will be unlocked by the end of this function
// (This is because addWorkers has to be called whilst unlocked)
func (p *WorkerPool) zeroBoost() {
ctx, cancel := context.WithTimeout(p.baseCtx, p.boostTimeout)
mq := GetManager().GetManagedQueue(p.qid)
@@ -109,7 +90,7 @@ func (p *WorkerPool) zeroBoost() {
boost = p.maxNumberOfWorkers - p.numberOfWorkers
}
if mq != nil {
log.Debug("WorkerPool: %d (for %s) has zero workers - adding %d temporary workers for %s", p.qid, mq.Name, boost, p.boostTimeout)
log.Warn("WorkerPool: %d (for %s) has zero workers - adding %d temporary workers for %s", p.qid, mq.Name, boost, p.boostTimeout)
start := time.Now()
pid := mq.RegisterWorkers(boost, start, true, start.Add(p.boostTimeout), cancel, false)
@@ -117,7 +98,7 @@ func (p *WorkerPool) zeroBoost() {
mq.RemoveWorkers(pid)
}
} else {
log.Debug("WorkerPool: %d has zero workers - adding %d temporary workers for %s", p.qid, p.boostWorkers, p.boostTimeout)
log.Warn("WorkerPool: %d has zero workers - adding %d temporary workers for %s", p.qid, p.boostWorkers, p.boostTimeout)
}
p.lock.Unlock()
p.addWorkers(ctx, cancel, boost)
@@ -291,21 +272,6 @@ func (p *WorkerPool) addWorkers(ctx context.Context, cancel context.CancelFunc,
p.cond.Broadcast()
cancel()
}
select {
case <-p.baseCtx.Done():
// Don't warn if the baseCtx is shutdown
default:
if p.hasNoWorkerScaling() {
log.Warn(
"Queue: %d is configured to be non-scaling and has no workers - this configuration is likely incorrect.", p.qid)
} else if p.numberOfWorkers == 0 && atomic.LoadInt64(&p.numInQueue) > 0 {
// OK there are no workers but... there's still work to be done -> Reboost
p.zeroBoost()
// p.lock will be unlocked by zeroBoost
return
}
}
p.lock.Unlock()
}()
}
@@ -360,10 +326,7 @@ func (p *WorkerPool) FlushWithContext(ctx context.Context) error {
log.Trace("WorkerPool: %d Flush", p.qid)
for {
select {
case data, ok := <-p.dataChan:
if !ok {
return nil
}
case data := <-p.dataChan:
p.handle(data)
atomic.AddInt64(&p.numInQueue, -1)
case <-p.baseCtx.Done():
@@ -378,7 +341,7 @@ func (p *WorkerPool) FlushWithContext(ctx context.Context) error {
func (p *WorkerPool) doWork(ctx context.Context) {
delay := time.Millisecond * 300
data := make([]Data, 0, p.batchLength)
var data = make([]Data, 0, p.batchLength)
for {
select {
case <-ctx.Done():

View File

@@ -23,7 +23,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
testTeamRepositories := func(teamID int64, repoIds []int64) {
team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
assert.NoError(t, team.GetRepositories(&models.SearchOrgTeamOptions{}), "%s: GetRepositories", team.Name)
assert.NoError(t, team.GetRepositories(&models.SearchTeamOptions{}), "%s: GetRepositories", team.Name)
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name)
for i, rid := range repoIds {

View File

@@ -1022,13 +1022,8 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
UI.CustomEmojisMap[emoji] = ":" + emoji + ":"
}
// FIXME: DEPRECATED to be removed in v1.18.0
U2F.AppID = strings.TrimSuffix(AppURL, "/")
if Cfg.Section("U2F").HasKey("APP_ID") {
U2F.AppID = Cfg.Section("U2F").Key("APP_ID").MustString(strings.TrimSuffix(AppURL, "/"))
} else if Cfg.Section("u2f").HasKey("APP_ID") {
U2F.AppID = Cfg.Section("u2f").Key("APP_ID").MustString(strings.TrimSuffix(AppURL, "/"))
}
sec = Cfg.Section("U2F")
U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimSuffix(AppURL, "/"))
}
func parseAuthorizedPrincipalsAllow(values []string) ([]string, bool) {
@@ -1167,6 +1162,7 @@ func MakeManifestData(appName, appURL, absoluteAssetURL string) []byte {
},
},
})
if err != nil {
log.Error("unable to marshal manifest JSON. Error: %v", err)
return make([]byte, 0)

View File

@@ -2334,7 +2334,6 @@ first_page = First
last_page = Last
total = Total: %d
dashboard.new_version_hint = Gitea %s is now available, you are running %s. Check the <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">blog</a> for more details.
dashboard.statistic = Summary
dashboard.operations = Maintenance Operations
dashboard.system_status = System Status
@@ -2408,7 +2407,6 @@ dashboard.last_gc_pause = Last GC Pause
dashboard.gc_times = GC Times
dashboard.delete_old_actions = Delete all old actions from database
dashboard.delete_old_actions.started = Delete all old actions from database started.
dashboard.update_checker = Update checker
users.user_manage_panel = User Account Management
users.new_account = Create User Account

View File

@@ -673,8 +673,8 @@ last_used=上次使用在
no_activity=没有最近活动
can_read_info=读取
can_write_info=写入
key_state_desc=7 天内使用过该密钥
token_state_desc=7 天内使用过该密钥
key_state_desc=7 天内使用过该密钥
token_state_desc=7 天内使用过该密钥
principal_state_desc=7 天内使用过该规则
show_openid=在个人信息上显示
hide_openid=在个人信息上隐藏
@@ -855,7 +855,7 @@ watchers=关注者
stargazers=称赞者
forks=派生仓库
pick_reaction=选择你的表情
reactions_more=再加载 %d
reactions_more=再加载 %d
unit_disabled=站点管理员已禁用此仓库单元。
language_other=其它
adopt_search=输入用户名以搜索未被收录的仓库... (留空以查找全部)
@@ -2334,7 +2334,6 @@ first_page=首页
last_page=末页
total=总计:%d
dashboard.new_version_hint = Gitea %s 可以更新了,您正在运行 %s。请检查 <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">博客</a> 查看更多详情。
dashboard.statistic=摘要
dashboard.operations=维护操作
dashboard.system_status=系统状态

748
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
"@claviska/jquery-minicolors": "2.3.6",
"@primer/octicons": "16.2.0",
"add-asset-webpack-plugin": "2.0.1",
"codemirror": "5.65.1",
"codemirror": "5.65.0",
"css-loader": "6.5.1",
"dropzone": "6.0.0-beta.2",
"easymde": "2.16.1",
@@ -23,13 +23,13 @@
"less": "4.1.2",
"less-loader": "10.2.0",
"license-checker-webpack-plugin": "0.2.1",
"mermaid": "8.14.0",
"mermaid": "8.13.9",
"mini-css-extract-plugin": "2.5.2",
"monaco-editor": "0.31.1",
"monaco-editor-webpack-plugin": "7.0.1",
"pretty-ms": "7.0.1",
"sortablejs": "1.14.0",
"swagger-ui-dist": "4.2.1",
"swagger-ui-dist": "4.1.3",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
"vue": "2.6.14",
@@ -37,8 +37,8 @@
"vue-calendar-heatmap": "0.8.4",
"vue-loader": "15.9.8",
"vue-template-compiler": "2.6.14",
"webpack": "5.67.0",
"webpack-cli": "4.9.2",
"webpack": "5.66.0",
"webpack-cli": "4.9.1",
"workbox-routing": "6.4.2",
"workbox-strategies": "6.4.2",
"worker-loader": "3.0.8",
@@ -55,7 +55,7 @@
"jest-extended": "1.2.0",
"jest-raw-loader": "1.0.1",
"postcss-less": "6.0.0",
"stylelint": "14.3.0",
"stylelint": "14.2.0",
"stylelint-config-standard": "24.0.0",
"svgo": "2.8.0",
"updates": "13.0.0"

View File

@@ -47,7 +47,7 @@ func ListTeams(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/TeamList"
teams, count, err := models.SearchOrgTeams(&models.SearchOrgTeamOptions{
teams, count, err := models.SearchTeam(&models.SearchTeamOptions{
ListOptions: utils.GetListOptions(ctx),
OrgID: ctx.Org.Organization.ID,
})
@@ -90,7 +90,7 @@ func ListUserTeams(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/TeamList"
teams, count, err := models.GetUserTeams(&models.GetUserTeamOptions{
teams, count, err := models.SearchTeam(&models.SearchTeamOptions{
ListOptions: utils.GetListOptions(ctx),
UserID: ctx.User.ID,
})
@@ -533,7 +533,7 @@ func GetTeamRepos(ctx *context.APIContext) {
// "$ref": "#/responses/RepositoryList"
team := ctx.Org.Team
if err := team.GetRepositories(&models.SearchOrgTeamOptions{
if err := team.GetRepositories(&models.SearchTeamOptions{
ListOptions: utils.GetListOptions(ctx),
}); err != nil {
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
@@ -707,14 +707,15 @@ func SearchTeam(ctx *context.APIContext) {
listOptions := utils.GetListOptions(ctx)
opts := &models.SearchOrgTeamOptions{
opts := &models.SearchTeamOptions{
UserID: ctx.User.ID,
Keyword: ctx.FormTrim("q"),
OrgID: ctx.Org.Organization.ID,
IncludeDesc: ctx.FormString("include_desc") == "" || ctx.FormBool("include_desc"),
ListOptions: listOptions,
}
teams, maxResults, err := models.SearchOrgTeams(opts)
teams, maxResults, err := models.SearchTeam(opts)
if err != nil {
log.Error("SearchTeam failed: %v", err)
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{

View File

@@ -203,7 +203,7 @@ func Migrate(ctx *context.APIContext) {
}
}()
if repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.User, repoOwner.Name, opts, nil); err != nil {
if _, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.User, repoOwner.Name, opts, nil); err != nil {
handleMigrateError(ctx, repoOwner, remoteAddr, err)
return
}

View File

@@ -192,9 +192,6 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
RequiredClaimName: form.Oauth2RequiredClaimName,
RequiredClaimValue: form.Oauth2RequiredClaimValue,
SkipLocalTwoFA: form.SkipLocalTwoFA,
GroupClaimName: form.Oauth2GroupClaimName,
RestrictedGroup: form.Oauth2RestrictedGroup,
AdminGroup: form.Oauth2AdminGroup,
}
}

View File

@@ -826,7 +826,7 @@ func SignInOAuthCallback(ctx *context.Context) {
u, gothUser, err := oAuth2UserLoginCallback(authSource, ctx.Req, ctx.Resp)
if err != nil {
if user_model.IsErrUserProhibitLogin(err) {
uplerr := err.(user_model.ErrUserProhibitLogin)
uplerr := err.(*user_model.ErrUserProhibitLogin)
log.Info("Failed authentication attempt for %s from %s: %v", uplerr.Name, ctx.RemoteAddr(), err)
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
@@ -904,10 +904,6 @@ func claimValueToStringSlice(claimValue interface{}) []string {
switch rawGroup := claimValue.(type) {
case []string:
groups = rawGroup
case []interface{}:
for _, group := range rawGroup {
groups = append(groups, fmt.Sprintf("%s", group))
}
default:
str := fmt.Sprintf("%s", rawGroup)
groups = strings.Split(str, ",")

View File

@@ -311,7 +311,6 @@ func TeamMembers(ctx *context.Context) {
ctx.ServerError("GetMembers", err)
return
}
ctx.Data["Units"] = unit_model.Units
ctx.HTML(http.StatusOK, tplTeamMembers)
}
@@ -320,11 +319,10 @@ func TeamRepositories(ctx *context.Context) {
ctx.Data["Title"] = ctx.Org.Team.Name
ctx.Data["PageIsOrgTeams"] = true
ctx.Data["PageIsOrgTeamRepos"] = true
if err := ctx.Org.Team.GetRepositories(&models.SearchOrgTeamOptions{}); err != nil {
if err := ctx.Org.Team.GetRepositories(&models.SearchTeamOptions{}); err != nil {
ctx.ServerError("GetRepositories", err)
return
}
ctx.Data["Units"] = unit_model.Units
ctx.HTML(http.StatusOK, tplTeamRepositories)
}

View File

@@ -351,7 +351,7 @@ func Diff(ctx *context.Context) {
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
return models.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID)
return models.IsUserRepoAdmin(ctx.Repo.Repository, user)
}, nil); err != nil {
ctx.ServerError("CalculateTrustStatus", err)
return

View File

@@ -786,15 +786,6 @@ func ExcerptBlob(ctx *context.Context) {
direction := ctx.FormString("direction")
filePath := ctx.FormString("path")
gitRepo := ctx.Repo.GitRepo
if ctx.FormBool("wiki") {
var err error
gitRepo, err = git.OpenRepositoryCtx(ctx, ctx.Repo.Repository.WikiPath())
if err != nil {
ctx.ServerError("OpenRepository", err)
return
}
defer gitRepo.Close()
}
chunkSize := gitdiff.BlobExcerptChunkSize
commit, err := gitRepo.GetCommit(commitID)
if err != nil {

View File

@@ -103,7 +103,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
}
isWiki := false
unitType := unit.TypeCode
var unitType = unit.TypeCode
var wikiRepoName string
if strings.HasSuffix(reponame, ".wiki") {
isWiki = true
@@ -456,6 +456,7 @@ func serviceRPC(h serviceHandler, service string) {
if err := h.r.Body.Close(); err != nil {
log.Error("serviceRPC: Close: %v", err)
}
}()
if !hasAccess(service, h, true) {
@@ -466,7 +467,7 @@ func serviceRPC(h serviceHandler, service string) {
h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", service))
var err error
reqBody := h.r.Body
var reqBody = h.r.Body
// Handle GZIP.
if h.r.Header.Get("Content-Encoding") == "gzip" {
@@ -490,10 +491,7 @@ func serviceRPC(h serviceHandler, service string) {
defer finished()
var stderr bytes.Buffer
args := make([]string, len(git.GlobalCommandArgs))
copy(args, git.GlobalCommandArgs)
args = append(args, []string{service, "--stateless-rpc", h.dir}...)
cmd := exec.CommandContext(ctx, git.GitExecutable, args...)
cmd := exec.CommandContext(ctx, git.GitExecutable, service, "--stateless-rpc", h.dir)
cmd.Dir = h.dir
cmd.Env = append(os.Environ(), h.environ...)
cmd.Stdout = h.w
@@ -501,9 +499,7 @@ func serviceRPC(h serviceHandler, service string) {
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
if err.Error() != "signal: killed" {
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.dir, err, stderr.String())
}
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.dir, err, stderr.String())
return
}
}

View File

@@ -802,7 +802,7 @@ func NewIssue(ctx *context.Context) {
milestoneID := ctx.FormInt64("milestone")
if milestoneID > 0 {
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, milestoneID)
milestone, err := models.GetMilestoneByID(milestoneID)
if err != nil {
log.Error("GetMilestoneByID: %d: %v", milestoneID, err)
} else {
@@ -889,7 +889,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
// Check milestone.
milestoneID := form.MilestoneID
if milestoneID > 0 {
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, milestoneID)
milestone, err := models.GetMilestoneByID(milestoneID)
if err != nil {
ctx.ServerError("GetMilestoneByID", err)
return nil, nil, 0, 0

View File

@@ -9,7 +9,6 @@ import (
"fmt"
"html"
"net/http"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
@@ -17,7 +16,6 @@ import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"github.com/sergi/go-diff/diffmatchpatch"
@@ -70,15 +68,9 @@ func GetContentHistoryList(ctx *context.Context) {
actionText = i18n.Tr(lang, "repo.issues.content_history.edited")
}
timeSinceText := timeutil.TimeSinceUnix(item.EditedUnix, lang)
username := item.UserName
if setting.UI.DefaultShowFullName && strings.TrimSpace(item.UserFullName) != "" {
username = strings.TrimSpace(item.UserFullName)
}
results = append(results, map[string]interface{}{
"name": fmt.Sprintf("<img class='ui avatar image' src='%s'><strong>%s</strong> %s %s",
html.EscapeString(item.UserAvatarLink), html.EscapeString(username), actionText, timeSinceText),
html.EscapeString(item.UserAvatarLink), html.EscapeString(item.UserName), actionText, timeSinceText),
"value": item.HistoryID,
})
}

View File

@@ -264,7 +264,7 @@ func DeleteMilestone(ctx *context.Context) {
// MilestoneIssuesAndPulls lists all the issues and pull requests of the milestone
func MilestoneIssuesAndPulls(ctx *context.Context) {
milestoneID := ctx.ParamsInt64(":id")
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, milestoneID)
milestone, err := models.GetMilestoneByID(milestoneID)
if err != nil {
if models.IsErrMilestoneNotExist(err) {
ctx.NotFound("GetMilestoneByID", err)

View File

@@ -392,8 +392,6 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C
// PrepareViewPullInfo show meta information for a pull request preview page
func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.CompareInfo {
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
repo := ctx.Repo.Repository
pull := issue.PullRequest
@@ -577,6 +575,8 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
ctx.Data["IsNothingToCompare"] = true
}
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
if pull.IsWorkInProgress() {
ctx.Data["IsPullWorkInProgress"] = true
ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix()

View File

@@ -465,7 +465,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
return
}
ctx.Data["LFSLockOwner"] = u.DisplayName()
ctx.Data["LFSLockOwnerHomeLink"] = u.HomeLink()
ctx.Data["LFSLockHint"] = ctx.Tr("repo.editor.this_file_locked")
}
@@ -801,7 +800,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
verification := asymkey_model.ParseCommitWithSignature(latestCommit)
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
return models.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID)
return models.IsUserRepoAdmin(ctx.Repo.Repository, user)
}, nil); err != nil {
ctx.ServerError("CalculateTrustStatus", err)
return nil

View File

@@ -5,7 +5,6 @@
package web
import (
gocontext "context"
"net/http"
"os"
"path"
@@ -953,25 +952,7 @@ func RegisterRoutes(m *web.Route) {
m.Group("/blob_excerpt", func() {
m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
}, func(ctx *context.Context) (cancel gocontext.CancelFunc) {
if ctx.FormBool("wiki") {
ctx.Data["PageIsWiki"] = true
repo.MustEnableWiki(ctx)
return
}
reqRepoCodeReader(ctx)
if ctx.Written() {
return
}
cancel = context.RepoRef()(ctx)
if ctx.Written() {
return
}
repo.MustBeNotEmpty(ctx)
return
})
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
m.Group("/pulls/{index}", func() {
m.Get(".diff", repo.DownloadPullDiff)

View File

@@ -24,18 +24,17 @@ import (
func UserSignIn(username, password string) (*user_model.User, *auth.Source, error) {
var user *user_model.User
if strings.Contains(username, "@") {
emailAddress := user_model.EmailAddress{LowerEmail: strings.ToLower(strings.TrimSpace(username))}
user = &user_model.User{Email: strings.ToLower(strings.TrimSpace(username))}
// check same email
has, err := db.GetEngine(db.DefaultContext).Where("is_activated=?", true).Get(&emailAddress)
cnt, err := db.Count(user)
if err != nil {
return nil, nil, err
}
if !has {
return nil, nil, user_model.ErrEmailAddressNotExist{
if cnt > 1 {
return nil, nil, user_model.ErrEmailAlreadyUsed{
Email: user.Email,
}
}
user = &user_model.User{ID: emailAddress.UID}
} else {
trimmedUsername := strings.TrimSpace(username)
if len(trimmedUsername) == 0 {
@@ -65,7 +64,7 @@ func UserSignIn(username, password string) (*user_model.User, *auth.Source, erro
return nil, nil, smtp.ErrUnsupportedLoginType
}
user, err := authenticator.Authenticate(user, user.LoginName, password)
user, err := authenticator.Authenticate(user, username, password)
if err != nil {
return nil, nil, err
}

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