mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-03 08:02:36 +09:00
Compare commits
52 Commits
v1.13.1
...
v1.11.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef8f6d99f1 | ||
|
|
4b688135f9 | ||
|
|
e24861a546 | ||
|
|
128cc34344 | ||
|
|
f82a805478 | ||
|
|
0dced15c1a | ||
|
|
db9342c854 | ||
|
|
79c1d48532 | ||
|
|
05b9864086 | ||
|
|
ff508c9c9b | ||
|
|
f96c1a2c79 | ||
|
|
ce756ee89f | ||
|
|
f2e9d4b851 | ||
|
|
e878d743f4 | ||
|
|
3fa14d89a2 | ||
|
|
bcb722daec | ||
|
|
8add1dfacc | ||
|
|
aa6ed1b7c1 | ||
|
|
95cb921097 | ||
|
|
6730df9e8c | ||
|
|
b577500a54 | ||
|
|
fe46185407 | ||
|
|
69a2a29c33 | ||
|
|
f766719895 | ||
|
|
e2ddc42377 | ||
|
|
3521177a34 | ||
|
|
c8bb0ecf52 | ||
|
|
dbe6136348 | ||
|
|
6d1f7e90cf | ||
|
|
42663a687c | ||
|
|
73c90c26d4 | ||
|
|
c579ad92b5 | ||
|
|
602c5da953 | ||
|
|
1980e59ac2 | ||
|
|
28508792ba | ||
|
|
3e23dad075 | ||
|
|
b13b9d3dbd | ||
|
|
4072f28e60 | ||
|
|
dbeef6bb02 | ||
|
|
fec35440db | ||
|
|
f8ea50cc7a | ||
|
|
0e53a16cca | ||
|
|
7eaba6ba8a | ||
|
|
ff16099c6d | ||
|
|
a516a7ba0f | ||
|
|
11bce6fd3d | ||
|
|
3fb906dc02 | ||
|
|
3a00a690c9 | ||
|
|
a2b7cc1bb1 | ||
|
|
04a77b1f42 | ||
|
|
f523372d07 | ||
|
|
e39c238ef4 |
@@ -1,44 +1,44 @@
|
|||||||
repo: go-gitea/gitea
|
repo: go-gitea/gitea
|
||||||
groups:
|
groups:
|
||||||
-
|
-
|
||||||
name: BREAKING
|
name: BREAKING
|
||||||
labels:
|
labels:
|
||||||
- kind/breaking
|
- kind/breaking
|
||||||
-
|
-
|
||||||
name: FEATURE
|
name: FEATURE
|
||||||
labels:
|
labels:
|
||||||
- kind/feature
|
- kind/feature
|
||||||
|
-
|
||||||
|
name: SECURITY
|
||||||
|
labels:
|
||||||
|
- kind/security
|
||||||
-
|
-
|
||||||
name: BUGFIXES
|
name: BUGFIXES
|
||||||
labels:
|
labels:
|
||||||
- kind/bug
|
- kind/bug
|
||||||
-
|
-
|
||||||
name: ENHANCEMENT
|
name: ENHANCEMENT
|
||||||
labels:
|
labels:
|
||||||
- kind/enhancement
|
- kind/enhancement
|
||||||
- kind/refactor
|
- kind/refactor
|
||||||
- kind/ui
|
- kind/ui
|
||||||
-
|
-
|
||||||
name: SECURITY
|
|
||||||
labels:
|
|
||||||
- kind/security
|
|
||||||
-
|
|
||||||
name: TESTING
|
name: TESTING
|
||||||
labels:
|
labels:
|
||||||
- kind/testing
|
- kind/testing
|
||||||
-
|
-
|
||||||
name: TRANSLATION
|
name: TRANSLATION
|
||||||
labels:
|
labels:
|
||||||
- kind/translation
|
- kind/translation
|
||||||
-
|
-
|
||||||
name: BUILD
|
name: BUILD
|
||||||
labels:
|
labels:
|
||||||
- kind/build
|
- kind/build
|
||||||
- kind/lint
|
- kind/lint
|
||||||
-
|
-
|
||||||
name: DOCS
|
name: DOCS
|
||||||
labels:
|
labels:
|
||||||
- kind/docs
|
- kind/docs
|
||||||
-
|
-
|
||||||
name: MISC
|
name: MISC
|
||||||
default: true
|
default: true
|
||||||
|
|||||||
408
.drone.yml
408
.drone.yml
@@ -1,6 +1,61 @@
|
|||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: testing
|
name: compliance
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /go
|
||||||
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: pre-build
|
||||||
|
pull: always
|
||||||
|
image: node:10 # this step is kept at the lowest version of node that we support
|
||||||
|
commands:
|
||||||
|
- make css
|
||||||
|
- make js
|
||||||
|
|
||||||
|
- name: build-without-gcc
|
||||||
|
pull: always
|
||||||
|
image: golang:1.11 # this step is kept as the lowest version of golang that we support
|
||||||
|
environment:
|
||||||
|
GO111MODULE: on
|
||||||
|
GOPROXY: off
|
||||||
|
commands:
|
||||||
|
- go build -mod=vendor -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||||
|
|
||||||
|
- name: build-linux-386
|
||||||
|
pull: always
|
||||||
|
image: golang:1.13
|
||||||
|
environment:
|
||||||
|
GO111MODULE: on
|
||||||
|
GOPROXY: off
|
||||||
|
GOOS: linux
|
||||||
|
GOARCH: 386
|
||||||
|
commands:
|
||||||
|
- go build -mod=vendor -o gitea_linux_386 # test if compatible with 32 bit
|
||||||
|
|
||||||
|
- name: check
|
||||||
|
pull: always
|
||||||
|
image: golang:1.13
|
||||||
|
commands:
|
||||||
|
- make clean
|
||||||
|
- make golangci-lint
|
||||||
|
- make revive
|
||||||
|
- make swagger-check
|
||||||
|
- make swagger-validate
|
||||||
|
- make test-vendor
|
||||||
|
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
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: testing-amd64
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
@@ -25,15 +80,9 @@ services:
|
|||||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||||
MYSQL_DATABASE: testgitea
|
MYSQL_DATABASE: testgitea
|
||||||
|
|
||||||
- name: pgsql
|
|
||||||
pull: default
|
|
||||||
image: postgres:9.5
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: test
|
|
||||||
|
|
||||||
- name: mssql
|
- name: mssql
|
||||||
pull: default
|
pull: default
|
||||||
image: microsoft/mssql-server-linux:latest
|
image: mcr.microsoft.com/mssql/server:latest
|
||||||
environment:
|
environment:
|
||||||
ACCEPT_EULA: Y
|
ACCEPT_EULA: Y
|
||||||
MSSQL_PID: Standard
|
MSSQL_PID: Standard
|
||||||
@@ -54,52 +103,23 @@ steps:
|
|||||||
exclude:
|
exclude:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
|
||||||
- name: pre-build
|
|
||||||
pull: always
|
|
||||||
image: node:10 # this step is kept at the lowest version of node that we support
|
|
||||||
commands:
|
|
||||||
- make css
|
|
||||||
- make js
|
|
||||||
|
|
||||||
- name: build-without-gcc
|
|
||||||
pull: always
|
|
||||||
image: golang:1.11 # this step is kept as the lowest version of golang that we support
|
|
||||||
environment:
|
|
||||||
GO111MODULE: on
|
|
||||||
GOPROXY: off
|
|
||||||
commands:
|
|
||||||
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
|
||||||
- go build -mod=vendor -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
|
||||||
|
|
||||||
- name: build-linux-386
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
environment:
|
|
||||||
GO111MODULE: on
|
|
||||||
GOPROXY: off
|
|
||||||
GOOS: linux
|
|
||||||
GOARCH: 386
|
|
||||||
commands:
|
|
||||||
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
|
||||||
- go build -mod=vendor -o gitea_linux_386 # test if compatible with 32 bit
|
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.13
|
image: golang:1.13
|
||||||
commands:
|
commands:
|
||||||
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
||||||
- make clean
|
|
||||||
- make golangci-lint
|
|
||||||
- make revive
|
|
||||||
- make swagger-check
|
|
||||||
- make swagger-validate
|
|
||||||
- make test-vendor
|
|
||||||
- make build
|
- make build
|
||||||
environment:
|
environment:
|
||||||
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
|
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
|
||||||
GOSUMDB: sum.golang.org
|
GOSUMDB: sum.golang.org
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
|
||||||
|
- name: tag-pre-condition
|
||||||
|
pull: always
|
||||||
|
image: alpine/git
|
||||||
|
commands:
|
||||||
|
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
|
||||||
|
|
||||||
- name: unit-test
|
- name: unit-test
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.13
|
image: golang:1.13
|
||||||
@@ -108,70 +128,8 @@ steps:
|
|||||||
environment:
|
environment:
|
||||||
GOPROXY: off
|
GOPROXY: off
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
depends_on:
|
GITHUB_READ_TOKEN:
|
||||||
- build
|
from_secret: github_read_token
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: release-test
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
commands:
|
|
||||||
- make test
|
|
||||||
environment:
|
|
||||||
GOPROXY: off
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
depends_on:
|
|
||||||
- build
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- "release/*"
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: tag-pre-condition
|
|
||||||
pull: always
|
|
||||||
image: alpine/git
|
|
||||||
commands:
|
|
||||||
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
|
|
||||||
depends_on:
|
|
||||||
- build
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: tag-test
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
commands:
|
|
||||||
- make test
|
|
||||||
environment:
|
|
||||||
GOPROXY: off
|
|
||||||
TAGS: bindata
|
|
||||||
depends_on:
|
|
||||||
- tag-pre-condition
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: test-sqlite
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
commands:
|
|
||||||
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
|
||||||
- apt-get install -y git-lfs
|
|
||||||
- timeout -s ABRT 20m make test-sqlite-migration
|
|
||||||
- timeout -s ABRT 20m make test-sqlite
|
|
||||||
environment:
|
|
||||||
GOPROXY: off
|
|
||||||
TAGS: bindata
|
|
||||||
depends_on:
|
|
||||||
- build
|
|
||||||
|
|
||||||
- name: test-mysql
|
- name: test-mysql
|
||||||
pull: always
|
pull: always
|
||||||
@@ -187,30 +145,6 @@ steps:
|
|||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: tag-test-mysql
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
commands:
|
|
||||||
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
|
||||||
- apt-get install -y git-lfs
|
|
||||||
- timeout -s ABRT 20m make test-mysql-migration
|
|
||||||
- timeout -s ABRT 20m make test-mysql
|
|
||||||
environment:
|
|
||||||
GOPROXY: off
|
|
||||||
TAGS: bindata
|
|
||||||
TEST_LDAP: 1
|
|
||||||
depends_on:
|
|
||||||
- build
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: test-mysql8
|
- name: test-mysql8
|
||||||
pull: always
|
pull: always
|
||||||
@@ -227,21 +161,6 @@ steps:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
|
||||||
- name: test-pgsql
|
|
||||||
pull: always
|
|
||||||
image: golang:1.13
|
|
||||||
commands:
|
|
||||||
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
|
||||||
- apt-get install -y git-lfs
|
|
||||||
- timeout -s ABRT 20m make test-pgsql-migration
|
|
||||||
- timeout -s ABRT 20m make test-pgsql
|
|
||||||
environment:
|
|
||||||
GOPROXY: off
|
|
||||||
TAGS: bindata
|
|
||||||
TEST_LDAP: 1
|
|
||||||
depends_on:
|
|
||||||
- build
|
|
||||||
|
|
||||||
- name: test-mssql
|
- name: test-mssql
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.13
|
image: golang:1.13
|
||||||
@@ -293,13 +212,89 @@ steps:
|
|||||||
- push
|
- push
|
||||||
- pull_request
|
- pull_request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: testing-arm64
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /go
|
||||||
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
|
services:
|
||||||
|
- name: pgsql
|
||||||
|
pull: default
|
||||||
|
image: postgres:9.5
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: test
|
||||||
|
|
||||||
|
- name: ldap
|
||||||
|
pull: default
|
||||||
|
image: gitea/test-openldap:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: fetch-tags
|
||||||
|
pull: default
|
||||||
|
image: docker:git
|
||||||
|
commands:
|
||||||
|
- git fetch --tags --force
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
exclude:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
- name: build
|
||||||
|
pull: always
|
||||||
|
image: golang:1.13
|
||||||
|
commands:
|
||||||
|
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
||||||
|
- make build
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: test-sqlite
|
||||||
|
pull: always
|
||||||
|
image: golang:1.13
|
||||||
|
commands:
|
||||||
|
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
||||||
|
- apt-get install -y git-lfs
|
||||||
|
- timeout -s ABRT 20m make test-sqlite-migration
|
||||||
|
- timeout -s ABRT 20m make test-sqlite
|
||||||
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
|
TAGS: bindata
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
|
- name: test-pgsql
|
||||||
|
pull: always
|
||||||
|
image: golang:1.13
|
||||||
|
commands:
|
||||||
|
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
||||||
|
- apt-get install -y git-lfs
|
||||||
|
- timeout -s ABRT 20m make test-pgsql-migration
|
||||||
|
- timeout -s ABRT 20m make test-pgsql
|
||||||
|
environment:
|
||||||
|
GOPROXY: off
|
||||||
|
TAGS: bindata
|
||||||
|
TEST_LDAP: 1
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: translations
|
name: translations
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: arm64
|
||||||
|
|
||||||
workspace:
|
workspace:
|
||||||
base: /go
|
base: /go
|
||||||
@@ -378,7 +373,8 @@ trigger:
|
|||||||
- push
|
- push
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- testing-amd64
|
||||||
|
- testing-arm64
|
||||||
- translations
|
- translations
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -476,7 +472,8 @@ trigger:
|
|||||||
- tag
|
- tag
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- testing-arm64
|
||||||
|
- testing-amd64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: fetch-tags
|
- name: fetch-tags
|
||||||
@@ -545,17 +542,14 @@ name: docs
|
|||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: arm64
|
||||||
|
|
||||||
workspace:
|
|
||||||
base: /go
|
|
||||||
path: src/code.gitea.io/gitea
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build-docs
|
- name: build-docs
|
||||||
pull: always
|
pull: always
|
||||||
image: webhippie/hugo:latest
|
image: plugins/hugo:latest
|
||||||
commands:
|
commands:
|
||||||
|
- apk add --no-cache make bash curl
|
||||||
- cd docs
|
- cd docs
|
||||||
- make trans-copy
|
- make trans-copy
|
||||||
- make clean
|
- make clean
|
||||||
@@ -563,7 +557,7 @@ steps:
|
|||||||
|
|
||||||
- name: publish-docs
|
- name: publish-docs
|
||||||
pull: always
|
pull: always
|
||||||
image: lucap/drone-netlify:latest
|
image: techknowlogick/drone-netlify:latest
|
||||||
settings:
|
settings:
|
||||||
path: docs/public/
|
path: docs/public/
|
||||||
site_id: d2260bae-7861-4c02-8646-8f6440b12672
|
site_id: d2260bae-7861-4c02-8646-8f6440b12672
|
||||||
@@ -578,7 +572,7 @@ steps:
|
|||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: docker-linux-amd64
|
name: docker-linux-amd64-release
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
@@ -589,13 +583,13 @@ workspace:
|
|||||||
path: src/code.gitea.io/gitea
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- testing-amd64
|
||||||
|
- testing-arm64
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
ref:
|
ref:
|
||||||
- refs/heads/master
|
- refs/heads/master
|
||||||
- "refs/tags/**"
|
- "refs/tags/**"
|
||||||
- "refs/pull/**"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: fetch-tags
|
- name: fetch-tags
|
||||||
@@ -603,23 +597,6 @@ steps:
|
|||||||
image: docker:git
|
image: docker:git
|
||||||
commands:
|
commands:
|
||||||
- git fetch --tags --force
|
- git fetch --tags --force
|
||||||
when:
|
|
||||||
event:
|
|
||||||
exclude:
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: dryrun
|
|
||||||
pull: always
|
|
||||||
image: plugins/docker:linux-amd64
|
|
||||||
settings:
|
|
||||||
dry_run: true
|
|
||||||
repo: gitea/gitea
|
|
||||||
tags: linux-amd64
|
|
||||||
build_args:
|
|
||||||
- GOPROXY=off
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: publish
|
- name: publish
|
||||||
pull: always
|
pull: always
|
||||||
@@ -641,7 +618,7 @@ steps:
|
|||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: docker-linux-arm64
|
name: docker-linux-arm64-dry-run
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
@@ -652,25 +629,13 @@ workspace:
|
|||||||
path: src/code.gitea.io/gitea
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- compliance
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
ref:
|
ref:
|
||||||
- refs/heads/master
|
|
||||||
- "refs/tags/**"
|
|
||||||
- "refs/pull/**"
|
- "refs/pull/**"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: fetch-tags
|
|
||||||
pull: default
|
|
||||||
image: docker:git
|
|
||||||
commands:
|
|
||||||
- git fetch --tags --force
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
exclude:
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
- name: dryrun
|
- name: dryrun
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/docker:linux-arm64
|
image: plugins/docker:linux-arm64
|
||||||
@@ -684,6 +649,33 @@ steps:
|
|||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: docker-linux-arm64-release
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /go
|
||||||
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- testing-amd64
|
||||||
|
- testing-arm64
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/master
|
||||||
|
- "refs/tags/**"
|
||||||
|
steps:
|
||||||
|
- name: fetch-tags
|
||||||
|
pull: default
|
||||||
|
image: docker:git
|
||||||
|
commands:
|
||||||
|
- git fetch --tags --force
|
||||||
|
|
||||||
- name: publish
|
- name: publish
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/docker:linux-arm64
|
image: plugins/docker:linux-arm64
|
||||||
@@ -729,45 +721,49 @@ trigger:
|
|||||||
- "refs/tags/**"
|
- "refs/tags/**"
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- docker-linux-amd64
|
- docker-linux-amd64-release
|
||||||
- docker-linux-arm64
|
- docker-linux-arm64-release
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: notify
|
name: notifications
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
arch: amd64
|
arch: arm64
|
||||||
|
|
||||||
workspace:
|
|
||||||
base: /go
|
|
||||||
path: src/code.gitea.io/gitea
|
|
||||||
|
|
||||||
clone:
|
clone:
|
||||||
disable: true
|
disable: true
|
||||||
|
|
||||||
when:
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
- "release/*"
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
- tag
|
||||||
status:
|
status:
|
||||||
- success
|
- success
|
||||||
- failure
|
- failure
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- testing-amd64
|
||||||
|
- testing-arm64
|
||||||
- translations
|
- translations
|
||||||
- release-version
|
- release-version
|
||||||
- release-master
|
- release-master
|
||||||
- docker-linux-amd64
|
- docker-linux-amd64-release
|
||||||
- docker-linux-arm64
|
- docker-linux-arm64-release
|
||||||
- docker-manifest
|
- docker-manifest
|
||||||
- docs
|
- docs
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: discord
|
- name: discord
|
||||||
pull: always
|
pull: always
|
||||||
image: appleboy/drone-discord:1.0.0
|
image: appleboy/drone-discord:1.2.4
|
||||||
environment:
|
settings:
|
||||||
DISCORD_WEBHOOK_ID:
|
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:
|
||||||
from_secret: discord_webhook_id
|
from_secret: discord_webhook_id
|
||||||
DISCORD_WEBHOOK_TOKEN:
|
webhook_token:
|
||||||
from_secret: discord_webhook_token
|
from_secret: discord_webhook_token
|
||||||
|
|||||||
78
CHANGELOG.md
78
CHANGELOG.md
@@ -4,6 +4,62 @@ 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
|
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).
|
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||||
|
|
||||||
|
## [1.11.0-RC2](https://github.com/go-gitea/gitea/releases/tag/v1.11.0-rc2) - 2020-01-18
|
||||||
|
* BREAKING
|
||||||
|
* Make CertFile and KeyFile relative to CustomPath (#9868) (#9874)
|
||||||
|
* SECURITY
|
||||||
|
* Never allow an empty password to validate (#9682) (#9683)
|
||||||
|
* Prevent redirect to Host (#9678) (#9679)
|
||||||
|
* BUGFIXES
|
||||||
|
* Don't convert ellipsis in markdown (#9905) (#9937)
|
||||||
|
* Fixed repo link in generated comment for cross repository dependency (#9863) (#9935)
|
||||||
|
* Check if diff actually contains sections when rendering (#9926) (#9933)
|
||||||
|
* Fix wrong hint when status checking is running on pull request view (#9886) (#9928)
|
||||||
|
* Fix RocketChat (#9908) (#9921)
|
||||||
|
* Do not try to recreate ldap user if they are already created (#9900) (#9919)
|
||||||
|
* Create terminated channel in queue_redis (#9910) (#9911)
|
||||||
|
* Prevent empty LDAP search result from deactivating all users (#9879) (#9896)
|
||||||
|
* Fix wrong permissions check when issues/prs shared operations (#9885) (#9889)
|
||||||
|
* Check user != nil before checking values (#9881) (#9883)
|
||||||
|
* Allow hyphen in language name (#9873) (#9880)
|
||||||
|
* Ensure that 2fa is checked on reset-password (#9857) (#9876)
|
||||||
|
* Fix issues/pulls dependencies problems (#9842) (#9864)
|
||||||
|
* Explicitly refer to PR in squash-merge commit message in case of external tracker (#9844) (#9855)
|
||||||
|
* Fix markdown anchor links (#9673) (#9840)
|
||||||
|
* Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9837)
|
||||||
|
* Fix download file wrong content-type (#9825) (#9834)
|
||||||
|
* Fix wrong poster identity on a migrated pull request when submit review (#9827) (#9830)
|
||||||
|
* Fix database dump when log directory is missing (#9818) (#9819)
|
||||||
|
* Fix compare (#9808) (#9814)
|
||||||
|
* Fix push-to-create (#9772) (#9797)
|
||||||
|
* Fix missing msteam webhook on organization (#9781) (#9794)
|
||||||
|
* Fix missing unlock in uniquequeue (#9790) (#9791)
|
||||||
|
* Fix add team on collaborator page when same name as organization (#9778)
|
||||||
|
* DeleteRepoFile incorrectly handles Delete to new branch (#9769) (#9775)
|
||||||
|
* Fix milestones page (#9771)
|
||||||
|
* Fix SimpleMDE quote reply (#9757) (#9768)
|
||||||
|
* Fix missing updated time on migrated issues and comments (#9744) (#9764)
|
||||||
|
* Move Errored PRs out of StatusChecking (#9675) (#9726)
|
||||||
|
* Make hook status printing configurable with delay (#9641) (#9725)
|
||||||
|
* Fix /repos/issues/search (#9698) (#9724)
|
||||||
|
* Silence fomantic error regarding tabs (#9713) (#9718)
|
||||||
|
* Remove unused lock (#9709) (#9710)
|
||||||
|
* Remove q.lock.Unlock() in setInternal to prevent panic (#9705) (#9706)
|
||||||
|
* Load milestone in API PR list (#9671) (#9700)
|
||||||
|
* Don't attempt to close issue if already closed (#9696) (#9699)
|
||||||
|
* Remove google font call (#9668) (#9681)
|
||||||
|
* Eliminate horizontal scroll caused by footer (#9674)
|
||||||
|
* Fix nil reference in repo generation (#9660) (#9666)
|
||||||
|
* Add HTML URL to API Issues (#9654) (#9661)
|
||||||
|
* Add PR review webhook to Telegram (#9653) (#9655)
|
||||||
|
* Use filepath.IsAbs instead of path.IsAbs (#9651) (#9652)
|
||||||
|
* TRANSLATION
|
||||||
|
* Fix Korean locales (#9761) (#9780)
|
||||||
|
* BUILD
|
||||||
|
* Fix webpack polyfills (#9735) (#9738)
|
||||||
|
* MISC
|
||||||
|
* Backport Locales [2020-01-14] (#9773)
|
||||||
|
|
||||||
## [1.11.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.11.0-rc1) - 2020-01-07
|
## [1.11.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.11.0-rc1) - 2020-01-07
|
||||||
* BREAKING
|
* BREAKING
|
||||||
* Remove unused endpoints (#9538)
|
* Remove unused endpoints (#9538)
|
||||||
@@ -384,6 +440,24 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
|||||||
* Update CodeMirror to version 5.49.0 (#8381)
|
* Update CodeMirror to version 5.49.0 (#8381)
|
||||||
* Wiki editor: enable side-by-side button (#7242)
|
* Wiki editor: enable side-by-side button (#7242)
|
||||||
|
|
||||||
|
## [1.10.3](https://github.com/go-gitea/gitea/releases/tag/v1.10.3) - 2020-01-17
|
||||||
|
* SECURITY
|
||||||
|
* Hide credentials when submitting migration (#9102) (#9704)
|
||||||
|
* Never allow an empty password to validate (#9682) (#9684)
|
||||||
|
* Prevent redirect to Host (#9678) (#9680)
|
||||||
|
* Hide public repos owned by private orgs (#9609) (#9616)
|
||||||
|
* BUGFIXES
|
||||||
|
* Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9838)
|
||||||
|
* Fix download file wrong content-type (#9825) (#9835)
|
||||||
|
* Fix wrong identify poster on a migrated pull request when submit review (#9827) (#9831)
|
||||||
|
* Fix dump non-exist log directory (#9818) (#9820)
|
||||||
|
* Fix compare (#9808) (#9815)
|
||||||
|
* Fix missing msteam webhook on organization (#9781) (#9795)
|
||||||
|
* Fix add team on collaborator page when same name as organization (#9783)
|
||||||
|
* Fix cache problem on dashboard (#9358) (#9703)
|
||||||
|
* Send tag create and push webhook when release created on UI (#8671) (#9702)
|
||||||
|
* Branches not at ref commit ID should not be listed as Merged (#9614) (#9639)
|
||||||
|
|
||||||
## [1.10.2](https://github.com/go-gitea/gitea/releases/tag/v1.10.2) - 2020-01-02
|
## [1.10.2](https://github.com/go-gitea/gitea/releases/tag/v1.10.2) - 2020-01-02
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
|
* Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
|
||||||
@@ -1483,13 +1557,13 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
|||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Allow resend of confirmation email when logged in (#6482) (#6487)
|
* Allow resend of confirmation email when logged in (#6482) (#6487)
|
||||||
|
|
||||||
## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
|
## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
|
* Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
|
||||||
* Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
|
* Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
|
||||||
* Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
|
* Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
|
||||||
|
|
||||||
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
|
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
|
||||||
* SECURITY
|
* SECURITY
|
||||||
* Fix potential XSS vulnerability in repository description. (#6306) (#6308)
|
* Fix potential XSS vulnerability in repository description. (#6306) (#6308)
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
|
|||||||
11
Makefile
11
Makefile
@@ -119,6 +119,13 @@ go-check:
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
.PHONY: git-check
|
||||||
|
git-check:
|
||||||
|
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
||||||
|
echo "Gitea requires git with lfs support to run tests." ; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: node-check
|
.PHONY: node-check
|
||||||
node-check:
|
node-check:
|
||||||
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?' | tr '.' ' ');))
|
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?' | tr '.' ' ');))
|
||||||
@@ -233,7 +240,7 @@ coverage:
|
|||||||
|
|
||||||
.PHONY: unit-test-coverage
|
.PHONY: unit-test-coverage
|
||||||
unit-test-coverage:
|
unit-test-coverage:
|
||||||
$(GO) test -tags='sqlite sqlite_unlock_notify' -cover -coverprofile coverage.out $(PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
GO111MODULE=on $(GO) test -mod=vendor -tags='sqlite sqlite_unlock_notify' -cover -coverprofile coverage.out $(PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||||
|
|
||||||
.PHONY: vendor
|
.PHONY: vendor
|
||||||
vendor:
|
vendor:
|
||||||
@@ -376,7 +383,7 @@ integrations.mssql.test: $(GO_SOURCES)
|
|||||||
integrations.sqlite.test: $(GO_SOURCES)
|
integrations.sqlite.test: $(GO_SOURCES)
|
||||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
|
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
|
||||||
|
|
||||||
integrations.cover.test: $(GO_SOURCES)
|
integrations.cover.test: git-check $(GO_SOURCES)
|
||||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
||||||
|
|
||||||
.PHONY: migrations.mysql.test
|
.PHONY: migrations.mysql.test
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ var (
|
|||||||
Name: "admin-filter",
|
Name: "admin-filter",
|
||||||
Usage: "An LDAP filter specifying if a user should be given administrator privileges.",
|
Usage: "An LDAP filter specifying if a user should be given administrator privileges.",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "allow-deactivate-all",
|
||||||
|
Usage: "Allow empty search results to deactivate all users.",
|
||||||
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "username-attribute",
|
Name: "username-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
||||||
@@ -231,6 +235,9 @@ func parseLdapConfig(c *cli.Context, config *models.LDAPConfig) error {
|
|||||||
if c.IsSet("admin-filter") {
|
if c.IsSet("admin-filter") {
|
||||||
config.Source.AdminFilter = c.String("admin-filter")
|
config.Source.AdminFilter = c.String("admin-filter")
|
||||||
}
|
}
|
||||||
|
if c.IsSet("allow-deactivate-all") {
|
||||||
|
config.Source.AllowDeactivateAll = c.Bool("allow-deactivate-all")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,8 +151,10 @@ func runDump(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
if com.IsExist(setting.LogRootPath) {
|
||||||
fatal("Failed to include log: %v", err)
|
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||||
|
fatal("Failed to include log: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = z.Close(); err != nil {
|
if err = z.Close(); err != nil {
|
||||||
|
|||||||
148
cmd/hook.go
148
cmd/hook.go
@@ -8,10 +8,12 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
@@ -58,6 +60,85 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type delayWriter struct {
|
||||||
|
internal io.Writer
|
||||||
|
buf *bytes.Buffer
|
||||||
|
timer *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDelayWriter(internal io.Writer, delay time.Duration) *delayWriter {
|
||||||
|
timer := time.NewTimer(delay)
|
||||||
|
return &delayWriter{
|
||||||
|
internal: internal,
|
||||||
|
buf: &bytes.Buffer{},
|
||||||
|
timer: timer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *delayWriter) Write(p []byte) (n int, err error) {
|
||||||
|
if d.buf != nil {
|
||||||
|
select {
|
||||||
|
case <-d.timer.C:
|
||||||
|
_, err := d.internal.Write(d.buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d.buf = nil
|
||||||
|
return d.internal.Write(p)
|
||||||
|
default:
|
||||||
|
return d.buf.Write(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.internal.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *delayWriter) WriteString(s string) (n int, err error) {
|
||||||
|
if d.buf != nil {
|
||||||
|
select {
|
||||||
|
case <-d.timer.C:
|
||||||
|
_, err := d.internal.Write(d.buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d.buf = nil
|
||||||
|
return d.internal.Write([]byte(s))
|
||||||
|
default:
|
||||||
|
return d.buf.WriteString(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.internal.Write([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *delayWriter) Close() error {
|
||||||
|
if d == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stopped := d.timer.Stop()
|
||||||
|
if stopped {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-d.timer.C:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if d.buf == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, err := d.internal.Write(d.buf.Bytes())
|
||||||
|
d.buf = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type nilWriter struct{}
|
||||||
|
|
||||||
|
func (n *nilWriter) Write(p []byte) (int, error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nilWriter) WriteString(s string) (int, error) {
|
||||||
|
return len(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
func runHookPreReceive(c *cli.Context) error {
|
func runHookPreReceive(c *cli.Context) error {
|
||||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||||
return nil
|
return nil
|
||||||
@@ -101,6 +182,18 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
total := 0
|
total := 0
|
||||||
lastline := 0
|
lastline := 0
|
||||||
|
|
||||||
|
var out io.Writer
|
||||||
|
out = &nilWriter{}
|
||||||
|
if setting.Git.VerbosePush {
|
||||||
|
if setting.Git.VerbosePushDelay > 0 {
|
||||||
|
dWriter := newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
||||||
|
defer dWriter.Close()
|
||||||
|
out = dWriter
|
||||||
|
} else {
|
||||||
|
out = os.Stdout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
// TODO: support news feeds for wiki
|
// TODO: support news feeds for wiki
|
||||||
if isWiki {
|
if isWiki {
|
||||||
@@ -124,12 +217,10 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
newCommitIDs[count] = newCommitID
|
newCommitIDs[count] = newCommitID
|
||||||
refFullNames[count] = refFullName
|
refFullNames[count] = refFullName
|
||||||
count++
|
count++
|
||||||
fmt.Fprintf(os.Stdout, "*")
|
fmt.Fprintf(out, "*")
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
if count >= hookBatchSize {
|
if count >= hookBatchSize {
|
||||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
hookOptions.OldCommitIDs = oldCommitIDs
|
hookOptions.OldCommitIDs = oldCommitIDs
|
||||||
hookOptions.NewCommitIDs = newCommitIDs
|
hookOptions.NewCommitIDs = newCommitIDs
|
||||||
@@ -147,12 +238,10 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
lastline = 0
|
lastline = 0
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stdout, ".")
|
fmt.Fprintf(out, ".")
|
||||||
os.Stdout.Sync()
|
|
||||||
}
|
}
|
||||||
if lastline >= hookBatchSize {
|
if lastline >= hookBatchSize {
|
||||||
fmt.Fprintf(os.Stdout, "\n")
|
fmt.Fprintf(out, "\n")
|
||||||
os.Stdout.Sync()
|
|
||||||
lastline = 0
|
lastline = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,8 +251,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||||
hookOptions.RefFullNames = refFullNames[:count]
|
hookOptions.RefFullNames = refFullNames[:count]
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
|
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
|
||||||
switch statusCode {
|
switch statusCode {
|
||||||
@@ -173,14 +261,11 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
fail(msg, "")
|
fail(msg, "")
|
||||||
}
|
}
|
||||||
} else if lastline > 0 {
|
} else if lastline > 0 {
|
||||||
fmt.Fprintf(os.Stdout, "\n")
|
fmt.Fprintf(out, "\n")
|
||||||
os.Stdout.Sync()
|
|
||||||
lastline = 0
|
lastline = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, "Checked %d references in total\n", total)
|
fmt.Fprintf(out, "Checked %d references in total\n", total)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +291,19 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var out io.Writer
|
||||||
|
var dWriter *delayWriter
|
||||||
|
out = &nilWriter{}
|
||||||
|
if setting.Git.VerbosePush {
|
||||||
|
if setting.Git.VerbosePushDelay > 0 {
|
||||||
|
dWriter = newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
||||||
|
defer dWriter.Close()
|
||||||
|
out = dWriter
|
||||||
|
} else {
|
||||||
|
out = os.Stdout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// the environment setted on serv command
|
// the environment setted on serv command
|
||||||
repoUser := os.Getenv(models.EnvRepoUsername)
|
repoUser := os.Getenv(models.EnvRepoUsername)
|
||||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||||
@@ -241,7 +339,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, ".")
|
fmt.Fprintf(out, ".")
|
||||||
oldCommitIDs[count] = string(fields[0])
|
oldCommitIDs[count] = string(fields[0])
|
||||||
newCommitIDs[count] = string(fields[1])
|
newCommitIDs[count] = string(fields[1])
|
||||||
refFullNames[count] = string(fields[2])
|
refFullNames[count] = string(fields[2])
|
||||||
@@ -250,16 +348,15 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
total++
|
total++
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
if count >= hookBatchSize {
|
if count >= hookBatchSize {
|
||||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||||
os.Stdout.Sync()
|
|
||||||
hookOptions.OldCommitIDs = oldCommitIDs
|
hookOptions.OldCommitIDs = oldCommitIDs
|
||||||
hookOptions.NewCommitIDs = newCommitIDs
|
hookOptions.NewCommitIDs = newCommitIDs
|
||||||
hookOptions.RefFullNames = refFullNames
|
hookOptions.RefFullNames = refFullNames
|
||||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
fail("Internal Server Error", err)
|
fail("Internal Server Error", err)
|
||||||
}
|
}
|
||||||
@@ -277,9 +374,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
|
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -288,19 +385,18 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||||
hookOptions.RefFullNames = refFullNames[:count]
|
hookOptions.RefFullNames = refFullNames[:count]
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
fail("Internal Server Error", err)
|
fail("Internal Server Error", err)
|
||||||
}
|
}
|
||||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||||
results = append(results, resp.Results...)
|
results = append(results, resp.Results...)
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
|
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||||
os.Stdout.Sync()
|
|
||||||
|
|
||||||
if wasEmpty && masterPushed {
|
if wasEmpty && masterPushed {
|
||||||
// We need to tell the repo to reset the default branch to master
|
// We need to tell the repo to reset the default branch to master
|
||||||
@@ -309,7 +405,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -275,8 +275,9 @@ DISABLE_ROUTER_LOG = false
|
|||||||
; not forget to export the private key):
|
; not forget to export the private key):
|
||||||
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
|
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
|
||||||
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
||||||
CERT_FILE = custom/https/cert.pem
|
; Paths are relative to CUSTOM_PATH
|
||||||
KEY_FILE = custom/https/key.pem
|
CERT_FILE = https/cert.pem
|
||||||
|
KEY_FILE = https/key.pem
|
||||||
; Root directory containing templates and static files.
|
; Root directory containing templates and static files.
|
||||||
; default is the path where Gitea is executed
|
; default is the path where Gitea is executed
|
||||||
STATIC_ROOT_PATH =
|
STATIC_ROOT_PATH =
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
|||||||
- `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
|
- `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
|
||||||
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
||||||
- `DISABLE_ROUTER_LOG`: **false**: Mute printing of the router log.
|
- `DISABLE_ROUTER_LOG`: **false**: Mute printing of the router log.
|
||||||
- `CERT_FILE`: **custom/https/cert.pem**: Cert file path used for HTTPS.
|
- `CERT_FILE`: **https/cert.pem**: Cert file path used for HTTPS. From 1.11 paths are relative to `CUSTOM_PATH`.
|
||||||
- `KEY_FILE`: **custom/https/key.pem**: Key file path used for HTTPS.
|
- `KEY_FILE`: **https/key.pem**: Key file path used for HTTPS. From 1.11 paths are relative to `CUSTOM_PATH`.
|
||||||
- `STATIC_ROOT_PATH`: **./**: Upper level of template and static files path.
|
- `STATIC_ROOT_PATH`: **./**: Upper level of template and static files path.
|
||||||
- `STATIC_CACHE_TIME`: **6h**: Web browser cache time for static resources on `custom/`, `public/` and all uploaded avatars.
|
- `STATIC_CACHE_TIME`: **6h**: Web browser cache time for static resources on `custom/`, `public/` and all uploaded avatars.
|
||||||
- `ENABLE_GZIP`: **false**: Enables application-level GZIP support.
|
- `ENABLE_GZIP`: **false**: Enables application-level GZIP support.
|
||||||
@@ -522,6 +522,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
|
|||||||
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
||||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
||||||
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
|
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
|
||||||
|
- `VERBOSE_PUSH`: **true**: Print status information about pushes as they are being processed.
|
||||||
|
- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.
|
||||||
|
|
||||||
## Git - Timeout settings (`git.timeout`)
|
## Git - Timeout settings (`git.timeout`)
|
||||||
- `DEFAUlT`: **360**: Git operations default timeout seconds.
|
- `DEFAUlT`: **360**: Git operations default timeout seconds.
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ the `!` marker to identify pull requests. For example:
|
|||||||
> This is pull request [!1234](#), and links to a pull request in Gitea.
|
> This is pull request [!1234](#), and links to a pull request in Gitea.
|
||||||
|
|
||||||
The `!` and `#` can be used interchangeably for issues and pull request _except_
|
The `!` and `#` can be used interchangeably for issues and pull request _except_
|
||||||
for this case, where a distinction is required.
|
for this case, where a distinction is required. If the repository uses external
|
||||||
|
tracker, commit message for squash merge will use `!` as reference by default.
|
||||||
|
|
||||||
## Issues and Pull Requests References Summary
|
## Issues and Pull Requests References Summary
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package integrations
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -120,3 +121,47 @@ func TestAPIEditIssue(t *testing.T) {
|
|||||||
assert.Equal(t, body, issueAfter.Content)
|
assert.Equal(t, body, issueAfter.Content)
|
||||||
assert.Equal(t, title, issueAfter.Title)
|
assert.Equal(t, title, issueAfter.Title)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPISearchIssue(t *testing.T) {
|
||||||
|
defer prepareTestEnv(t)()
|
||||||
|
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
|
||||||
|
link, _ := url.Parse("/api/v1/repos/issues/search")
|
||||||
|
req := NewRequest(t, "GET", link.String())
|
||||||
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
var apiIssues []*api.Issue
|
||||||
|
DecodeJSON(t, resp, &apiIssues)
|
||||||
|
|
||||||
|
assert.Len(t, apiIssues, 8)
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
query.Add("token", token)
|
||||||
|
link.RawQuery = query.Encode()
|
||||||
|
req = NewRequest(t, "GET", link.String())
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
DecodeJSON(t, resp, &apiIssues)
|
||||||
|
assert.Len(t, apiIssues, 8)
|
||||||
|
|
||||||
|
query.Add("state", "closed")
|
||||||
|
link.RawQuery = query.Encode()
|
||||||
|
req = NewRequest(t, "GET", link.String())
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
DecodeJSON(t, resp, &apiIssues)
|
||||||
|
assert.Len(t, apiIssues, 2)
|
||||||
|
|
||||||
|
query.Set("state", "all")
|
||||||
|
link.RawQuery = query.Encode()
|
||||||
|
req = NewRequest(t, "GET", link.String())
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
DecodeJSON(t, resp, &apiIssues)
|
||||||
|
assert.Len(t, apiIssues, 10) //there are more but 10 is page item limit
|
||||||
|
|
||||||
|
query.Add("page", "2")
|
||||||
|
link.RawQuery = query.Encode()
|
||||||
|
req = NewRequest(t, "GET", link.String())
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
DecodeJSON(t, resp, &apiIssues)
|
||||||
|
assert.Len(t, apiIssues, 0)
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -48,20 +47,20 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
|||||||
|
|
||||||
commitID := path.Base(commitURL)
|
commitID := path.Base(commitURL)
|
||||||
|
|
||||||
statusList := []models.CommitStatusState{
|
statusList := []api.CommitStatusState{
|
||||||
models.CommitStatusPending,
|
api.CommitStatusPending,
|
||||||
models.CommitStatusError,
|
api.CommitStatusError,
|
||||||
models.CommitStatusFailure,
|
api.CommitStatusFailure,
|
||||||
models.CommitStatusWarning,
|
api.CommitStatusWarning,
|
||||||
models.CommitStatusSuccess,
|
api.CommitStatusSuccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
statesIcons := map[models.CommitStatusState]string{
|
statesIcons := map[api.CommitStatusState]string{
|
||||||
models.CommitStatusPending: "circle icon yellow",
|
api.CommitStatusPending: "circle icon yellow",
|
||||||
models.CommitStatusSuccess: "check icon green",
|
api.CommitStatusSuccess: "check icon green",
|
||||||
models.CommitStatusError: "warning icon red",
|
api.CommitStatusError: "warning icon red",
|
||||||
models.CommitStatusFailure: "remove icon red",
|
api.CommitStatusFailure: "remove icon red",
|
||||||
models.CommitStatusWarning: "warning sign icon yellow",
|
api.CommitStatusWarning: "warning sign icon yellow",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update commit status, and check if icon is updated as well
|
// Update commit status, and check if icon is updated as well
|
||||||
|
|||||||
@@ -19,52 +19,19 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommitStatusState holds the state of a Status
|
|
||||||
// It can be "pending", "success", "error", "failure", and "warning"
|
|
||||||
type CommitStatusState string
|
|
||||||
|
|
||||||
// IsWorseThan returns true if this State is worse than the given State
|
|
||||||
func (css CommitStatusState) IsWorseThan(css2 CommitStatusState) bool {
|
|
||||||
switch css {
|
|
||||||
case CommitStatusError:
|
|
||||||
return true
|
|
||||||
case CommitStatusFailure:
|
|
||||||
return css2 != CommitStatusError
|
|
||||||
case CommitStatusWarning:
|
|
||||||
return css2 != CommitStatusError && css2 != CommitStatusFailure
|
|
||||||
case CommitStatusSuccess:
|
|
||||||
return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning
|
|
||||||
default:
|
|
||||||
return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning && css2 != CommitStatusSuccess
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// CommitStatusPending is for when the Status is Pending
|
|
||||||
CommitStatusPending CommitStatusState = "pending"
|
|
||||||
// CommitStatusSuccess is for when the Status is Success
|
|
||||||
CommitStatusSuccess CommitStatusState = "success"
|
|
||||||
// CommitStatusError is for when the Status is Error
|
|
||||||
CommitStatusError CommitStatusState = "error"
|
|
||||||
// CommitStatusFailure is for when the Status is Failure
|
|
||||||
CommitStatusFailure CommitStatusState = "failure"
|
|
||||||
// CommitStatusWarning is for when the Status is Warning
|
|
||||||
CommitStatusWarning CommitStatusState = "warning"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommitStatus holds a single Status of a single Commit
|
// CommitStatus holds a single Status of a single Commit
|
||||||
type CommitStatus struct {
|
type CommitStatus struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||||
RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||||
Repo *Repository `xorm:"-"`
|
Repo *Repository `xorm:"-"`
|
||||||
State CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
|
State api.CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
|
||||||
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
|
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
|
||||||
TargetURL string `xorm:"TEXT"`
|
TargetURL string `xorm:"TEXT"`
|
||||||
Description string `xorm:"TEXT"`
|
Description string `xorm:"TEXT"`
|
||||||
ContextHash string `xorm:"char(40) index"`
|
ContextHash string `xorm:"char(40) index"`
|
||||||
Context string `xorm:"TEXT"`
|
Context string `xorm:"TEXT"`
|
||||||
Creator *User `xorm:"-"`
|
Creator *User `xorm:"-"`
|
||||||
CreatorID int64
|
CreatorID int64
|
||||||
|
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||||
@@ -118,9 +85,9 @@ func (status *CommitStatus) APIFormat() *api.Status {
|
|||||||
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
||||||
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
||||||
var lastStatus *CommitStatus
|
var lastStatus *CommitStatus
|
||||||
var state CommitStatusState
|
var state api.CommitStatusState
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
if status.State.IsWorseThan(state) {
|
if status.State.NoBetterThan(state) {
|
||||||
state = status.State
|
state = status.State
|
||||||
lastStatus = status
|
lastStatus = status
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,22 +24,22 @@ func TestGetCommitStatuses(t *testing.T) {
|
|||||||
assert.Len(t, statuses, 5)
|
assert.Len(t, statuses, 5)
|
||||||
|
|
||||||
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
||||||
assert.Equal(t, CommitStatusPending, statuses[0].State)
|
assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL())
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
|
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
|
||||||
assert.Equal(t, CommitStatusWarning, statuses[1].State)
|
assert.Equal(t, structs.CommitStatusWarning, statuses[1].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL())
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
|
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
|
||||||
assert.Equal(t, CommitStatusSuccess, statuses[2].State)
|
assert.Equal(t, structs.CommitStatusSuccess, statuses[2].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL())
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, "ci/awesomeness", statuses[3].Context)
|
assert.Equal(t, "ci/awesomeness", statuses[3].Context)
|
||||||
assert.Equal(t, CommitStatusFailure, statuses[3].State)
|
assert.Equal(t, structs.CommitStatusFailure, statuses[3].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL())
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, "deploy/awesomeness", statuses[4].Context)
|
assert.Equal(t, "deploy/awesomeness", statuses[4].Context)
|
||||||
assert.Equal(t, CommitStatusError, statuses[4].State)
|
assert.Equal(t, structs.CommitStatusError, statuses[4].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL())
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,6 +381,7 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
|
|||||||
apiIssue := &api.Issue{
|
apiIssue := &api.Issue{
|
||||||
ID: issue.ID,
|
ID: issue.ID,
|
||||||
URL: issue.APIURL(),
|
URL: issue.APIURL(),
|
||||||
|
HTMLURL: issue.HTMLURL(),
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Poster: issue.Poster.APIFormat(),
|
Poster: issue.Poster.APIFormat(),
|
||||||
Title: issue.Title,
|
Title: issue.Title,
|
||||||
@@ -402,11 +403,12 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
|
|||||||
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
|
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue.loadMilestone(e)
|
||||||
if issue.Milestone != nil {
|
if issue.Milestone != nil {
|
||||||
apiIssue.Milestone = issue.Milestone.APIFormat()
|
apiIssue.Milestone = issue.Milestone.APIFormat()
|
||||||
}
|
}
|
||||||
issue.loadAssignees(e)
|
|
||||||
|
|
||||||
|
issue.loadAssignees(e)
|
||||||
if len(issue.Assignees) > 0 {
|
if len(issue.Assignees) > 0 {
|
||||||
for _, assignee := range issue.Assignees {
|
for _, assignee := range issue.Assignees {
|
||||||
apiIssue.Assignees = append(apiIssue.Assignees, assignee.APIFormat())
|
apiIssue.Assignees = append(apiIssue.Assignees, assignee.APIFormat())
|
||||||
@@ -436,7 +438,7 @@ func (issue *Issue) HashTag() string {
|
|||||||
|
|
||||||
// IsPoster returns true if given user by ID is the poster.
|
// IsPoster returns true if given user by ID is the poster.
|
||||||
func (issue *Issue) IsPoster(uid int64) bool {
|
func (issue *Issue) IsPoster(uid int64) bool {
|
||||||
return issue.PosterID == uid
|
return issue.OriginalAuthorID == 0 && issue.PosterID == uid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) hasLabel(e Engine, labelID int64) bool {
|
func (issue *Issue) hasLabel(e Engine, labelID int64) bool {
|
||||||
|
|||||||
@@ -376,6 +376,11 @@ func (comments CommentList) loadDependentIssues(e Engine) error {
|
|||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
if comment.DependentIssue == nil {
|
if comment.DependentIssue == nil {
|
||||||
comment.DependentIssue = issues[comment.DependentIssueID]
|
comment.DependentIssue = issues[comment.DependentIssueID]
|
||||||
|
if comment.DependentIssue != nil {
|
||||||
|
if err := comment.DependentIssue.loadRepo(e); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ var (
|
|||||||
|
|
||||||
// LoginViaLDAP queries if login/password is valid against the LDAP directory pool,
|
// LoginViaLDAP queries if login/password is valid against the LDAP directory pool,
|
||||||
// and create a local user if success when enabled.
|
// and create a local user if success when enabled.
|
||||||
func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) {
|
func LoginViaLDAP(user *User, login, password string, source *LoginSource) (*User, error) {
|
||||||
sr := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LoginDLDAP)
|
sr := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LoginDLDAP)
|
||||||
if sr == nil {
|
if sr == nil {
|
||||||
// User not in LDAP, do nothing
|
// User not in LDAP, do nothing
|
||||||
@@ -473,17 +473,25 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
|
|||||||
// Update User admin flag if exist
|
// Update User admin flag if exist
|
||||||
if isExist, err := IsUserExist(0, sr.Username); err != nil {
|
if isExist, err := IsUserExist(0, sr.Username); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if isExist &&
|
} else if isExist {
|
||||||
!user.ProhibitLogin && len(source.LDAP().AdminFilter) > 0 && user.IsAdmin != sr.IsAdmin {
|
if user == nil {
|
||||||
// Change existing admin flag only if AdminFilter option is set
|
user, err = GetUserByName(sr.Username)
|
||||||
user.IsAdmin = sr.IsAdmin
|
if err != nil {
|
||||||
err = UpdateUserCols(user, "is_admin")
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
}
|
||||||
|
if user != nil &&
|
||||||
|
!user.ProhibitLogin && len(source.LDAP().AdminFilter) > 0 && user.IsAdmin != sr.IsAdmin {
|
||||||
|
// Change existing admin flag only if AdminFilter option is set
|
||||||
|
user.IsAdmin = sr.IsAdmin
|
||||||
|
err = UpdateUserCols(user, "is_admin")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !autoRegister {
|
if user != nil {
|
||||||
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
|
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
|
||||||
return user, RewriteAllPublicKeys()
|
return user, RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
@@ -594,7 +602,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
|
|||||||
|
|
||||||
// LoginViaSMTP queries if login/password is valid against the SMTP,
|
// LoginViaSMTP queries if login/password is valid against the SMTP,
|
||||||
// and create a local user if success when enabled.
|
// and create a local user if success when enabled.
|
||||||
func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
|
func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPConfig) (*User, error) {
|
||||||
// Verify allowed domains.
|
// Verify allowed domains.
|
||||||
if len(cfg.AllowedDomains) > 0 {
|
if len(cfg.AllowedDomains) > 0 {
|
||||||
idx := strings.Index(login, "@")
|
idx := strings.Index(login, "@")
|
||||||
@@ -625,7 +633,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !autoRegister {
|
if user != nil {
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +665,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
|
|||||||
|
|
||||||
// LoginViaPAM queries if login/password is valid against the PAM,
|
// LoginViaPAM queries if login/password is valid against the PAM,
|
||||||
// and create a local user if success when enabled.
|
// and create a local user if success when enabled.
|
||||||
func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
|
func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig) (*User, error) {
|
||||||
if err := pam.Auth(cfg.ServiceName, login, password); err != nil {
|
if err := pam.Auth(cfg.ServiceName, login, password); err != nil {
|
||||||
if strings.Contains(err.Error(), "Authentication failure") {
|
if strings.Contains(err.Error(), "Authentication failure") {
|
||||||
return nil, ErrUserNotExist{0, login, 0}
|
return nil, ErrUserNotExist{0, login, 0}
|
||||||
@@ -665,7 +673,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !autoRegister {
|
if user != nil {
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +691,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExternalUserLogin attempts a login using external source types.
|
// ExternalUserLogin attempts a login using external source types.
|
||||||
func ExternalUserLogin(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) {
|
func ExternalUserLogin(user *User, login, password string, source *LoginSource) (*User, error) {
|
||||||
if !source.IsActived {
|
if !source.IsActived {
|
||||||
return nil, ErrLoginSourceNotActived
|
return nil, ErrLoginSourceNotActived
|
||||||
}
|
}
|
||||||
@@ -691,11 +699,11 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
|
|||||||
var err error
|
var err error
|
||||||
switch source.Type {
|
switch source.Type {
|
||||||
case LoginLDAP, LoginDLDAP:
|
case LoginLDAP, LoginDLDAP:
|
||||||
user, err = LoginViaLDAP(user, login, password, source, autoRegister)
|
user, err = LoginViaLDAP(user, login, password, source)
|
||||||
case LoginSMTP:
|
case LoginSMTP:
|
||||||
user, err = LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
|
user, err = LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig))
|
||||||
case LoginPAM:
|
case LoginPAM:
|
||||||
user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
|
user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig))
|
||||||
default:
|
default:
|
||||||
return nil, ErrUnsupportedLoginType
|
return nil, ErrUnsupportedLoginType
|
||||||
}
|
}
|
||||||
@@ -775,7 +783,7 @@ func UserSignIn(username, password string) (*User, error) {
|
|||||||
return nil, ErrLoginSourceNotExist{user.LoginSource}
|
return nil, ErrLoginSourceNotExist{user.LoginSource}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExternalUserLogin(user, user.LoginName, password, &source, false)
|
return ExternalUserLogin(user, user.LoginName, password, &source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,7 +797,7 @@ func UserSignIn(username, password string) (*User, error) {
|
|||||||
// don't try to authenticate against OAuth2 and SSPI sources here
|
// don't try to authenticate against OAuth2 and SSPI sources here
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
authUser, err := ExternalUserLogin(nil, username, password, source, true)
|
authUser, err := ExternalUserLogin(nil, username, password, source)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return authUser, nil
|
return authUser, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const (
|
|||||||
PullRequestStatusChecking
|
PullRequestStatusChecking
|
||||||
PullRequestStatusMergeable
|
PullRequestStatusMergeable
|
||||||
PullRequestStatusManuallyMerged
|
PullRequestStatusManuallyMerged
|
||||||
|
PullRequestStatusError
|
||||||
)
|
)
|
||||||
|
|
||||||
// PullRequest represents relation between pull request and repositories.
|
// PullRequest represents relation between pull request and repositories.
|
||||||
@@ -384,6 +385,13 @@ func (pr *PullRequest) GetDefaultSquashMessage() string {
|
|||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
if err := pr.LoadBaseRepo(); err != nil {
|
||||||
|
log.Error("LoadBaseRepo: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if pr.BaseRepo.UnitEnabled(UnitTypeExternalTracker) {
|
||||||
|
return fmt.Sprintf("%s (!%d)", pr.Issue.Title, pr.Issue.Index)
|
||||||
|
}
|
||||||
return fmt.Sprintf("%s (#%d)", pr.Issue.Title, pr.Issue.Index)
|
return fmt.Sprintf("%s (#%d)", pr.Issue.Title, pr.Issue.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +521,7 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pr.Status != PullRequestStatusChecking {
|
if pr.Status != PullRequestStatusChecking {
|
||||||
mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
|
mergeable := !(pr.Status == PullRequestStatusConflict || pr.Status == PullRequestStatusError) && !pr.IsWorkInProgress()
|
||||||
apiPullRequest.Mergeable = mergeable
|
apiPullRequest.Mergeable = mergeable
|
||||||
}
|
}
|
||||||
if pr.HasMerged {
|
if pr.HasMerged {
|
||||||
|
|||||||
@@ -124,41 +124,43 @@ func generateRepoCommit(e Engine, repo, templateRepo, generateRepo *Repository,
|
|||||||
return fmt.Errorf("checkGiteaTemplate: %v", err)
|
return fmt.Errorf("checkGiteaTemplate: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Remove(gt.Path); err != nil {
|
if gt != nil {
|
||||||
return fmt.Errorf("remove .giteatemplate: %v", err)
|
if err := os.Remove(gt.Path); err != nil {
|
||||||
}
|
return fmt.Errorf("remove .giteatemplate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid walking tree if there are no globs
|
// Avoid walking tree if there are no globs
|
||||||
if len(gt.Globs()) > 0 {
|
if len(gt.Globs()) > 0 {
|
||||||
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
|
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
|
||||||
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
|
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
|
||||||
if walkErr != nil {
|
if walkErr != nil {
|
||||||
return walkErr
|
return walkErr
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
|
|
||||||
for _, g := range gt.Globs() {
|
|
||||||
if g.Match(base) {
|
|
||||||
content, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ioutil.WriteFile(path,
|
|
||||||
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
|
|
||||||
0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
|
||||||
|
for _, g := range gt.Globs() {
|
||||||
|
if g.Match(base) {
|
||||||
|
content, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ioutil.WriteFile(path,
|
||||||
|
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
|
||||||
|
0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -503,7 +503,7 @@ func (u *User) ValidatePassword(passwd string) bool {
|
|||||||
|
|
||||||
// IsPasswordSet checks if the password is set or left empty
|
// IsPasswordSet checks if the password is set or left empty
|
||||||
func (u *User) IsPasswordSet() bool {
|
func (u *User) IsPasswordSet() bool {
|
||||||
return len(u.Passwd) > 0
|
return !u.ValidatePassword("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadAvatar saves custom avatar for user.
|
// UploadAvatar saves custom avatar for user.
|
||||||
@@ -1760,6 +1760,15 @@ func SyncExternalUsers(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(sr) == 0 {
|
||||||
|
if !s.LDAP().AllowDeactivateAll {
|
||||||
|
log.Error("LDAP search found no entries but did not report an error. Refusing to deactivate all users")
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
log.Warn("LDAP search found no entries but did not report an error. All users will be deactivated as per settings")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, su := range sr {
|
for _, su := range sr {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type AuthenticationForm struct {
|
|||||||
SearchPageSize int
|
SearchPageSize int
|
||||||
Filter string
|
Filter string
|
||||||
AdminFilter string
|
AdminFilter string
|
||||||
|
AllowDeactivateAll bool
|
||||||
IsActive bool
|
IsActive bool
|
||||||
IsSyncEnabled bool
|
IsSyncEnabled bool
|
||||||
SMTPAuth string
|
SMTPAuth string
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ type Source struct {
|
|||||||
Filter string // Query filter to validate entry
|
Filter string // Query filter to validate entry
|
||||||
AdminFilter string // Query filter to check if user is admin
|
AdminFilter string // Query filter to check if user is admin
|
||||||
Enabled bool // if this source is disabled
|
Enabled bool // if this source is disabled
|
||||||
|
AllowDeactivateAll bool // Allow an empty search response to deactivate all users from this source
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchResult : user data
|
// SearchResult : user data
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ func (ctx *Context) RedirectToFirst(location ...string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(loc)
|
u, err := url.Parse(loc)
|
||||||
if err != nil || (u.Scheme != "" && !strings.HasPrefix(strings.ToLower(loc), strings.ToLower(setting.AppURL))) {
|
if err != nil || ((u.Scheme != "" || u.Host != "") && !strings.HasPrefix(strings.ToLower(loc), strings.ToLower(setting.AppURL))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,12 +91,12 @@ func (r *Repository) CanUseTimetracker(issue *models.Issue, user *models.User) b
|
|||||||
// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
|
// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
|
||||||
isAssigned, _ := models.IsUserAssignedToIssue(issue, user)
|
isAssigned, _ := models.IsUserAssignedToIssue(issue, user)
|
||||||
return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() ||
|
return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() ||
|
||||||
r.Permission.CanWrite(models.UnitTypeIssues) || issue.IsPoster(user.ID) || isAssigned)
|
r.Permission.CanWriteIssuesOrPulls(issue.IsPull) || issue.IsPoster(user.ID) || isAssigned)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanCreateIssueDependencies returns whether or not a user can create dependencies.
|
// CanCreateIssueDependencies returns whether or not a user can create dependencies.
|
||||||
func (r *Repository) CanCreateIssueDependencies(user *models.User) bool {
|
func (r *Repository) CanCreateIssueDependencies(user *models.User, isPull bool) bool {
|
||||||
return r.Permission.CanWrite(models.UnitTypeIssues) && r.Repository.IsDependenciesEnabled()
|
return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommitsCount returns cached commit count for current view
|
// GetCommitsCount returns cached commit count for current view
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package graceful
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -99,12 +100,25 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string, serve ServeFuncti
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.Certificates = make([]tls.Certificate, 1)
|
config.Certificates = make([]tls.Certificate, 1)
|
||||||
var err error
|
|
||||||
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
|
certPEMBlock, err := ioutil.ReadFile(certFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, err)
|
log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyPEMBlock, err := ioutil.ReadFile(keyFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to load https key file %s for %s:%s: %v", keyFile, srv.network, srv.address, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Certificates[0], err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to create certificate from cert file %s and key file %s for %s:%s: %v", certFile, keyFile, srv.network, srv.address, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return srv.ListenAndServeTLSConfig(config, serve)
|
return srv.ListenAndServeTLSConfig(config, serve)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ func (g *GiteaASTTransformer) Transform(node *ast.Document, reader text.Reader,
|
|||||||
}
|
}
|
||||||
link = []byte(giteautil.URLJoin(pc.Get(urlPrefixKey).(string), lnk))
|
link = []byte(giteautil.URLJoin(pc.Get(urlPrefixKey).(string), lnk))
|
||||||
}
|
}
|
||||||
|
if len(link) > 0 && link[0] == '#' {
|
||||||
|
link = []byte("#user-content-" + string(link)[1:])
|
||||||
|
}
|
||||||
v.Destination = link
|
v.Destination = link
|
||||||
}
|
}
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
|
|||||||
common.FootnoteExtension,
|
common.FootnoteExtension,
|
||||||
extension.NewTypographer(
|
extension.NewTypographer(
|
||||||
extension.WithTypographicSubstitutions(extension.TypographicSubstitutions{
|
extension.WithTypographicSubstitutions(extension.TypographicSubstitutions{
|
||||||
extension.EnDash: nil,
|
extension.EnDash: nil,
|
||||||
extension.EmDash: nil,
|
extension.EmDash: nil,
|
||||||
|
extension.Ellipsis: nil,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func NewSanitizer() {
|
|||||||
func ReplaceSanitizer() {
|
func ReplaceSanitizer() {
|
||||||
sanitizer.policy = bluemonday.UGCPolicy()
|
sanitizer.policy = bluemonday.UGCPolicy()
|
||||||
// We only want to allow HighlightJS specific classes for code blocks
|
// We only want to allow HighlightJS specific classes for code blocks
|
||||||
sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^language-\w+$`)).OnElements("code")
|
sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^language-[\w-]+$`)).OnElements("code")
|
||||||
|
|
||||||
// Checkboxes
|
// Checkboxes
|
||||||
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
|
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type Comment struct {
|
|||||||
PosterName string
|
PosterName string
|
||||||
PosterEmail string
|
PosterEmail string
|
||||||
Created time.Time
|
Created time.Time
|
||||||
|
Updated time.Time
|
||||||
Content string
|
Content string
|
||||||
Reactions *Reactions
|
Reactions *Reactions
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type Issue struct {
|
|||||||
State string // closed, open
|
State string // closed, open
|
||||||
IsLocked bool
|
IsLocked bool
|
||||||
Created time.Time
|
Created time.Time
|
||||||
|
Updated time.Time
|
||||||
Closed *time.Time
|
Closed *time.Time
|
||||||
Labels []*Label
|
Labels []*Label
|
||||||
Reactions *Reactions
|
Reactions *Reactions
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type PullRequest struct {
|
|||||||
Milestone string
|
Milestone string
|
||||||
State string
|
State string
|
||||||
Created time.Time
|
Created time.Time
|
||||||
|
Updated time.Time
|
||||||
Closed *time.Time
|
Closed *time.Time
|
||||||
Labels []*Label
|
Labels []*Label
|
||||||
PatchURL string
|
PatchURL string
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error {
|
|||||||
MilestoneID: milestoneID,
|
MilestoneID: milestoneID,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
CreatedUnix: timeutil.TimeStamp(issue.Created.Unix()),
|
CreatedUnix: timeutil.TimeStamp(issue.Created.Unix()),
|
||||||
|
UpdatedUnix: timeutil.TimeStamp(issue.Updated.Unix()),
|
||||||
}
|
}
|
||||||
|
|
||||||
userid, ok := g.userMap[issue.PosterID]
|
userid, ok := g.userMap[issue.PosterID]
|
||||||
@@ -406,6 +407,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
|
|||||||
Type: models.CommentTypeComment,
|
Type: models.CommentTypeComment,
|
||||||
Content: comment.Content,
|
Content: comment.Content,
|
||||||
CreatedUnix: timeutil.TimeStamp(comment.Created.Unix()),
|
CreatedUnix: timeutil.TimeStamp(comment.Created.Unix()),
|
||||||
|
UpdatedUnix: timeutil.TimeStamp(comment.Updated.Unix()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if userid > 0 {
|
if userid > 0 {
|
||||||
@@ -574,6 +576,7 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
|
|||||||
IsLocked: pr.IsLocked,
|
IsLocked: pr.IsLocked,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
CreatedUnix: timeutil.TimeStamp(pr.Created.Unix()),
|
CreatedUnix: timeutil.TimeStamp(pr.Created.Unix()),
|
||||||
|
UpdatedUnix: timeutil.TimeStamp(pr.Updated.Unix()),
|
||||||
}
|
}
|
||||||
|
|
||||||
userid, ok := g.userMap[pr.PosterID]
|
userid, ok := g.userMap[pr.PosterID]
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import (
|
|||||||
var (
|
var (
|
||||||
_ base.Downloader = &GithubDownloaderV3{}
|
_ base.Downloader = &GithubDownloaderV3{}
|
||||||
_ base.DownloaderFactory = &GithubDownloaderV3Factory{}
|
_ base.DownloaderFactory = &GithubDownloaderV3Factory{}
|
||||||
|
// GithubLimitRateRemaining limit to wait for new rate to apply
|
||||||
|
GithubLimitRateRemaining = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -115,7 +117,7 @@ func (g *GithubDownloaderV3) SetContext(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubDownloaderV3) sleep() {
|
func (g *GithubDownloaderV3) sleep() {
|
||||||
for g.rate != nil && g.rate.Remaining <= 0 {
|
for g.rate != nil && g.rate.Remaining <= GithubLimitRateRemaining {
|
||||||
timer := time.NewTimer(time.Until(g.rate.Reset.Time))
|
timer := time.NewTimer(time.Until(g.rate.Reset.Time))
|
||||||
select {
|
select {
|
||||||
case <-g.ctx.Done():
|
case <-g.ctx.Done():
|
||||||
@@ -124,15 +126,24 @@ func (g *GithubDownloaderV3) sleep() {
|
|||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
}
|
}
|
||||||
|
|
||||||
rates, _, err := g.client.RateLimits(g.ctx)
|
err := g.RefreshRate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("g.client.RateLimits: %s", err)
|
log.Error("g.client.RateLimits: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.rate = rates.GetCore()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefreshRate update the current rate (doesn't count in rate limit)
|
||||||
|
func (g *GithubDownloaderV3) RefreshRate() error {
|
||||||
|
rates, _, err := g.client.RateLimits(g.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.rate = rates.GetCore()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetRepoInfo returns a repository information
|
// GetRepoInfo returns a repository information
|
||||||
func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
|
func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
|
||||||
g.sleep()
|
g.sleep()
|
||||||
@@ -385,6 +396,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
|
|||||||
Milestone: milestone,
|
Milestone: milestone,
|
||||||
State: *issue.State,
|
State: *issue.State,
|
||||||
Created: *issue.CreatedAt,
|
Created: *issue.CreatedAt,
|
||||||
|
Updated: *issue.UpdatedAt,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
Reactions: reactions,
|
Reactions: reactions,
|
||||||
Closed: issue.ClosedAt,
|
Closed: issue.ClosedAt,
|
||||||
@@ -428,6 +440,7 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er
|
|||||||
PosterEmail: email,
|
PosterEmail: email,
|
||||||
Content: *comment.Body,
|
Content: *comment.Body,
|
||||||
Created: *comment.CreatedAt,
|
Created: *comment.CreatedAt,
|
||||||
|
Updated: *comment.UpdatedAt,
|
||||||
Reactions: reactions,
|
Reactions: reactions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -523,6 +536,7 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
|
|||||||
Milestone: milestone,
|
Milestone: milestone,
|
||||||
State: *pr.State,
|
State: *pr.State,
|
||||||
Created: *pr.CreatedAt,
|
Created: *pr.CreatedAt,
|
||||||
|
Updated: *pr.UpdatedAt,
|
||||||
Closed: pr.ClosedAt,
|
Closed: pr.ClosedAt,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
Merged: merged,
|
Merged: merged,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package migrations
|
package migrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -62,7 +63,11 @@ func assertLabelEqual(t *testing.T, name, color, description string, label *base
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGitHubDownloadRepo(t *testing.T) {
|
func TestGitHubDownloadRepo(t *testing.T) {
|
||||||
downloader := NewGithubDownloaderV3("", "", "go-gitea", "test_repo")
|
GithubLimitRateRemaining = 3 //Wait at 3 remaining since we could have 3 CI in //
|
||||||
|
downloader := NewGithubDownloaderV3(os.Getenv("GITHUB_READ_TOKEN"), "", "go-gitea", "test_repo")
|
||||||
|
err := downloader.RefreshRate()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
repo, err := downloader.GetRepoInfo()
|
repo, err := downloader.GetRepoInfo()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, &base.Repository{
|
assert.EqualValues(t, &base.Repository{
|
||||||
@@ -157,6 +162,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterName: "guillep2k",
|
PosterName: "guillep2k",
|
||||||
State: "closed",
|
State: "closed",
|
||||||
Created: time.Date(2019, 11, 9, 17, 0, 29, 0, time.UTC),
|
Created: time.Date(2019, 11, 9, 17, 0, 29, 0, time.UTC),
|
||||||
|
Updated: time.Date(2019, 11, 12, 20, 29, 53, 0, time.UTC),
|
||||||
Labels: []*base.Label{
|
Labels: []*base.Label{
|
||||||
{
|
{
|
||||||
Name: "bug",
|
Name: "bug",
|
||||||
@@ -189,6 +195,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterName: "mrsdizzie",
|
PosterName: "mrsdizzie",
|
||||||
State: "closed",
|
State: "closed",
|
||||||
Created: time.Date(2019, 11, 12, 21, 0, 6, 0, time.UTC),
|
Created: time.Date(2019, 11, 12, 21, 0, 6, 0, time.UTC),
|
||||||
|
Updated: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC),
|
||||||
Labels: []*base.Label{
|
Labels: []*base.Label{
|
||||||
{
|
{
|
||||||
Name: "duplicate",
|
Name: "duplicate",
|
||||||
@@ -219,6 +226,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterID: 1669571,
|
PosterID: 1669571,
|
||||||
PosterName: "mrsdizzie",
|
PosterName: "mrsdizzie",
|
||||||
Created: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC),
|
Created: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC),
|
||||||
|
Updated: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC),
|
||||||
Content: "This is a comment",
|
Content: "This is a comment",
|
||||||
Reactions: &base.Reactions{
|
Reactions: &base.Reactions{
|
||||||
TotalCount: 1,
|
TotalCount: 1,
|
||||||
@@ -235,6 +243,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterID: 1669571,
|
PosterID: 1669571,
|
||||||
PosterName: "mrsdizzie",
|
PosterName: "mrsdizzie",
|
||||||
Created: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC),
|
Created: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC),
|
||||||
|
Updated: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC),
|
||||||
Content: "A second comment",
|
Content: "A second comment",
|
||||||
Reactions: &base.Reactions{
|
Reactions: &base.Reactions{
|
||||||
TotalCount: 0,
|
TotalCount: 0,
|
||||||
@@ -266,6 +275,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterName: "mrsdizzie",
|
PosterName: "mrsdizzie",
|
||||||
State: "closed",
|
State: "closed",
|
||||||
Created: time.Date(2019, 11, 12, 21, 21, 43, 0, time.UTC),
|
Created: time.Date(2019, 11, 12, 21, 21, 43, 0, time.UTC),
|
||||||
|
Updated: time.Date(2019, 11, 12, 21, 39, 28, 0, time.UTC),
|
||||||
Labels: []*base.Label{
|
Labels: []*base.Label{
|
||||||
{
|
{
|
||||||
Name: "documentation",
|
Name: "documentation",
|
||||||
@@ -302,6 +312,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
PosterName: "mrsdizzie",
|
PosterName: "mrsdizzie",
|
||||||
State: "open",
|
State: "open",
|
||||||
Created: time.Date(2019, 11, 12, 21, 54, 18, 0, time.UTC),
|
Created: time.Date(2019, 11, 12, 21, 54, 18, 0, time.UTC),
|
||||||
|
Updated: time.Date(2020, 1, 4, 11, 30, 1, 0, time.UTC),
|
||||||
Labels: []*base.Label{
|
Labels: []*base.Label{
|
||||||
{
|
{
|
||||||
Name: "bug",
|
Name: "bug",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package queue
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
@@ -33,6 +34,7 @@ type PersistableChannelQueueConfiguration struct {
|
|||||||
type PersistableChannelQueue struct {
|
type PersistableChannelQueue struct {
|
||||||
*ChannelQueue
|
*ChannelQueue
|
||||||
delayedStarter
|
delayedStarter
|
||||||
|
lock sync.Mutex
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,11 +84,12 @@ func NewRedisQueue(handle HandlerFunc, cfg, exemplar interface{}) (Queue, error)
|
|||||||
boostWorkers: config.BoostWorkers,
|
boostWorkers: config.BoostWorkers,
|
||||||
maxNumberOfWorkers: config.MaxWorkers,
|
maxNumberOfWorkers: config.MaxWorkers,
|
||||||
},
|
},
|
||||||
queueName: config.QueueName,
|
queueName: config.QueueName,
|
||||||
exemplar: exemplar,
|
exemplar: exemplar,
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
workers: config.Workers,
|
terminated: make(chan struct{}),
|
||||||
name: config.Name,
|
workers: config.Workers,
|
||||||
|
name: config.Name,
|
||||||
}
|
}
|
||||||
if len(dbs) == 0 {
|
if len(dbs) == 0 {
|
||||||
return nil, errors.New("no redis host specified")
|
return nil, errors.New("no redis host specified")
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ type WrappedQueueConfiguration struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type delayedStarter struct {
|
type delayedStarter struct {
|
||||||
lock sync.Mutex
|
|
||||||
internal Queue
|
internal Queue
|
||||||
underlying Type
|
underlying Type
|
||||||
cfg interface{}
|
cfg interface{}
|
||||||
@@ -62,7 +61,6 @@ func (q *delayedStarter) setInternal(atShutdown func(context.Context, func()), h
|
|||||||
queue, err := NewQueue(q.underlying, handle, q.cfg, exemplar)
|
queue, err := NewQueue(q.underlying, handle, q.cfg, exemplar)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
q.internal = queue
|
q.internal = queue
|
||||||
q.lock.Unlock()
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err.Error() != "resource temporarily unavailable" {
|
if err.Error() != "resource temporarily unavailable" {
|
||||||
@@ -90,6 +88,7 @@ func (q *delayedStarter) setInternal(atShutdown func(context.Context, func()), h
|
|||||||
// WrappedQueue wraps a delayed starting queue
|
// WrappedQueue wraps a delayed starting queue
|
||||||
type WrappedQueue struct {
|
type WrappedQueue struct {
|
||||||
delayedStarter
|
delayedStarter
|
||||||
|
lock sync.Mutex
|
||||||
handle HandlerFunc
|
handle HandlerFunc
|
||||||
exemplar interface{}
|
exemplar interface{}
|
||||||
channel chan Data
|
channel chan Data
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*m
|
|||||||
refMarked[key] = true
|
refMarked[key] = true
|
||||||
|
|
||||||
// FIXME: this kind of condition is all over the code, it should be consolidated in a single place
|
// FIXME: this kind of condition is all over the code, it should be consolidated in a single place
|
||||||
canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWrite(models.UnitTypeIssues) || refIssue.PosterID == doer.ID
|
canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWriteIssuesOrPulls(refIssue.IsPull) || refIssue.PosterID == doer.ID
|
||||||
cancomment := canclose || perm.CanRead(models.UnitTypeIssues)
|
cancomment := canclose || perm.CanReadIssuesOrPulls(refIssue.IsPull)
|
||||||
|
|
||||||
// Don't proceed if the user can't comment
|
// Don't proceed if the user can't comment
|
||||||
if !cancomment {
|
if !cancomment {
|
||||||
@@ -137,9 +137,11 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*m
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close := (ref.Action == references.XRefActionCloses)
|
||||||
if err := changeIssueStatus(refRepo, refIssue, doer, ref.Action == references.XRefActionCloses); err != nil {
|
if close != refIssue.IsClosed {
|
||||||
return err
|
if err := changeIssueStatus(refRepo, refIssue, doer, close); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
|
|||||||
// If we aren't branching to a new branch, make sure user can commit to the given branch
|
// If we aren't branching to a new branch, make sure user can commit to the given branch
|
||||||
if opts.NewBranch != opts.OldBranch {
|
if opts.NewBranch != opts.OldBranch {
|
||||||
newBranch, err := repo.GetBranch(opts.NewBranch)
|
newBranch, err := repo.GetBranch(opts.NewBranch)
|
||||||
if git.IsErrNotExist(err) {
|
if err != nil && !git.IsErrBranchNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if newBranch != nil {
|
if newBranch != nil {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ var (
|
|||||||
MaxGitDiffLines int
|
MaxGitDiffLines int
|
||||||
MaxGitDiffLineCharacters int
|
MaxGitDiffLineCharacters int
|
||||||
MaxGitDiffFiles int
|
MaxGitDiffFiles int
|
||||||
|
VerbosePush bool
|
||||||
|
VerbosePushDelay time.Duration
|
||||||
GCArgs []string `ini:"GC_ARGS" delim:" "`
|
GCArgs []string `ini:"GC_ARGS" delim:" "`
|
||||||
EnableAutoGitWireProtocol bool
|
EnableAutoGitWireProtocol bool
|
||||||
Timeout struct {
|
Timeout struct {
|
||||||
@@ -36,6 +38,8 @@ var (
|
|||||||
MaxGitDiffLines: 1000,
|
MaxGitDiffLines: 1000,
|
||||||
MaxGitDiffLineCharacters: 5000,
|
MaxGitDiffLineCharacters: 5000,
|
||||||
MaxGitDiffFiles: 100,
|
MaxGitDiffFiles: 100,
|
||||||
|
VerbosePush: true,
|
||||||
|
VerbosePushDelay: 5 * time.Second,
|
||||||
GCArgs: []string{},
|
GCArgs: []string{},
|
||||||
EnableAutoGitWireProtocol: true,
|
EnableAutoGitWireProtocol: true,
|
||||||
Timeout: struct {
|
Timeout: struct {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package setting
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -44,7 +45,7 @@ func GetQueueSettings(name string) QueueSettings {
|
|||||||
q := QueueSettings{}
|
q := QueueSettings{}
|
||||||
sec := Cfg.Section("queue." + name)
|
sec := Cfg.Section("queue." + name)
|
||||||
// DataDir is not directly inheritable
|
// DataDir is not directly inheritable
|
||||||
q.DataDir = path.Join(Queue.DataDir, name)
|
q.DataDir = filepath.Join(Queue.DataDir, name)
|
||||||
// QueueName is not directly inheritable either
|
// QueueName is not directly inheritable either
|
||||||
q.QueueName = name + Queue.QueueName
|
q.QueueName = name + Queue.QueueName
|
||||||
for _, key := range sec.Keys() {
|
for _, key := range sec.Keys() {
|
||||||
@@ -55,8 +56,8 @@ func GetQueueSettings(name string) QueueSettings {
|
|||||||
q.QueueName = key.MustString(q.QueueName)
|
q.QueueName = key.MustString(q.QueueName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !path.IsAbs(q.DataDir) {
|
if !filepath.IsAbs(q.DataDir) {
|
||||||
q.DataDir = path.Join(AppDataPath, q.DataDir)
|
q.DataDir = filepath.Join(AppDataPath, q.DataDir)
|
||||||
}
|
}
|
||||||
sec.Key("DATADIR").SetValue(q.DataDir)
|
sec.Key("DATADIR").SetValue(q.DataDir)
|
||||||
// The rest are...
|
// The rest are...
|
||||||
@@ -82,8 +83,8 @@ func GetQueueSettings(name string) QueueSettings {
|
|||||||
func NewQueueService() {
|
func NewQueueService() {
|
||||||
sec := Cfg.Section("queue")
|
sec := Cfg.Section("queue")
|
||||||
Queue.DataDir = sec.Key("DATADIR").MustString("queues/")
|
Queue.DataDir = sec.Key("DATADIR").MustString("queues/")
|
||||||
if !path.IsAbs(Queue.DataDir) {
|
if !filepath.IsAbs(Queue.DataDir) {
|
||||||
Queue.DataDir = path.Join(AppDataPath, Queue.DataDir)
|
Queue.DataDir = filepath.Join(AppDataPath, Queue.DataDir)
|
||||||
}
|
}
|
||||||
Queue.Length = sec.Key("LENGTH").MustInt(20)
|
Queue.Length = sec.Key("LENGTH").MustInt(20)
|
||||||
Queue.BatchLength = sec.Key("BATCH_LENGTH").MustInt(20)
|
Queue.BatchLength = sec.Key("BATCH_LENGTH").MustInt(20)
|
||||||
|
|||||||
@@ -554,6 +554,12 @@ func NewContext() {
|
|||||||
Protocol = HTTPS
|
Protocol = HTTPS
|
||||||
CertFile = sec.Key("CERT_FILE").String()
|
CertFile = sec.Key("CERT_FILE").String()
|
||||||
KeyFile = sec.Key("KEY_FILE").String()
|
KeyFile = sec.Key("KEY_FILE").String()
|
||||||
|
if !filepath.IsAbs(CertFile) && len(CertFile) > 0 {
|
||||||
|
CertFile = filepath.Join(CustomPath, CertFile)
|
||||||
|
}
|
||||||
|
if !filepath.IsAbs(KeyFile) && len(KeyFile) > 0 {
|
||||||
|
KeyFile = filepath.Join(CustomPath, KeyFile)
|
||||||
|
}
|
||||||
case "fcgi":
|
case "fcgi":
|
||||||
Protocol = FCGI
|
Protocol = FCGI
|
||||||
case "fcgi+unix":
|
case "fcgi+unix":
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package structs // import "code.gitea.io/gitea/modules/structs"
|
package structs // import "code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|||||||
63
modules/structs/commit_status.go
Normal file
63
modules/structs/commit_status.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2020 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 structs
|
||||||
|
|
||||||
|
// CommitStatusState holds the state of a Status
|
||||||
|
// It can be "pending", "success", "error", "failure", and "warning"
|
||||||
|
type CommitStatusState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CommitStatusPending is for when the Status is Pending
|
||||||
|
CommitStatusPending CommitStatusState = "pending"
|
||||||
|
// CommitStatusSuccess is for when the Status is Success
|
||||||
|
CommitStatusSuccess CommitStatusState = "success"
|
||||||
|
// CommitStatusError is for when the Status is Error
|
||||||
|
CommitStatusError CommitStatusState = "error"
|
||||||
|
// CommitStatusFailure is for when the Status is Failure
|
||||||
|
CommitStatusFailure CommitStatusState = "failure"
|
||||||
|
// CommitStatusWarning is for when the Status is Warning
|
||||||
|
CommitStatusWarning CommitStatusState = "warning"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NoBetterThan returns true if this State is no better than the given State
|
||||||
|
func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool {
|
||||||
|
switch css {
|
||||||
|
case CommitStatusError:
|
||||||
|
return true
|
||||||
|
case CommitStatusFailure:
|
||||||
|
return css2 != CommitStatusError
|
||||||
|
case CommitStatusWarning:
|
||||||
|
return css2 != CommitStatusError && css2 != CommitStatusFailure
|
||||||
|
case CommitStatusPending:
|
||||||
|
return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning
|
||||||
|
default:
|
||||||
|
return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning && css2 != CommitStatusPending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPending represents if commit status state is pending
|
||||||
|
func (css CommitStatusState) IsPending() bool {
|
||||||
|
return css == CommitStatusPending
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSuccess represents if commit status state is success
|
||||||
|
func (css CommitStatusState) IsSuccess() bool {
|
||||||
|
return css == CommitStatusSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsError represents if commit status state is error
|
||||||
|
func (css CommitStatusState) IsError() bool {
|
||||||
|
return css == CommitStatusError
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFailure represents if commit status state is failure
|
||||||
|
func (css CommitStatusState) IsFailure() bool {
|
||||||
|
return css == CommitStatusFailure
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsWarning represents if commit status state is warning
|
||||||
|
func (css CommitStatusState) IsWarning() bool {
|
||||||
|
return css == CommitStatusWarning
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ type RepositoryMeta struct {
|
|||||||
type Issue struct {
|
type Issue struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
Index int64 `json:"number"`
|
Index int64 `json:"number"`
|
||||||
Poster *User `json:"user"`
|
Poster *User `json:"user"`
|
||||||
OriginalAuthor string `json:"original_author"`
|
OriginalAuthor string `json:"original_author"`
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ func (q *UniqueQueue) AddFunc(id interface{}, fn func()) {
|
|||||||
idStr := com.ToStr(id)
|
idStr := com.ToStr(id)
|
||||||
q.table.lock.Lock()
|
q.table.lock.Lock()
|
||||||
if _, ok := q.table.pool[idStr]; ok {
|
if _, ok := q.table.pool[idStr]; ok {
|
||||||
|
q.table.lock.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.table.pool[idStr] = struct{}{}
|
q.table.pool[idStr] = struct{}{}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) {
|
|||||||
Title: issueTitle,
|
Title: issueTitle,
|
||||||
HideAvatar: "0",
|
HideAvatar: "0",
|
||||||
SingleTitle: "view issue",
|
SingleTitle: "view issue",
|
||||||
SingleURL: p.Issue.URL,
|
SingleURL: p.Issue.HTMLURL,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPa
|
|||||||
{
|
{
|
||||||
Title: text,
|
Title: text,
|
||||||
Description: attachmentText,
|
Description: attachmentText,
|
||||||
URL: p.Issue.URL,
|
URL: p.Issue.HTMLURL,
|
||||||
Color: color,
|
Color: color,
|
||||||
Author: DiscordEmbedAuthor{
|
Author: DiscordEmbedAuthor{
|
||||||
Name: p.Sender.UserName,
|
Name: p.Sender.UserName,
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) {
|
|||||||
Targets: []MSTeamsActionTarget{
|
Targets: []MSTeamsActionTarget{
|
||||||
{
|
{
|
||||||
Os: "default",
|
Os: "default",
|
||||||
URI: p.Issue.URL,
|
URI: p.Issue.HTMLURL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload
|
|||||||
pl.Attachments = []SlackAttachment{{
|
pl.Attachments = []SlackAttachment{{
|
||||||
Color: fmt.Sprintf("%x", color),
|
Color: fmt.Sprintf("%x", color),
|
||||||
Title: issueTitle,
|
Title: issueTitle,
|
||||||
TitleLink: p.Issue.URL,
|
TitleLink: p.Issue.HTMLURL,
|
||||||
Text: attachmentText,
|
Text: attachmentText,
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@@ -232,8 +232,10 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
|
|||||||
Username: slack.Username,
|
Username: slack.Username,
|
||||||
IconURL: slack.IconURL,
|
IconURL: slack.IconURL,
|
||||||
Attachments: []SlackAttachment{{
|
Attachments: []SlackAttachment{{
|
||||||
Color: slack.Color,
|
Color: slack.Color,
|
||||||
Text: attachmentText,
|
Title: p.Repo.HTMLURL,
|
||||||
|
TitleLink: p.Repo.HTMLURL,
|
||||||
|
Text: attachmentText,
|
||||||
}},
|
}},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -289,12 +291,11 @@ func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackM
|
|||||||
func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
|
func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||||
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
||||||
var text, title, attachmentText string
|
var text string
|
||||||
|
|
||||||
switch p.Action {
|
switch p.Action {
|
||||||
case api.HookRepoCreated:
|
case api.HookRepoCreated:
|
||||||
text = fmt.Sprintf("[%s] Repository created by %s", repoLink, senderLink)
|
text = fmt.Sprintf("[%s] Repository created by %s", repoLink, senderLink)
|
||||||
title = p.Repository.HTMLURL
|
|
||||||
case api.HookRepoDeleted:
|
case api.HookRepoDeleted:
|
||||||
text = fmt.Sprintf("[%s] Repository deleted by %s", repoLink, senderLink)
|
text = fmt.Sprintf("[%s] Repository deleted by %s", repoLink, senderLink)
|
||||||
}
|
}
|
||||||
@@ -304,12 +305,6 @@ func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*Sla
|
|||||||
Text: text,
|
Text: text,
|
||||||
Username: slack.Username,
|
Username: slack.Username,
|
||||||
IconURL: slack.IconURL,
|
IconURL: slack.IconURL,
|
||||||
Attachments: []SlackAttachment{{
|
|
||||||
Color: slack.Color,
|
|
||||||
Title: title,
|
|
||||||
TitleLink: title,
|
|
||||||
Text: attachmentText,
|
|
||||||
}},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,25 @@ func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTelegramPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*TelegramPayload, error) {
|
||||||
|
var text, attachmentText string
|
||||||
|
switch p.Action {
|
||||||
|
case api.HookIssueSynchronized:
|
||||||
|
action, err := parseHookPullRequestEventType(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
text = fmt.Sprintf("[%s] Pull request review %s: #%d %s", p.Repository.FullName, action, p.Index, p.PullRequest.Title)
|
||||||
|
attachmentText = p.Review.Content
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &TelegramPayload{
|
||||||
|
Message: text + "\n" + attachmentText,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getTelegramRepositoryPayload(p *api.RepositoryPayload) (*TelegramPayload, error) {
|
func getTelegramRepositoryPayload(p *api.RepositoryPayload) (*TelegramPayload, error) {
|
||||||
var title string
|
var title string
|
||||||
switch p.Action {
|
switch p.Action {
|
||||||
@@ -192,6 +211,8 @@ func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string
|
|||||||
return getTelegramPushPayload(p.(*api.PushPayload))
|
return getTelegramPushPayload(p.(*api.PushPayload))
|
||||||
case models.HookEventPullRequest:
|
case models.HookEventPullRequest:
|
||||||
return getTelegramPullRequestPayload(p.(*api.PullRequestPayload))
|
return getTelegramPullRequestPayload(p.(*api.PullRequestPayload))
|
||||||
|
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment:
|
||||||
|
return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
|
||||||
case models.HookEventRepository:
|
case models.HookEventRepository:
|
||||||
return getTelegramRepositoryPayload(p.(*api.RepositoryPayload))
|
return getTelegramRepositoryPayload(p.(*api.RepositoryPayload))
|
||||||
case models.HookEventRelease:
|
case models.HookEventRelease:
|
||||||
|
|||||||
@@ -2035,4 +2035,3 @@ error.probable_bad_default_signature=VAROVÁNÍ! Ačkoli výchozí klíč má to
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Nejste oprávněni přistupovat k žádné části tohoto repozitáře.
|
error.no_unit_allowed_repo=Nejste oprávněni přistupovat k žádné části tohoto repozitáře.
|
||||||
error.unit_not_allowed=Nejste oprávněni přistupovat k této části repozitáře.
|
error.unit_not_allowed=Nejste oprávněni přistupovat k této části repozitáře.
|
||||||
|
|
||||||
|
|||||||
@@ -606,7 +606,7 @@ clone_helper=Benötigst du Hilfe beim Klonen? Öffne die <a target="_blank" rel=
|
|||||||
fork_repo=Repository forken
|
fork_repo=Repository forken
|
||||||
fork_from=Fork von
|
fork_from=Fork von
|
||||||
fork_visibility_helper=Die Sichtbarkeit eines geforkten Repositorys kann nicht geändert werden.
|
fork_visibility_helper=Die Sichtbarkeit eines geforkten Repositorys kann nicht geändert werden.
|
||||||
use_template=Verwende dieses Template
|
use_template=Dieses Template verwenden
|
||||||
generate_repo=Repository erstellen
|
generate_repo=Repository erstellen
|
||||||
generate_from=Erstelle aus
|
generate_from=Erstelle aus
|
||||||
repo_desc=Beschreibung
|
repo_desc=Beschreibung
|
||||||
@@ -1062,6 +1062,8 @@ pulls.no_merge_desc=Dieser Pull-Request kann nicht gemerged werden, da keine Mer
|
|||||||
pulls.no_merge_helper=Aktiviere Mergeoptionen in den Repositoryeinstellungen oder merge den Pull-Request manuell.
|
pulls.no_merge_helper=Aktiviere Mergeoptionen in den Repositoryeinstellungen oder merge den Pull-Request manuell.
|
||||||
pulls.no_merge_wip=Dieser Pull Request kann nicht zusammengeführt werden, da er als Work In Progress gekennzeichnet ist.
|
pulls.no_merge_wip=Dieser Pull Request kann nicht zusammengeführt werden, da er als Work In Progress gekennzeichnet ist.
|
||||||
pulls.no_merge_status_check=Dieser Pull-Request kann nicht zusammengeführt werden, da nicht alle erforderlichen Statusprüfungen erfolgreich waren.
|
pulls.no_merge_status_check=Dieser Pull-Request kann nicht zusammengeführt werden, da nicht alle erforderlichen Statusprüfungen erfolgreich waren.
|
||||||
|
pulls.no_merge_not_ready=Dieser Pull-Request kann nicht zusammengeführt werden, überprüfe den Reviewstatus und die Statusprüfungen.
|
||||||
|
pulls.no_merge_access=Du bist nicht berechtigt, diesen Pull-Request zu Mergen.
|
||||||
pulls.merge_pull_request=Pull-Request zusammenführen
|
pulls.merge_pull_request=Pull-Request zusammenführen
|
||||||
pulls.rebase_merge_pull_request=Rebase und Mergen
|
pulls.rebase_merge_pull_request=Rebase und Mergen
|
||||||
pulls.rebase_merge_commit_pull_request=Rebasen und Mergen (--no-ff)
|
pulls.rebase_merge_commit_pull_request=Rebasen und Mergen (--no-ff)
|
||||||
@@ -1412,6 +1414,8 @@ settings.protect_approvals_whitelist_enabled=Freigaben auf Benutzer oder Teams a
|
|||||||
settings.protect_approvals_whitelist_enabled_desc=Nur Bewertungen von Benutzern auf der Whitelist oder Teams zählen zu den erforderlichen Genehmigungen. Gibt es keine Whitelist, so zählen Reviews von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen.
|
settings.protect_approvals_whitelist_enabled_desc=Nur Bewertungen von Benutzern auf der Whitelist oder Teams zählen zu den erforderlichen Genehmigungen. Gibt es keine Whitelist, so zählen Reviews von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen.
|
||||||
settings.protect_approvals_whitelist_users=Freigeschaltete Reviewer:
|
settings.protect_approvals_whitelist_users=Freigeschaltete Reviewer:
|
||||||
settings.protect_approvals_whitelist_teams=Freigeschaltete Teams:
|
settings.protect_approvals_whitelist_teams=Freigeschaltete Teams:
|
||||||
|
settings.dismiss_stale_approvals=Entferne alte Genehmigungen
|
||||||
|
settings.dismiss_stale_approvals_desc=Wenn neue Commits gepusht werden, die den Inhalt des Pull-Requests ändern, werden alte Genehmigungen entfernt.
|
||||||
settings.add_protected_branch=Schutz aktivieren
|
settings.add_protected_branch=Schutz aktivieren
|
||||||
settings.delete_protected_branch=Schutz deaktivieren
|
settings.delete_protected_branch=Schutz deaktivieren
|
||||||
settings.update_protect_branch_success=Branch-Schutz für den Branch „%s“ wurde geändert.
|
settings.update_protect_branch_success=Branch-Schutz für den Branch „%s“ wurde geändert.
|
||||||
@@ -1747,6 +1751,7 @@ users.new_account=Benutzerkonto erstellen
|
|||||||
users.name=Benutzername
|
users.name=Benutzername
|
||||||
users.activated=Aktiviert
|
users.activated=Aktiviert
|
||||||
users.admin=Administrator
|
users.admin=Administrator
|
||||||
|
users.restricted=Eingeschränkt
|
||||||
users.repos=Repositories
|
users.repos=Repositories
|
||||||
users.created=Registriert am
|
users.created=Registriert am
|
||||||
users.last_login=Letzte Anmeldung
|
users.last_login=Letzte Anmeldung
|
||||||
@@ -1765,6 +1770,7 @@ users.max_repo_creation_desc=(Gib -1 ein, um das globale Standardlimit zu verwen
|
|||||||
users.is_activated=Account ist aktiviert
|
users.is_activated=Account ist aktiviert
|
||||||
users.prohibit_login=Anmelden deaktivieren
|
users.prohibit_login=Anmelden deaktivieren
|
||||||
users.is_admin=Ist Administrator
|
users.is_admin=Ist Administrator
|
||||||
|
users.is_restricted=Ist eingeschränkt
|
||||||
users.allow_git_hook=Darf „Git Hooks“ erstellen
|
users.allow_git_hook=Darf „Git Hooks“ erstellen
|
||||||
users.allow_import_local=Darf lokale Repositories importieren
|
users.allow_import_local=Darf lokale Repositories importieren
|
||||||
users.allow_create_organization=Darf Organisationen erstellen
|
users.allow_create_organization=Darf Organisationen erstellen
|
||||||
@@ -2025,8 +2031,47 @@ monitor.execute_time=Ausführungszeit
|
|||||||
monitor.process.cancel=Prozess abbrechen
|
monitor.process.cancel=Prozess abbrechen
|
||||||
monitor.process.cancel_desc=Abbrechen eines Prozesses kann Datenverlust verursachen
|
monitor.process.cancel_desc=Abbrechen eines Prozesses kann Datenverlust verursachen
|
||||||
monitor.process.cancel_notices=Abbrechen: <strong>%s</strong>?
|
monitor.process.cancel_notices=Abbrechen: <strong>%s</strong>?
|
||||||
|
monitor.queues=Warteschlangen
|
||||||
|
monitor.queue=Warteschlange: %s
|
||||||
|
monitor.queue.name=Name
|
||||||
|
monitor.queue.type=Typ
|
||||||
|
monitor.queue.numberworkers=Anzahl der Worker
|
||||||
|
monitor.queue.maxnumberworkers=Maximale Anzahl der Worker
|
||||||
|
monitor.queue.review=Konfiguration überprüfen
|
||||||
|
monitor.queue.review_add=Worker hinzufügen/prüfen
|
||||||
|
monitor.queue.configuration=Erstkonfiguration
|
||||||
|
monitor.queue.nopool.title=Kein Worker-Pool
|
||||||
|
monitor.queue.nopool.desc=Diese Warteschlange umgibt andere Warteschlangen und hat selbst keinen Worker-Pool.
|
||||||
|
monitor.queue.wrapped.desc=Eine Wrapped Queue umfasst eine langsame Start-Warteschlange und puffert die in der Warteschlange stehenden Aufträge in einem Kanal. Sie besitzt selbst keinen Worker-Pool.
|
||||||
|
monitor.queue.persistable-channel.desc=Ein persistierender Channel umfasst zwei Warteschlangen, eine Channel-Warteschlange mit einem eigenen Worker-Pool und eine Level-Warteschlange für persistente Anfragen aus früheren Shutdowns. Er hat selbst keinen Worker-Pool.
|
||||||
|
monitor.queue.pool.timeout=Timeout
|
||||||
|
monitor.queue.pool.addworkers.title=Worker hinzufügen
|
||||||
|
monitor.queue.pool.addworkers.submit=Worker hinzufügen
|
||||||
|
monitor.queue.pool.addworkers.numberworkers.placeholder=Anzahl der Worker
|
||||||
|
monitor.queue.pool.addworkers.timeout.placeholder=Setze auf 0 für keinen Timeout
|
||||||
|
monitor.queue.pool.addworkers.musttimeoutduration=Timeout muss eine Golang-Dauer sein, z. B. 5m oder 0
|
||||||
|
|
||||||
|
monitor.queue.settings.title=Pool-Einstellungen
|
||||||
|
monitor.queue.settings.desc=Pools wachsen dynamisch mit einem Boost als Reaktion auf die Blockierung ihrer Workerwarteschlangen. Diese Änderungen wirken sich nicht auf die aktuellen Worker Gruppen aus.
|
||||||
|
monitor.queue.settings.timeout=Timeout verlängern
|
||||||
|
monitor.queue.settings.timeout.placeholder=Derzeit %[1]v
|
||||||
|
monitor.queue.settings.timeout.error=Timeout muss eine Golang-Dauer sein, z.B. 5m oder 0
|
||||||
|
monitor.queue.settings.numberworkers=Anzahl der Worker erhöhen
|
||||||
|
monitor.queue.settings.numberworkers.placeholder=Derzeit %[1]v
|
||||||
|
monitor.queue.settings.maxnumberworkers.placeholder=Derzeit %[1]v
|
||||||
|
monitor.queue.settings.maxnumberworkers.error=Die Anzahl der Worker muss eine Zahl sein
|
||||||
|
monitor.queue.settings.submit=Einstellungen aktualisieren
|
||||||
|
monitor.queue.settings.changed=Einstellungen aktualisiert
|
||||||
|
monitor.queue.settings.blocktimeout=Aktuelle Block-Timeout
|
||||||
|
monitor.queue.settings.blocktimeout.value=%[1]v
|
||||||
|
|
||||||
|
monitor.queue.pool.none=Diese Warteschlange hat keinen Pool
|
||||||
|
monitor.queue.pool.added=Workergruppe hinzugefügt
|
||||||
|
monitor.queue.pool.workers.title=Aktive Workergruppen
|
||||||
|
monitor.queue.pool.workers.none=Keine Workergruppen.
|
||||||
|
monitor.queue.pool.cancel=Workergruppen herunterfahren
|
||||||
|
monitor.queue.pool.cancelling=Workergruppe fährt herunter
|
||||||
|
monitor.queue.pool.cancel_notices=Diese Gruppe von %s Workern herunterfahren?
|
||||||
|
|
||||||
notices.system_notice_list=Systemmitteilungen
|
notices.system_notice_list=Systemmitteilungen
|
||||||
notices.view_detail_header=Meldungsdetails ansehen
|
notices.view_detail_header=Meldungsdetails ansehen
|
||||||
@@ -2120,4 +2165,3 @@ error.probable_bad_default_signature=WARNHINWEIS! Obwohl der Standardschlüssel
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Du hast keine Berechtigung, um auf irgendeinen Bereich dieses Repositories zuzugreifen.
|
error.no_unit_allowed_repo=Du hast keine Berechtigung, um auf irgendeinen Bereich dieses Repositories zuzugreifen.
|
||||||
error.unit_not_allowed=Du hast keine Berechtigung, um auf diesen Repository-Bereich zuzugreifen.
|
error.unit_not_allowed=Du hast keine Berechtigung, um auf diesen Repository-Bereich zuzugreifen.
|
||||||
|
|
||||||
|
|||||||
@@ -1063,6 +1063,8 @@ pulls.no_merge_desc = This pull request cannot be merged because all repository
|
|||||||
pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually.
|
pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually.
|
||||||
pulls.no_merge_wip = This pull request can not be merged because it is marked as being a work in progress.
|
pulls.no_merge_wip = This pull request can not be merged because it is marked as being a work in progress.
|
||||||
pulls.no_merge_status_check = This pull request cannot be merged because not all required status checkes are successful.
|
pulls.no_merge_status_check = This pull request cannot be merged because not all required status checkes are successful.
|
||||||
|
pulls.no_merge_not_ready = This pull request is not ready to be merged, check review status and status checks.
|
||||||
|
pulls.no_merge_access = You are not authorized to merge this pull request.
|
||||||
pulls.merge_pull_request = Merge Pull Request
|
pulls.merge_pull_request = Merge Pull Request
|
||||||
pulls.rebase_merge_pull_request = Rebase and Merge
|
pulls.rebase_merge_pull_request = Rebase and Merge
|
||||||
pulls.rebase_merge_commit_pull_request = Rebase and Merge (--no-ff)
|
pulls.rebase_merge_commit_pull_request = Rebase and Merge (--no-ff)
|
||||||
@@ -1413,6 +1415,8 @@ settings.protect_approvals_whitelist_enabled = Restrict approvals to whitelisted
|
|||||||
settings.protect_approvals_whitelist_enabled_desc = Only reviews from whitelisted users or teams will count to the required approvals. Without approval whitelist, reviews from anyone with write access count to the required approvals.
|
settings.protect_approvals_whitelist_enabled_desc = Only reviews from whitelisted users or teams will count to the required approvals. Without approval whitelist, reviews from anyone with write access count to the required approvals.
|
||||||
settings.protect_approvals_whitelist_users = Whitelisted reviewers:
|
settings.protect_approvals_whitelist_users = Whitelisted reviewers:
|
||||||
settings.protect_approvals_whitelist_teams = Whitelisted teams for reviews:
|
settings.protect_approvals_whitelist_teams = Whitelisted teams for reviews:
|
||||||
|
settings.dismiss_stale_approvals = Dismiss stale approvals
|
||||||
|
settings.dismiss_stale_approvals_desc = When new commits that change the content of the pull request are pushed to the branch, old approvals will be dismissed.
|
||||||
settings.add_protected_branch = Enable protection
|
settings.add_protected_branch = Enable protection
|
||||||
settings.delete_protected_branch = Disable protection
|
settings.delete_protected_branch = Disable protection
|
||||||
settings.update_protect_branch_success = Branch protection for branch '%s' has been updated.
|
settings.update_protect_branch_success = Branch protection for branch '%s' has been updated.
|
||||||
@@ -1748,6 +1752,7 @@ users.new_account = Create User Account
|
|||||||
users.name = Username
|
users.name = Username
|
||||||
users.activated = Activated
|
users.activated = Activated
|
||||||
users.admin = Admin
|
users.admin = Admin
|
||||||
|
users.restricted = Restricted
|
||||||
users.repos = Repos
|
users.repos = Repos
|
||||||
users.created = Created
|
users.created = Created
|
||||||
users.last_login = Last Sign-In
|
users.last_login = Last Sign-In
|
||||||
@@ -1766,6 +1771,7 @@ users.max_repo_creation_desc = (Enter -1 to use the global default limit.)
|
|||||||
users.is_activated = User Account Is Activated
|
users.is_activated = User Account Is Activated
|
||||||
users.prohibit_login = Disable Sign-In
|
users.prohibit_login = Disable Sign-In
|
||||||
users.is_admin = Is Administrator
|
users.is_admin = Is Administrator
|
||||||
|
users.is_restricted = Is Restricted
|
||||||
users.allow_git_hook = May Create Git Hooks
|
users.allow_git_hook = May Create Git Hooks
|
||||||
users.allow_import_local = May Import Local Repositories
|
users.allow_import_local = May Import Local Repositories
|
||||||
users.allow_create_organization = May Create Organizations
|
users.allow_create_organization = May Create Organizations
|
||||||
@@ -1820,6 +1826,7 @@ auths.attribute_surname = Surname Attribute
|
|||||||
auths.attribute_mail = Email Attribute
|
auths.attribute_mail = Email Attribute
|
||||||
auths.attribute_ssh_public_key = Public SSH Key Attribute
|
auths.attribute_ssh_public_key = Public SSH Key Attribute
|
||||||
auths.attributes_in_bind = Fetch Attributes in Bind DN Context
|
auths.attributes_in_bind = Fetch Attributes in Bind DN Context
|
||||||
|
auths.allow_deactivate_all = Allow an empty search result to deactivate all users
|
||||||
auths.use_paged_search = Use Paged Search
|
auths.use_paged_search = Use Paged Search
|
||||||
auths.search_page_size = Page Size
|
auths.search_page_size = Page Size
|
||||||
auths.filter = User Filter
|
auths.filter = User Filter
|
||||||
|
|||||||
@@ -2109,4 +2109,3 @@ error.probable_bad_default_signature=¡ADVERTENCIA! ¡La clave por defecto tiene
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=No tiene permisos para acceder a ninguna sección de este repositorio.
|
error.no_unit_allowed_repo=No tiene permisos para acceder a ninguna sección de este repositorio.
|
||||||
error.unit_not_allowed=No tiene permisos para acceder a esta sección del repositorio.
|
error.unit_not_allowed=No tiene permisos para acceder a esta sección del repositorio.
|
||||||
|
|
||||||
|
|||||||
@@ -2120,4 +2120,3 @@ error.probable_bad_default_signature=هشدار! اگرچه اینجا یک کل
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=شما اجازه دسترسی به هیچ قسمت از این مخزن را ندارید.
|
error.no_unit_allowed_repo=شما اجازه دسترسی به هیچ قسمت از این مخزن را ندارید.
|
||||||
error.unit_not_allowed=شما اجازه دسترسی به این قسمت مخزن را ندارید.
|
error.unit_not_allowed=شما اجازه دسترسی به این قسمت مخزن را ندارید.
|
||||||
|
|
||||||
|
|||||||
@@ -2096,4 +2096,3 @@ error.probable_bad_default_signature=AVERTISSEMENT ! Bien que la clé par défau
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Vous n'êtes pas autorisé à accéder à n'importe quelle section de ce dépôt.
|
error.no_unit_allowed_repo=Vous n'êtes pas autorisé à accéder à n'importe quelle section de ce dépôt.
|
||||||
error.unit_not_allowed=Vous n'êtes pas autorisé à accéder à cette section du dépôt.
|
error.unit_not_allowed=Vous n'êtes pas autorisé à accéder à cette section du dépôt.
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ link_account=Tautan Akun
|
|||||||
register=Daftar
|
register=Daftar
|
||||||
website=Situs Web
|
website=Situs Web
|
||||||
version=Versi
|
version=Versi
|
||||||
|
powered_by=Diberdayakan oleh %s
|
||||||
page=Halaman
|
page=Halaman
|
||||||
template=Contoh
|
template=Contoh
|
||||||
language=Bahasa
|
language=Bahasa
|
||||||
@@ -29,8 +30,16 @@ twofa_scratch=Kode Awal Dua Faktor
|
|||||||
passcode=Kode Akses
|
passcode=Kode Akses
|
||||||
|
|
||||||
u2f_insert_key=Masukkan kunci keamanan anda
|
u2f_insert_key=Masukkan kunci keamanan anda
|
||||||
|
u2f_sign_in=Tekan tombol pada kunci keamanan anda. Jika kunci keamanan anda tidak memiliki tombol, masukkan kembali.
|
||||||
u2f_press_button=Silahkan tekan tombol pada kunci keamanan anda…
|
u2f_press_button=Silahkan tekan tombol pada kunci keamanan anda…
|
||||||
u2f_use_twofa=Menggunakan kode dua faktor dari telepon anda
|
u2f_use_twofa=Menggunakan kode dua faktor dari telepon anda
|
||||||
|
u2f_error=Tidak dapat membaca kunci keamanan Anda.
|
||||||
|
u2f_unsupported_browser=Browser Anda tidak mendukung kunci keamanan U2F.
|
||||||
|
u2f_error_1=Terdapat kesalahan yang tidak diketahui. Mohon coba lagi.
|
||||||
|
u2f_error_2=Pastikan menggunakan URL yang benar dan terenkripsi (https://).
|
||||||
|
u2f_error_3=Server tidak bisa memproses permintaan anda.
|
||||||
|
u2f_error_4=Kunci keamanan tidak diperbolehkan untuk permintaan ini. Pastikan bahwa kunci ini belum terdaftar sebelumnya.
|
||||||
|
u2f_error_5=Waktu habis sebelum kunci Anda dapat dibaca. Mohon muat ulang halaman ini dan coba lagi.
|
||||||
u2f_reload=Muat Ulang
|
u2f_reload=Muat Ulang
|
||||||
|
|
||||||
repository=Repositori
|
repository=Repositori
|
||||||
@@ -58,25 +67,51 @@ forks=Garpu
|
|||||||
activities=Aktivitas
|
activities=Aktivitas
|
||||||
pull_requests=Tarik Permintaan
|
pull_requests=Tarik Permintaan
|
||||||
issues=Masalah
|
issues=Masalah
|
||||||
|
milestones=Tonggak
|
||||||
|
|
||||||
cancel=Batal
|
cancel=Batal
|
||||||
|
add=Tambah
|
||||||
|
add_all=Tambah Semua
|
||||||
|
remove=Buang
|
||||||
|
remove_all=Buang Semua
|
||||||
|
|
||||||
|
write=Tulis
|
||||||
|
preview=Pratinjau
|
||||||
|
loading=Memuat…
|
||||||
|
|
||||||
[startpage]
|
[startpage]
|
||||||
|
app_desc=Sebuah layanan hosting Git sendiri yang tanpa kesulitan
|
||||||
|
install=Mudah dipasang
|
||||||
|
install_desc=Cukup <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/install-from-binary/">jalankan program biner</a> yang sesuai dengan sistem operasi Anda. Atau jalankan Gitea dengan <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a> atau <a target="_blank" rel="noopener noreferrer" href="https://github.com/alvaroaleman/ansible-gitea/blob/master/Vagrantfile">Vagrant</a>, atau install dari <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/install-from-package/">paket</a>.
|
||||||
|
platform=Lintas platform
|
||||||
|
platform_desc=Gitea bisa digunakan di mana <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a> bisa dijalankan: Windows, macOS, Linux, ARM, dll. Silahkan pilih yang Anda suka!
|
||||||
|
lightweight=Ringan
|
||||||
|
lightweight_desc=Gitea hanya membutuhkan persyaratan minimal dan bisa berjalan pada Raspberry Pi yang murah. Bisa menghemat listrik!
|
||||||
|
license=Sumber Terbuka
|
||||||
|
license_desc="Go get" (Dapatkan kode sumber dari) <a target="_blank" rel="noopener noreferrer" href="https://code.gitea.io/gitea">code.gitea.io/gitea</a>! Mari bergabung dengan <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">berkontribusi</a> untuk membuat proyek ini lebih baik. Jangan malu untuk menjadi kontributor!
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
install=Pemasangan
|
install=Pemasangan
|
||||||
title=Konfigurasi Awal
|
title=Konfigurasi Awal
|
||||||
|
docker_helper=Jika Anda menjalankan Gitea di dalam Docker, baca <a target="_blank" rel="noopener" href="%s">dokumentasi </a> sebelum mengubah pengaturan.
|
||||||
|
requite_db_desc=Gitea memerlukan MySQL, PostgreSQL, MSSQL atau SQLite3.
|
||||||
db_title=Pengaturan Basis Data
|
db_title=Pengaturan Basis Data
|
||||||
db_type=Tipe Basis Data
|
db_type=Tipe Basis Data
|
||||||
host=Host
|
host=Host
|
||||||
user=Nama Pengguna
|
user=Nama Pengguna
|
||||||
password=Kata Sandi
|
password=Kata Sandi
|
||||||
db_name=Nama Basis Data
|
db_name=Nama Basis Data
|
||||||
|
db_helper=Untuk pengguna MySQL: Mohon gunakan mesin penyimpanan InnoDB, dan jika Anda menggunakan enkoding "utf8mb4", versi InnoDB Anda harus diatas 5.6.
|
||||||
ssl_mode=SSL
|
ssl_mode=SSL
|
||||||
|
charset=Jenis karakter
|
||||||
path=Jalur
|
path=Jalur
|
||||||
|
sqlite_helper=Jalur berkas untuk basis data SQLite3 atau TiDB.<br>Masukkan path absolut jika anda menjalankan Gitea sebagai layanan.
|
||||||
|
err_empty_db_path=Jalur basis data SQLite3 tidak boleh kosong.
|
||||||
no_admin_and_disable_registration=Anda tidak dapat menonaktifkan pendaftaran tanpa membuat akun admin.
|
no_admin_and_disable_registration=Anda tidak dapat menonaktifkan pendaftaran tanpa membuat akun admin.
|
||||||
err_empty_admin_password=Sandi administrator tidak boleh kosong.
|
err_empty_admin_password=Sandi administrator tidak boleh kosong.
|
||||||
|
err_empty_admin_email=Email administrator tidak boleh kosong.
|
||||||
|
err_admin_name_is_reserved=Nama pengguna Administrator tidak valid, nama tersebut dicadangkan
|
||||||
|
err_admin_name_is_invalid=Nama Administrator tidak valid.
|
||||||
|
|
||||||
general_title=Pengaturan Umum
|
general_title=Pengaturan Umum
|
||||||
app_name=Judul Situs
|
app_name=Judul Situs
|
||||||
@@ -111,13 +146,20 @@ server_service_title=Server dan Pengaturan Layanan Pihak Ketiga
|
|||||||
offline_mode=Aktifkan Mode Lokal
|
offline_mode=Aktifkan Mode Lokal
|
||||||
offline_mode_popup=Non-aktifkan jaringan pengiriman konten dari pihak ketiga dan layani semua sumber daya secara lokal.
|
offline_mode_popup=Non-aktifkan jaringan pengiriman konten dari pihak ketiga dan layani semua sumber daya secara lokal.
|
||||||
disable_gravatar=Non-aktifkan Gravatar
|
disable_gravatar=Non-aktifkan Gravatar
|
||||||
|
federated_avatar_lookup=Aktifkan Avatar Terfederasi
|
||||||
federated_avatar_lookup_popup=Mengaktifkan pencarian avatar federasi menggunakan Libravatar.
|
federated_avatar_lookup_popup=Mengaktifkan pencarian avatar federasi menggunakan Libravatar.
|
||||||
|
disable_registration=Matikan Swa-pendaftaran
|
||||||
|
disable_registration_popup=Nonaktifkan pendaftaran oleh pengguna. Hanya admin yang dapat membuat akun pengguna baru.
|
||||||
|
allow_only_external_registration_popup=Perbolehkan Pendaftaran Hanya Melalui Layanan External
|
||||||
openid_signin=Aktifkan Login OpenID
|
openid_signin=Aktifkan Login OpenID
|
||||||
|
openid_signin_popup=Aktifkan masuk pengguna lewat OpenID.
|
||||||
openid_signup=Aktifkan Pendaftaran OpenID
|
openid_signup=Aktifkan Pendaftaran OpenID
|
||||||
openid_signup_popup=Aktifkan pendaftaran berdasarkan OpenID.
|
openid_signup_popup=Aktifkan pendaftaran berdasarkan OpenID.
|
||||||
enable_captcha=Aktifkan CAPTCHA
|
enable_captcha=Aktifkan CAPTCHA
|
||||||
enable_captcha_popup=Membutukan CAPTCHA untuk pendaftaran.
|
enable_captcha_popup=Membutukan CAPTCHA untuk pendaftaran.
|
||||||
require_sign_in_view=Anda Harus Login untuk Melihat Halaman
|
require_sign_in_view=Anda Harus Login untuk Melihat Halaman
|
||||||
|
require_sign_in_view_popup=Batasi akses halaman hanya pada pengguna yang masuk. Pengunjung hanya dapat melihat halaman masuk dan pendaftaran.
|
||||||
|
admin_setting_desc=Akun administrator tidak wajib dibuat. Pengguna yang pertama kali mendaftar akan secara otomatis menjadi administrator.
|
||||||
admin_title=Pengaturan Akun Admin
|
admin_title=Pengaturan Akun Admin
|
||||||
admin_name=Nama Pengguna Admin
|
admin_name=Nama Pengguna Admin
|
||||||
admin_password=Kata sandi
|
admin_password=Kata sandi
|
||||||
@@ -127,7 +169,15 @@ install_btn_confirm=Memasang Gitea
|
|||||||
test_git_failed=Tidak dapat menguji perintah 'git': %v
|
test_git_failed=Tidak dapat menguji perintah 'git': %v
|
||||||
sqlite3_not_available=Gitea versi ini tidak mendukung SQLite3, Silahkan untuh versi biner resmi dari %s (bukan versi 'gobuild').
|
sqlite3_not_available=Gitea versi ini tidak mendukung SQLite3, Silahkan untuh versi biner resmi dari %s (bukan versi 'gobuild').
|
||||||
invalid_db_setting=Pengaturan basis data tidak valid: %v
|
invalid_db_setting=Pengaturan basis data tidak valid: %v
|
||||||
|
invalid_repo_path=Lokasi folder repositori tidak valid: %v
|
||||||
|
run_user_not_match=Nama pengguna 'run as' bukanlah nama pengguna saat ini: %s -> %s
|
||||||
save_config_failed=Gagal menyimpan konfigurasi: %v
|
save_config_failed=Gagal menyimpan konfigurasi: %v
|
||||||
|
invalid_admin_setting=Pengaturan akun administrator tidak valid: %v
|
||||||
|
install_success=Selamat datang! Terimakasih telah memilih Gitea. Selamat bersenang-senang dan hati-hati!
|
||||||
|
invalid_log_root_path=Jalur folder log tidak valid: %v
|
||||||
|
default_keep_email_private=Sembunyikan Alamat Email secara Asali
|
||||||
|
default_keep_email_private_popup=Sembunyikan alamat email pengguna baru secara asali.
|
||||||
|
default_allow_create_organization_popup=Perbolehkan pengguna baru untuk membuat organisasi.
|
||||||
|
|
||||||
[home]
|
[home]
|
||||||
uname_holder=Nama Pengguna atau Alamat Surel
|
uname_holder=Nama Pengguna atau Alamat Surel
|
||||||
@@ -161,36 +211,50 @@ social_register_helper_msg=Sudah memiliki akun? Hubungkan sekarang!
|
|||||||
remember_me=Ingat Saya
|
remember_me=Ingat Saya
|
||||||
forgot_password_title=Lupa Kata Sandi
|
forgot_password_title=Lupa Kata Sandi
|
||||||
forgot_password=Lupa kata sandi?
|
forgot_password=Lupa kata sandi?
|
||||||
|
sign_up_now=Butuh akun? Daftar sekarang.
|
||||||
|
sign_up_successful=Akun berhasil dibuat.
|
||||||
confirmation_mail_sent_prompt=Surel konfirmasi baru telah dikirim ke <b>%s</b>. Silakan periksa kotak masuk anda dalam %s ke depan untuk menyelesaikan proses pendaftaran.
|
confirmation_mail_sent_prompt=Surel konfirmasi baru telah dikirim ke <b>%s</b>. Silakan periksa kotak masuk anda dalam %s ke depan untuk menyelesaikan proses pendaftaran.
|
||||||
active_your_account=Aktifkan Akun Anda
|
active_your_account=Aktifkan Akun Anda
|
||||||
|
account_activated=Akun telah diaktifkan
|
||||||
|
prohibit_login_desc=Akun Anda tidak diperbolehkan untuk masuk, silakan hubungi admin situs.
|
||||||
has_unconfirmed_mail=Hai %s, anda memiliki sebuah alamat surel yang belum dikonfirmasi (<b>%s</b>). Jika anda belum menerima surel konfirmasi atau perlu untuk mengirim ulang yang baru, silakan klik pada tombol di bawah.
|
has_unconfirmed_mail=Hai %s, anda memiliki sebuah alamat surel yang belum dikonfirmasi (<b>%s</b>). Jika anda belum menerima surel konfirmasi atau perlu untuk mengirim ulang yang baru, silakan klik pada tombol di bawah.
|
||||||
resend_mail=Klik di sini untuk mengirim ulang surel aktivasi anda
|
resend_mail=Klik di sini untuk mengirim ulang surel aktivasi anda
|
||||||
email_not_associate=Alamat surel tidak terhubung dengan akun apapun.
|
email_not_associate=Alamat surel tidak terhubung dengan akun apapun.
|
||||||
|
send_reset_mail=Kirim Surel Pemulihan Akun
|
||||||
|
reset_password=Pemulihan Akun
|
||||||
|
password_too_short=Panjang kata sandi tidak boleh kurang dari %d karakter.
|
||||||
verify=Verifikasi
|
verify=Verifikasi
|
||||||
scratch_code=Kode coretan
|
scratch_code=Kode coretan
|
||||||
use_scratch_code=Gunakan kode coretan
|
use_scratch_code=Gunakan kode coretan
|
||||||
twofa_scratch_used=Anda telah menggunakan kode coretan anda. Anda telah dialihkan ke halaman pengaturan dua-faktor jadi anda boleh menghapus pendaftaran perangkat anda atau menghasilkan kode coretan yang baru.
|
twofa_scratch_used=Anda telah menggunakan kode coretan anda. Anda telah dialihkan ke halaman pengaturan dua-faktor jadi anda boleh menghapus pendaftaran perangkat anda atau menghasilkan kode coretan yang baru.
|
||||||
|
twofa_passcode_incorrect=Kata sandi Anda salah. Jika Anda salah tempatkan perangkat Anda, gunakan kode gosok Anda untuk masuk.
|
||||||
twofa_scratch_token_incorrect=Kode coretan anda tidak tepat.
|
twofa_scratch_token_incorrect=Kode coretan anda tidak tepat.
|
||||||
login_openid=OpenID
|
login_openid=OpenID
|
||||||
openid_connect_submit=Sambungkan
|
openid_connect_submit=Sambungkan
|
||||||
openid_connect_title=Sambungkan ke akun yang sudah ada
|
openid_connect_title=Sambungkan ke akun yang sudah ada
|
||||||
openid_register_title=Buat akun baru
|
openid_register_title=Buat akun baru
|
||||||
|
openid_signin_desc=Masukkan URI OpenID Anda. Misalnya: https://anne.me, bob.openid.org.cn, atau gnusocial.net/carry.
|
||||||
|
email_domain_blacklisted=Anda tidak dapat mendaftar dengan alamat email.
|
||||||
|
authorize_application=Izinkan aplikasi
|
||||||
|
|
||||||
[mail]
|
[mail]
|
||||||
activate_account=Silakan aktifkan akun anda
|
activate_account=Silakan aktifkan akun anda
|
||||||
activate_email=Verifikasi alamat surel anda
|
activate_email=Verifikasi alamat surel anda
|
||||||
|
reset_password=Pulihkan akun Anda
|
||||||
register_success=Pendaftaran berhasil
|
register_success=Pendaftaran berhasil
|
||||||
register_notify=Selamat Datang di Gitea
|
register_notify=Selamat Datang di Gitea
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ya
|
yes=Ya
|
||||||
no=Tidak
|
no=Tidak
|
||||||
|
modify=Perbarui
|
||||||
|
|
||||||
[form]
|
[form]
|
||||||
UserName=Nama Pengguna
|
UserName=Nama Pengguna
|
||||||
RepoName=Nama repositori
|
RepoName=Nama repositori
|
||||||
Email=Alamat surel
|
Email=Alamat surel
|
||||||
Password=Kata Sandi
|
Password=Kata Sandi
|
||||||
|
Retype=Ketik Ulang Kata Sandi
|
||||||
SSHTitle=Nama kunci SSH
|
SSHTitle=Nama kunci SSH
|
||||||
HttpsUrl=HTTPS URL
|
HttpsUrl=HTTPS URL
|
||||||
PayloadUrl=Muatan URL
|
PayloadUrl=Muatan URL
|
||||||
@@ -205,6 +269,7 @@ CommitChoice=Pilihan Commit
|
|||||||
TreeName=Jalur berkas
|
TreeName=Jalur berkas
|
||||||
Content=Konten
|
Content=Konten
|
||||||
|
|
||||||
|
SSPISeparatorReplacement=Pemisah
|
||||||
|
|
||||||
require_error=` tidak boleh kosong.`
|
require_error=` tidak boleh kosong.`
|
||||||
size_error=` harus berukuran %s.`
|
size_error=` harus berukuran %s.`
|
||||||
@@ -214,53 +279,100 @@ email_error=` bukan alamat surel yang valid. `
|
|||||||
url_error=` bukan URL yang valid.`
|
url_error=` bukan URL yang valid.`
|
||||||
include_error=` harus mengandung substring '%s'.`
|
include_error=` harus mengandung substring '%s'.`
|
||||||
unknown_error=Kesalahan yang tidak diketahui:
|
unknown_error=Kesalahan yang tidak diketahui:
|
||||||
|
lang_select_error=Pilih bahasa dari daftar.
|
||||||
|
|
||||||
|
email_been_used=Alamat email sudah digunakan.
|
||||||
|
openid_been_used=Alamat OpenID '%s' sudah digunakan.
|
||||||
|
username_password_incorrect=Nama pengguna atau sandi salah.
|
||||||
|
password_complexity=Kata sandi tidak memenuhi persyaratan kerumitan:
|
||||||
|
password_lowercase_one=Sekurang-kurangnya satu karakter kecil
|
||||||
|
password_uppercase_one=Sekurang-kurangnya satu karakter besar
|
||||||
|
password_digit_one=Sekurang-kurangnya satu angka
|
||||||
|
password_special_one=Sekurang-kurangnya satu karater khusus (tanda baca, kurung, kutip, dll.)
|
||||||
|
enterred_invalid_repo_name=Nama repositori yang Anda masukkan salah.
|
||||||
|
enterred_invalid_owner_name=Nama pemilik baru salah.
|
||||||
|
enterred_invalid_password=Kata sandi yang Anda masukkan salah.
|
||||||
user_not_exist=Pengguna tidak ada.
|
user_not_exist=Pengguna tidak ada.
|
||||||
|
team_not_exist=Tim tidak ada.
|
||||||
|
last_org_owner=Anda tidak dapat menghapus pengguna terakhir dari tim pemilik. Harus ada setidaknya satu pemilik dalam tim yang diberikan.
|
||||||
|
cannot_add_org_to_team=Sebuah organisasi tidak dapat ditambahkan sebagai anggota tim.
|
||||||
|
|
||||||
|
invalid_ssh_key=Tidak dapat memverifikasi kunci SSH Anda: %s
|
||||||
|
invalid_gpg_key=Tidak dapat memverifikasi kunci GPG Anda: %s
|
||||||
|
unable_verify_ssh_key=Tidak dapat memverifikasi kunci SSH; periksa kembali bila ada kesalahan.
|
||||||
auth_failed=Otentikasi gagal: %v
|
auth_failed=Otentikasi gagal: %v
|
||||||
|
|
||||||
|
still_own_repo=Akun anda memiliki satu atau lebih repositori, pindahkan atau transfer terlebih dahulu.
|
||||||
|
still_has_org=Akun Anda adalah anggota dari satu atau lebih organisasi, tinggalkan terlebih dahulu.
|
||||||
|
org_still_own_repo=Organisasi ini masih memiliki satu atau lebih repositori; hapus atau transfer terlebih dahulu.
|
||||||
|
|
||||||
target_branch_not_exist=Target cabang tidak ada.
|
target_branch_not_exist=Target cabang tidak ada.
|
||||||
|
|
||||||
[user]
|
[user]
|
||||||
|
change_avatar=Ganti avatar anda…
|
||||||
join_on=Telah bergabung di
|
join_on=Telah bergabung di
|
||||||
repositories=Repositori
|
repositories=Repositori
|
||||||
activity=Aktivitas Publik
|
activity=Aktivitas Publik
|
||||||
followers=Pengikut
|
followers=Pengikut
|
||||||
|
starred=Repositori Terbintang
|
||||||
following=Mengikuti
|
following=Mengikuti
|
||||||
follow=Ikuti
|
follow=Ikuti
|
||||||
unfollow=Berhenti Mengikuti
|
unfollow=Berhenti Mengikuti
|
||||||
|
heatmap.loading=Memuat Peta Panas…
|
||||||
|
user_bio=Biografi
|
||||||
|
|
||||||
form.name_reserved=Nama pengguna '%s' dicadangkan.
|
form.name_reserved=Nama pengguna '%s' dicadangkan.
|
||||||
|
form.name_pattern_not_allowed=Pola '%s' tidak diperbolehkan dalam nama pengguna.
|
||||||
|
|
||||||
[settings]
|
[settings]
|
||||||
profile=Profil
|
profile=Profil
|
||||||
|
account=Akun
|
||||||
password=Kata Sandi
|
password=Kata Sandi
|
||||||
security=Keamanan
|
security=Keamanan
|
||||||
avatar=Avatar
|
avatar=Avatar
|
||||||
ssh_gpg_keys=Kunci SSH / GPG
|
ssh_gpg_keys=Kunci SSH / GPG
|
||||||
social=Akun Sosial
|
social=Akun Sosial
|
||||||
|
applications=Aplikasi
|
||||||
|
orgs=Kelola organisasi
|
||||||
repos=Repositori
|
repos=Repositori
|
||||||
delete=Hapus Akun
|
delete=Hapus Akun
|
||||||
twofa=Otentikasi Dua-Faktor
|
twofa=Otentikasi Dua-Faktor
|
||||||
|
account_link=Akun Tertaut
|
||||||
|
organization=Organisasi
|
||||||
uid=Uid
|
uid=Uid
|
||||||
|
u2f=Kunci keamanan
|
||||||
|
|
||||||
public_profile=Profil Publik
|
public_profile=Profil Publik
|
||||||
|
profile_desc=Alamat email Anda akan digunakan untuk notifikasi dan operasi lainnya.
|
||||||
|
password_username_disabled=Pengguna non-lokal tidak diizinkan untuk mengubah nama pengguna mereka. Silakan hubungi administrator sistem anda untuk lebih lanjut.
|
||||||
full_name=Nama Lengkap
|
full_name=Nama Lengkap
|
||||||
website=Situs Web
|
website=Situs Web
|
||||||
location=Lokasi
|
location=Lokasi
|
||||||
|
update_theme=Perbarui Tema
|
||||||
update_profile=Perbarui Profil
|
update_profile=Perbarui Profil
|
||||||
update_profile_success=Profil anda telah diperbarui.
|
update_profile_success=Profil anda telah diperbarui.
|
||||||
|
change_username=Nama pengguna Anda telah diganti.
|
||||||
|
change_username_prompt=Catatan: Perubahan nama pengguna juga mengubah URL akun Anda.
|
||||||
continue=Lanjutkan
|
continue=Lanjutkan
|
||||||
cancel=Batalkan
|
cancel=Batalkan
|
||||||
|
language=Bahasa
|
||||||
|
ui=Tema
|
||||||
|
|
||||||
|
lookup_avatar_by_mail=Cari Avatar melalui Alamat Email
|
||||||
federated_avatar_lookup=Aktifkan Pencarian Avatar Representasi
|
federated_avatar_lookup=Aktifkan Pencarian Avatar Representasi
|
||||||
enable_custom_avatar=Gunakan Avatar Pilihan
|
enable_custom_avatar=Gunakan Avatar Pilihan
|
||||||
choose_new_avatar=Pilih avatar baru
|
choose_new_avatar=Pilih avatar baru
|
||||||
|
update_avatar=Perbarui Avatar
|
||||||
delete_current_avatar=Hapus Avatar Saat Ini
|
delete_current_avatar=Hapus Avatar Saat Ini
|
||||||
|
uploaded_avatar_not_a_image=Berkas yang diunggah bukanlah gambar.
|
||||||
|
uploaded_avatar_is_too_big=Berkas yang diunggah melebihi ukuran maksimum.
|
||||||
|
update_avatar_success=Avatar Anda telah diperbarui.
|
||||||
|
|
||||||
|
change_password=Perbarui kata sandi
|
||||||
old_password=Kata Sandi Saat Ini
|
old_password=Kata Sandi Saat Ini
|
||||||
new_password=Kata Sandi Baru
|
new_password=Kata Sandi Baru
|
||||||
|
retype_new_password=Ketik Ulang Kata Sandi Baru
|
||||||
|
password_incorrect=Kata sandi saat ini salah.
|
||||||
|
|
||||||
emails=Alamat Surel
|
emails=Alamat Surel
|
||||||
email_desc=Alamat surel utama anda akan digunakan untuk notifikasi dan operasi lainnya.
|
email_desc=Alamat surel utama anda akan digunakan untuk notifikasi dan operasi lainnya.
|
||||||
@@ -318,6 +430,7 @@ confirm_delete_account=Konfirmasi Penghapusan
|
|||||||
owner=Pemilik
|
owner=Pemilik
|
||||||
repo_name=Nama Repositori
|
repo_name=Nama Repositori
|
||||||
visibility=Jarak pandang
|
visibility=Jarak pandang
|
||||||
|
clone_helper=Butuh bantuan kloning? Kunjungi <a target="_blank" rel="noopener noreferrer" href="%s">Bantuan</a>.
|
||||||
fork_repo=Cabang Gudang penyimpanan
|
fork_repo=Cabang Gudang penyimpanan
|
||||||
fork_from=Cabang Dari
|
fork_from=Cabang Dari
|
||||||
repo_desc=Deskripsi
|
repo_desc=Deskripsi
|
||||||
@@ -508,6 +621,7 @@ pulls.new=Permintaan Tarik Baru
|
|||||||
pulls.filter_branch=Penyaringan cabang
|
pulls.filter_branch=Penyaringan cabang
|
||||||
pulls.no_results=Hasil tidak ditemukan.
|
pulls.no_results=Hasil tidak ditemukan.
|
||||||
pulls.create=Buat Permintaan Tarik
|
pulls.create=Buat Permintaan Tarik
|
||||||
|
pulls.title_desc=ingin menggabungkan komit %[1]d dari <code>%[2]s</code> menuju <code id="branch_target">%[3]s</code>
|
||||||
pulls.merged_title_desc=commit %[1]d telah digabungkan dari <code>%[2]s</code> menjadi <code>%[3]s</code> %[4]s
|
pulls.merged_title_desc=commit %[1]d telah digabungkan dari <code>%[2]s</code> menjadi <code>%[3]s</code> %[4]s
|
||||||
pulls.tab_conversation=Percakapan
|
pulls.tab_conversation=Percakapan
|
||||||
pulls.tab_commits=Melakukan
|
pulls.tab_commits=Melakukan
|
||||||
@@ -625,6 +739,7 @@ settings.webhook.request=Permintaan
|
|||||||
settings.webhook.response=Tanggapan
|
settings.webhook.response=Tanggapan
|
||||||
settings.webhook.headers=Tajuk
|
settings.webhook.headers=Tajuk
|
||||||
settings.webhook.body=Tubuh
|
settings.webhook.body=Tubuh
|
||||||
|
settings.githooks_desc=Kaitan Git diberdayakan oleh Git itu sendiri. Anda bisa menyunting berkas kaitan di bawah untuk mempersiapkan operasi kustom.
|
||||||
settings.githook_edit_desc=Jika hook tidak aktif, konten sampel akan dipaparkan. Meninggalkan konten dengan nilai kosong akan menonaktifkan hook ini.
|
settings.githook_edit_desc=Jika hook tidak aktif, konten sampel akan dipaparkan. Meninggalkan konten dengan nilai kosong akan menonaktifkan hook ini.
|
||||||
settings.githook_name=Nama Hook
|
settings.githook_name=Nama Hook
|
||||||
settings.githook_content=Konten Hook
|
settings.githook_content=Konten Hook
|
||||||
|
|||||||
@@ -1062,6 +1062,8 @@ pulls.no_merge_desc=リポジトリのマージオプションがすべて無効
|
|||||||
pulls.no_merge_helper=リポジトリ設定でマージを有効にするか、手動でマージしてください。
|
pulls.no_merge_helper=リポジトリ設定でマージを有効にするか、手動でマージしてください。
|
||||||
pulls.no_merge_wip=このプルリクエストはWork in Progressとマークされているため、マージすることはできません。
|
pulls.no_merge_wip=このプルリクエストはWork in Progressとマークされているため、マージすることはできません。
|
||||||
pulls.no_merge_status_check=すべての必要なステータスチェックが成功していないため、このプルリクエストはマージできません。
|
pulls.no_merge_status_check=すべての必要なステータスチェックが成功していないため、このプルリクエストはマージできません。
|
||||||
|
pulls.no_merge_not_ready=このプルリクエストはマージする準備ができていません。 レビュー状況とステータスチェックを確認してください。
|
||||||
|
pulls.no_merge_access=このプルリクエストをマージする権限がありません。
|
||||||
pulls.merge_pull_request=プルリクエストをマージ
|
pulls.merge_pull_request=プルリクエストをマージ
|
||||||
pulls.rebase_merge_pull_request=リベースしてマージ
|
pulls.rebase_merge_pull_request=リベースしてマージ
|
||||||
pulls.rebase_merge_commit_pull_request=リベースしてマージ(--no-ff)
|
pulls.rebase_merge_commit_pull_request=リベースしてマージ(--no-ff)
|
||||||
@@ -1412,6 +1414,8 @@ settings.protect_approvals_whitelist_enabled=ホワイトリストに登録し
|
|||||||
settings.protect_approvals_whitelist_enabled_desc=ホワイトリストに登録したユーザーやチームによるレビューのみを、必要な承認とみなします。 承認のホワイトリストが無い場合は、書き込み権限がある人によるレビューを必要な承認とみなします。
|
settings.protect_approvals_whitelist_enabled_desc=ホワイトリストに登録したユーザーやチームによるレビューのみを、必要な承認とみなします。 承認のホワイトリストが無い場合は、書き込み権限がある人によるレビューを必要な承認とみなします。
|
||||||
settings.protect_approvals_whitelist_users=ホワイトリストに含めるレビューア:
|
settings.protect_approvals_whitelist_users=ホワイトリストに含めるレビューア:
|
||||||
settings.protect_approvals_whitelist_teams=ホワイトリストに含めるレビューチーム:
|
settings.protect_approvals_whitelist_teams=ホワイトリストに含めるレビューチーム:
|
||||||
|
settings.dismiss_stale_approvals=古くなった承認を取り消す
|
||||||
|
settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える新たなコミットがブランチにプッシュされた場合、以前の承認を取り消します。
|
||||||
settings.add_protected_branch=保護を有効にする
|
settings.add_protected_branch=保護を有効にする
|
||||||
settings.delete_protected_branch=保護を無効にする
|
settings.delete_protected_branch=保護を無効にする
|
||||||
settings.update_protect_branch_success=ブランチ '%s' の保護を更新しました。
|
settings.update_protect_branch_success=ブランチ '%s' の保護を更新しました。
|
||||||
@@ -1747,6 +1751,7 @@ users.new_account=ユーザーアカウントを作成
|
|||||||
users.name=ユーザー名
|
users.name=ユーザー名
|
||||||
users.activated=アクティベート済み
|
users.activated=アクティベート済み
|
||||||
users.admin=管理者
|
users.admin=管理者
|
||||||
|
users.restricted=制限あり
|
||||||
users.repos=リポジトリ
|
users.repos=リポジトリ
|
||||||
users.created=作成日
|
users.created=作成日
|
||||||
users.last_login=前回のサインイン
|
users.last_login=前回のサインイン
|
||||||
@@ -1765,6 +1770,7 @@ users.max_repo_creation_desc=( -1を設定するとデフォルトの制限が
|
|||||||
users.is_activated=ユーザーアカウントはアクティベート済み
|
users.is_activated=ユーザーアカウントはアクティベート済み
|
||||||
users.prohibit_login=サインイン無効
|
users.prohibit_login=サインイン無効
|
||||||
users.is_admin=管理者
|
users.is_admin=管理者
|
||||||
|
users.is_restricted=制限あり
|
||||||
users.allow_git_hook=Gitフックを作成可
|
users.allow_git_hook=Gitフックを作成可
|
||||||
users.allow_import_local=ローカルリポジトリをインポート可
|
users.allow_import_local=ローカルリポジトリをインポート可
|
||||||
users.allow_create_organization=組織を作成可
|
users.allow_create_organization=組織を作成可
|
||||||
@@ -2025,8 +2031,54 @@ monitor.execute_time=実行時間
|
|||||||
monitor.process.cancel=処理をキャンセル
|
monitor.process.cancel=処理をキャンセル
|
||||||
monitor.process.cancel_desc=処理をキャンセルするとデータが失われる可能性があります
|
monitor.process.cancel_desc=処理をキャンセルするとデータが失われる可能性があります
|
||||||
monitor.process.cancel_notices=キャンセル: <strong>%s</strong>?
|
monitor.process.cancel_notices=キャンセル: <strong>%s</strong>?
|
||||||
|
monitor.queues=キュー
|
||||||
|
monitor.queue=キュー: %s
|
||||||
|
monitor.queue.name=キュー名
|
||||||
|
monitor.queue.type=種類
|
||||||
|
monitor.queue.exemplar=要素の型
|
||||||
|
monitor.queue.numberworkers=ワーカー数
|
||||||
|
monitor.queue.maxnumberworkers=ワーカー数上限
|
||||||
|
monitor.queue.review=設定確認
|
||||||
|
monitor.queue.review_add=確認/ワーカー追加
|
||||||
|
monitor.queue.configuration=初期設定
|
||||||
|
monitor.queue.nopool.title=ワーカープールはありません
|
||||||
|
monitor.queue.nopool.desc=このキューは他のキューをラップし、これ自体にはワーカープールがありません。
|
||||||
|
monitor.queue.wrapped.desc=wrappedキューは、すぐに開始されないキューをラップし、入ってきたリクエストをチャンネルにバッファリングします。 これ自体にはワーカープールがありません。
|
||||||
|
monitor.queue.persistable-channel.desc=persistable-channelキューは二つのキューをラップします。 一つはchannelキューで、自分のワーカープールを持ちます。もう一つはlevelキューで、前回のシャットダウンからリクエストを引き継ぐためのものです。 これ自体にはワーカープールがありません。
|
||||||
|
monitor.queue.pool.timeout=タイムアウト
|
||||||
|
monitor.queue.pool.addworkers.title=ワーカーの追加
|
||||||
|
monitor.queue.pool.addworkers.submit=ワーカーを追加
|
||||||
|
monitor.queue.pool.addworkers.desc=このプールに、タイムアウト付きまたはタイムアウト無しでワーカーを追加します。 タイムアウトを指定した場合は、タイムアウト後にそれらのワーカーがこのプールから取り除かれます。
|
||||||
|
monitor.queue.pool.addworkers.numberworkers.placeholder=ワーカー数
|
||||||
|
monitor.queue.pool.addworkers.timeout.placeholder=0でタイムアウト無し
|
||||||
|
monitor.queue.pool.addworkers.mustnumbergreaterzero=追加するワーカー数は1以上にしてください
|
||||||
|
monitor.queue.pool.addworkers.musttimeoutduration=タイムアウトは 、Go言語の時間差表記(例 5m)、または0にしてください
|
||||||
|
|
||||||
|
monitor.queue.settings.title=プール設定
|
||||||
|
monitor.queue.settings.desc=ワーカーへのキューのブロックが発生すると、それに応じてプール数がブースト分ずつ動的に増えます。 これらの変更は現在のワーカーグループには影響しません。
|
||||||
|
monitor.queue.settings.timeout=ブースト分のタイムアウト
|
||||||
|
monitor.queue.settings.timeout.placeholder=現在の設定 %[1]v
|
||||||
|
monitor.queue.settings.timeout.error=タイムアウトは 、Go言語の時間差表記(例 5m)、または0にしてください
|
||||||
|
monitor.queue.settings.numberworkers=ブースト分のワーカー数
|
||||||
|
monitor.queue.settings.numberworkers.placeholder=現在の設定 %[1]d
|
||||||
|
monitor.queue.settings.numberworkers.error=追加するワーカー数はゼロ以上にしてください
|
||||||
|
monitor.queue.settings.maxnumberworkers=ワーカー数上限
|
||||||
|
monitor.queue.settings.maxnumberworkers.placeholder=現在の設定 %[1]d
|
||||||
|
monitor.queue.settings.maxnumberworkers.error=ワーカー数上限は数値にしてください
|
||||||
|
monitor.queue.settings.submit=設定を更新
|
||||||
|
monitor.queue.settings.changed=設定を更新しました
|
||||||
|
monitor.queue.settings.blocktimeout=現在のブロックタイムアウト
|
||||||
|
monitor.queue.settings.blocktimeout.value=%[1]v
|
||||||
|
|
||||||
|
monitor.queue.pool.none=このキューにはプールがありません
|
||||||
|
monitor.queue.pool.added=ワーカーグループを追加しました
|
||||||
|
monitor.queue.pool.max_changed=ワーカー数の上限を変更しました
|
||||||
|
monitor.queue.pool.workers.title=アクティブなワーカーグループ
|
||||||
|
monitor.queue.pool.workers.none=ワーカーグループはありません。
|
||||||
|
monitor.queue.pool.cancel=ワーカーグループのシャットダウン
|
||||||
|
monitor.queue.pool.cancelling=ワーカーグループをシャットダウンしています
|
||||||
|
monitor.queue.pool.cancel_notices=このワーカー数 %s のグループをシャットダウンしますか?
|
||||||
|
monitor.queue.pool.cancel_desc=キューをワーカーグループ無しのままにすると、リクエストがブロックし続ける原因となります。
|
||||||
|
|
||||||
notices.system_notice_list=システム通知
|
notices.system_notice_list=システム通知
|
||||||
notices.view_detail_header=通知の詳細を表示
|
notices.view_detail_header=通知の詳細を表示
|
||||||
@@ -2120,4 +2172,3 @@ error.probable_bad_default_signature=警告! これはデフォルト鍵のIDで
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=このリポジトリのどのセクションにもアクセスが許可されていません。
|
error.no_unit_allowed_repo=このリポジトリのどのセクションにもアクセスが許可されていません。
|
||||||
error.unit_not_allowed=このセクションへのアクセスが許可されていません。
|
error.unit_not_allowed=このセクションへのアクセスが許可されていません。
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ dashboard=대시보드
|
|||||||
explore=탐색
|
explore=탐색
|
||||||
help=도움말
|
help=도움말
|
||||||
sign_in=로그인
|
sign_in=로그인
|
||||||
sign_in_with=냐후 ㅑㅜ 쨔소
|
sign_in_with=다음을 통해 로그인
|
||||||
sign_out=로그아웃
|
sign_out=로그아웃
|
||||||
sign_up=ㄲㄷ햔ㅅㄷㄱ
|
sign_up=가입하기
|
||||||
link_account=계정 연결
|
link_account=계정 연결
|
||||||
register=가입하기
|
register=가입하기
|
||||||
website=웹 사이트
|
website=웹 사이트
|
||||||
@@ -14,18 +14,18 @@ page=페이지
|
|||||||
template=템플릿
|
template=템플릿
|
||||||
language=언어
|
language=언어
|
||||||
notifications=알림
|
notifications=알림
|
||||||
create_new=ㅊㄱㄷㅁㅅㄷ...
|
create_new=생성하기
|
||||||
user_profile_and_more=ㅖ개랴ㅣㄷ 뭉 ㄴㄷㅅ샤ㅜㅎㄴ...
|
user_profile_and_more=프로파일 및 설정
|
||||||
signed_in_as=다음 사용자로 로그인됨
|
signed_in_as=다음 사용자로 로그인됨
|
||||||
enable_javascript=쏘ㅑㄴ ㅈ듀냣ㄷ 재간 ㅠㄷㅅㅅㄷㄱ 쟈소 ㅓㅁㅍㅁㄴㅊ갸ㅔㅅ.
|
enable_javascript=이 웹사이트는 자바스크립트 활성화가 필요합니다.
|
||||||
|
|
||||||
username=사용자명
|
username=사용자명
|
||||||
email=뜨먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ
|
email=이메일 주소
|
||||||
password=비밀번호
|
password=비밀번호
|
||||||
re_type=ㄲㄷ-쑈ㅔㄷ ㅖㅁㄴㄴ잭ㅇ
|
re_type=비밀번호 재입력
|
||||||
captcha=ㅊ몠촘
|
captcha=보안 문자
|
||||||
twofa=ㅆ재-ㄻㅊ색 며소두샻ㅁ샤ㅐㅜ
|
twofa=2단계 인증
|
||||||
twofa_scratch=ㅆ재-ㄻㅊ색 ㄴㅊㄱㅁㅅ초 챙ㄷ
|
twofa_scratch=2단계 일회성 코드
|
||||||
passcode=인증코드
|
passcode=인증코드
|
||||||
|
|
||||||
u2f_insert_key=보안 키를 입력해주세요.
|
u2f_insert_key=보안 키를 입력해주세요.
|
||||||
@@ -50,12 +50,12 @@ new_mirror=새로운 미러
|
|||||||
new_fork=새 저장소 포크
|
new_fork=새 저장소 포크
|
||||||
new_org=새로운 조직
|
new_org=새로운 조직
|
||||||
manage_org=조직 관리
|
manage_org=조직 관리
|
||||||
admin_panel=냣ㄷ ㅁ으ㅑㅜㅑㄴㅅㄱㅁ샤ㅐㅜ
|
admin_panel=사이트 관리
|
||||||
account_settings=계정 설정
|
account_settings=계정 설정
|
||||||
settings=설정
|
settings=설정
|
||||||
your_profile=ㅖ개랴ㅣㄷ
|
your_profile=프로필
|
||||||
your_starred=ㄴㅅㅁㄱㄱㄷㅇ
|
your_starred=즐겨찾기
|
||||||
your_settings=ㄴㄷㅅ샤ㅜㅎㄴ
|
your_settings=설정
|
||||||
|
|
||||||
all=전체
|
all=전체
|
||||||
sources=소스
|
sources=소스
|
||||||
@@ -66,71 +66,75 @@ forks=포크
|
|||||||
activities=활동
|
activities=활동
|
||||||
pull_requests=풀 리퀘스트
|
pull_requests=풀 리퀘스트
|
||||||
issues=이슈들
|
issues=이슈들
|
||||||
|
milestones=마일스톤
|
||||||
|
|
||||||
cancel=취소
|
cancel=취소
|
||||||
|
add=추가
|
||||||
|
|
||||||
write=쓰기
|
write=쓰기
|
||||||
preview=미리보기
|
preview=미리보기
|
||||||
loading=불러오는 중...
|
loading=불러오는 중...
|
||||||
|
|
||||||
[startpage]
|
[startpage]
|
||||||
|
app_desc=편리한 설치형 Git 서비스
|
||||||
|
license=오픈 소스
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
install=설치
|
install=설치
|
||||||
title=ㅑㅜㅑ샤미 채ㅜ랴혁ㅁ샤ㅐㅜ
|
title=초기 설정
|
||||||
docker_helper=Gitea를 Docker에서 실행하려면 설정 전에 이 <a target="_blank" rel="noopener noreferrer" href="%s">문서</a>를 읽어보세요.
|
docker_helper=Gitea를 Docker에서 실행하려면 설정 전에 이 <a target="_blank" rel="noopener noreferrer" href="%s">문서</a>를 읽어보세요.
|
||||||
requite_db_desc=Gitea를 실행하려면 MySQL, PostgreSQL, MSSQL 또는 SQLite3 중 하나가 필요합니다.
|
requite_db_desc=Gitea를 실행하려면 MySQL, PostgreSQL, MSSQL 또는 SQLite3 중 하나가 필요합니다.
|
||||||
db_title=데이터베이스 설정
|
db_title=데이터베이스 설정
|
||||||
db_type=데이터베이스 유형
|
db_type=데이터베이스 유형
|
||||||
host=호스트
|
host=호스트
|
||||||
user=ㅕㄴㄷ구믇
|
user=이름
|
||||||
password=비밀번호
|
password=비밀번호
|
||||||
db_name=데이터베이스 이름
|
db_name=데이터베이스 이름
|
||||||
ssl_mode=ㄴ니
|
ssl_mode=SSL
|
||||||
charset=문자셋
|
charset=문자셋
|
||||||
path=경로
|
path=경로
|
||||||
sqlite_helper=SQLite3 데이터베이스에 대한 파일 경로입니다.<br>Gitea를 서비스로 구동할 경우, 절대 경로를 입력해주십시오.
|
sqlite_helper=SQLite3 데이터베이스에 대한 파일 경로입니다.<br>Gitea를 서비스로 구동할 경우, 절대 경로를 입력해주십시오.
|
||||||
err_empty_db_path=SQLite3 데이터베이스 경로는 필수 입력 값입니다.
|
err_empty_db_path=SQLite3 데이터베이스 경로는 필수 입력 값입니다.
|
||||||
no_admin_and_disable_registration=ㅛㅐㅕ ㅊ무ㅜㅐㅅ 얀뮤ㅣㄷ ㅕㄴㄷㄱ ㄴ딜-ㄱㄷ햔ㅅㄱㅁ샤ㅐㅜ 쟈쇄ㅕㅅ ㅊㄱㄷㅁ샤ㅜㅎ 무 ㅁ으ㅑㅜㅑㄴㅅㄱㅁ색 ㅁㅊ채ㅕㅜㅅ.
|
no_admin_and_disable_registration=관리자 계정을 만들지 않고 등록을 비활성화할 수 없습니다.
|
||||||
err_empty_admin_password=쏟 ㅁ으ㅑㅜㅑㄴㅅㄱㅁ색 ㅔㅁㄴㄴ잭ㅇ ㅊ무ㅜㅐㅅ ㅠㄷ 드ㅔ쇼.
|
err_empty_admin_password=관리자 비밀번호는 비어 있을 수 없습니다.
|
||||||
err_empty_admin_email=관리자 이메일은 비어 있을 수 없습니다.
|
err_empty_admin_email=관리자 이메일은 비어 있을 수 없습니다.
|
||||||
err_admin_name_is_reserved=관리자 사용자 이름이 올바르지 않습니다, 제한된 사용자 이름입니다
|
err_admin_name_is_reserved=관리자 사용자 이름이 올바르지 않습니다, 제한된 사용자 이름입니다
|
||||||
err_admin_name_is_invalid=관리자 사용자 이름이 올바르지 않습니다
|
err_admin_name_is_invalid=관리자 사용자 이름이 올바르지 않습니다
|
||||||
|
|
||||||
general_title=ㅎ둗ㄱ미 ㄴㄷㅅ샤ㅜㅎㄴ
|
general_title=기본설정
|
||||||
app_name=냣ㄷ 쌰싣
|
app_name=사이트 제목
|
||||||
app_name_helper=ㅛㅐㅕ ㅊ무 둣ㄷㄱ ㅛㅐㅕㄱ 채ㅡㅔ무ㅛ ㅜ믇 ㅗㄷㄱㄷ.
|
app_name_helper=회사이름을 넣으세요.
|
||||||
repo_path=저장소 최상위 경로
|
repo_path=저장소 최상위 경로
|
||||||
repo_path_helper=ㄲ드ㅐㅅㄷ 햣 ㄱ데ㅐ냐새갿ㄴ 쟈ㅣㅣ ㅠㄷ ㄴㅁㅍㄷㅇ 새 소ㅑㄴ 약ㄷㅊ새교.
|
repo_path_helper=Git 원격 저장소는 이 디렉터리에 저장 됩니다.
|
||||||
lfs_path=햣 ㅣㄹㄴ 깨ㅐㅅ ㅖㅁ소
|
lfs_path=Git LFS 루트 경로
|
||||||
lfs_path_helper=랴ㅣㄷㄴ ㅅㄱㅁ찯ㅇ ㅠㅛ 햣 ㅣㄹㄴ 쟈ㅣㅣ ㅠㄷ ㄴ색ㄷㅇ ㅑㅜ 소ㅑㄴ 약ㄷㅊ새교. ㅣㄷㅁㅍㄷ 드ㅔ쇼 새 얀뮤ㅣㄷ.
|
lfs_path_helper=Git LFS에 저장된 파일들은 이 디렉토리에 저장됩니다. LFS를 사용하지 않는다면 빈칸으로 남겨주세요.
|
||||||
run_user=껴ㅜ ㅁㄴ ㅕㄴㄷ구믇
|
run_user=실행 사용자명
|
||||||
run_user_helper=뚯ㄷㄱ 솓 ㅐㅔㄷㄱㅁ샤ㅜㅎ 뇬ㅅ드 ㅕㄴㄷ구믇 솜ㅅ 햣ㄷㅁ 겨ㅜㄴ ㅁㄴ. ㅜㅐㅅㄷ 솜ㅅ 소ㅑㄴ ㅕㄴㄷㄱ ㅡㅕㄴㅅ ㅗㅁㅍㄷ ㅁㅊㅊㄷㄴㄴ 새 솓 ㄱ데ㅐ냐새교 개ㅐㅅ ㅔㅁ소.
|
run_user_helper=Gitea 를 실행할 시스템 사용자명을 넣으세요. 시스템 사용자는 레포지토리 루트 경로에 대한 권한이 필요합니다.
|
||||||
domain=ㄴ노 ㄴㄷㄱㅍㄷㄱ 애ㅡ먀ㅜ
|
domain=SSH 서버 도메인
|
||||||
domain_helper=애ㅡ먀ㅜ ㅐㄱ ㅙㄴㅅ ㅁㅇㅇㄱㄷㄴㄴ 랙 노ㅗ 치ㅐㅜㄷ ㅕ낀.
|
domain_helper=SSH clone URL 에 대한 도메인 또는 호스트 주소
|
||||||
ssh_port=ㄴ노 ㄴㄷㄱㅍㄷㄱ ㅖㅐㄳ
|
ssh_port=ㄴ노 ㄴㄷㄱㅍㄷㄱ ㅖㅐㄳ
|
||||||
ssh_port_helper=ㅖㅐㄳ ㅜㅕㅡㅠㄷㄱ ㅛㅐㅕㄱ 노ㅗ ㄴㄷㄱㅍㄷㄱ ㅣㅑㄴㅅ둔 ㅐㅜ. ㅣㄷㅁㅍㄷ 드ㅔ쇼 새 얀뮤ㅣㄷ.
|
ssh_port_helper=SSH 서버가 실행되고 있는 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
|
||||||
http_port=햣ㄷㅁ ㅗㅆ쎄 ㅣㅑㄴㅅ두 ㅖㅐㄳ
|
http_port=Gitea HTTP 수신 포트
|
||||||
http_port_helper=ㅖㅐㄳ ㅜㅕㅡㅠㄷㄱ 솓 햣ㄷㅁㄴ ㅈ듀 ㄴㄷㄱㅍㄷㄱ 쟈ㅣㅣ ㅣㅑㄴㅅ두 ㅐㅜ.
|
http_port_helper=Gitea 웹서버가 수신할 포트 번호
|
||||||
app_url=햣ㄷㅁ ㅠㅁㄴㄷ ㅕ끼
|
app_url=Gitea 기본 URL
|
||||||
app_url_helper=ㅠㅁㄴㄷ ㅁㅇㅇㄱㄷㄴㄴ 랙 ㅗㅆ쎼(ㄴ) 치ㅐㅜㄷ ㅕ낀 뭉 드먀ㅣ ㅜㅐ샤럋ㅁ샤ㅐㅜㄴ.
|
app_url_helper=HTTP(S) clone URL 및 이메일 알림 기본 주소
|
||||||
log_root_path=로그 경로
|
log_root_path=로그 경로
|
||||||
log_root_path_helper=ㅣㅐㅎ 랴ㅣㄷㄴ 쟈ㅣㅣ ㅠㄷ ㅈ걋ㅅ두 새 소ㅑㄴ 약ㄷㅊ새교.
|
log_root_path_helper=로그파일은 이 디렉토리에 저장됩니다.
|
||||||
|
|
||||||
optional_title=추가설정
|
optional_title=추가설정
|
||||||
email_title=뜨먀ㅣ ㄴㄷㅅ샤ㅜㅎㄴ
|
email_title=이메일 설정
|
||||||
smtp_host=SMTP 호스트
|
smtp_host=SMTP 호스트
|
||||||
smtp_from=ㄴ둥 뜨먀ㅣ ㅁㄴ
|
smtp_from=이메일 발신인
|
||||||
smtp_from_helper=뜨먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ 햣ㄷㅁ 쟈ㅣㅣ ㅕㄴㄷ. 뚯ㄷㄱ ㅁ ㅔㅣ먀ㅜ 드먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ ㅐㄱ ㅕㄴㄷ 솓 "ㅜ믇" <드먀ㅣ@ㄷㅌ므ㅔㅣㄷ.kr> 래금ㅅ.
|
smtp_from_helper=Gitea 가 사용할 이메일 주소. 이메일 주소 또는 "이름" <email@example.com> 형식으로 입력하세요.
|
||||||
mailer_user=느쎼 ㅕㄴㄷ구믇
|
mailer_user=SMTP 사용자이름
|
||||||
mailer_password=느쎼 ㅖㅁㄴㄴ잭ㅇ
|
mailer_password=SMTP 비밀번호
|
||||||
register_confirm=ㄲㄷ벼ㅑㄱㄷ 뜨먀ㅣ 채ㅜ랴금샤ㅐㅜ 새 ㄲㄷ햔ㅅㄷㄱ
|
register_confirm=가입시 이메일 확인 필수
|
||||||
mail_notify=뚜뮤ㅣㄷ 뜨먀ㅣ ㅜㅐ샤럋ㅁ샤ㅐㅜㄴ
|
mail_notify=이메일 알림 켜기
|
||||||
server_service_title=ㄴㄷㄱㅍㄷㄱ 뭉 쏘ㅑㄱㅇ-ㅖㅁㄱ쇼 ㄴㄷㄱ퍛ㄷ ㄴㄷㅅ샤ㅜㅎㄴ
|
server_service_title=서버 및 기타 서비스 설정
|
||||||
offline_mode=뚜뮤ㅣㄷ ㅣㅐㅊ미 ㅡㅐㅇㄷ
|
offline_mode=로컬 모드 켜기
|
||||||
offline_mode_popup=얀뮤ㅣㄷ 소ㅑㄱㅇ-ㅔㅁㄱ쇼 채ㅜㅅ둣 ㅇ디ㅑㅍㄷ교 ㅜㄷㅅ재간 뭉 ㄴㄷㄱㅍㄷ 미ㅣ ㄱㄷ내ㅕㄱㅊㄷㄴ ㅣㅐㅊ미ㅣㅛ.
|
offline_mode_popup=타사 콘텐츠 전송 네트워크를 사용하지 않도록 설정하고 모든 리소스를 로컬로 제공하십시오.
|
||||||
disable_gravatar=얀뮤ㅣㄷ ㅎㄱㅁㅍㅍㅁㅅㅁㄱ
|
disable_gravatar=Gravatar 사용안함
|
||||||
disable_gravatar_popup=얀뮤ㅣㄷ ㅎㄱㅁㅍㅁㅅㅁㄱ 뭉 소ㅑㄱㅇ-ㅔㅁㄱ쇼 ㅁㅍㅁㄴㅅㅁㄱ 내ㅕㄱㅊㄷㄴ. ㅁ ㅇㄷㄹ며ㅣㅅ ㅁㅍㅁㅅㅁㄱ 쟈ㅣㅣ ㅠㄷ ㅕㄴㄷㅇ ㅕㅟㄷㄴㄴ ㅁ ㅕㄴㄷㄱ ㅣㅐㅊ미ㅣㅛ ㅕㅔㅣㅐㅁㅇㄴ 무 ㅁㅍㅁㅅㅁㄱ.
|
disable_gravatar_popup=Gravatar 및 타사 아바타 소스를 사용하지 않도록 설정합니다. 사용자가 로컬로 아바타를 업로드하지 않는 한 기본 아바타가 사용됩니다.
|
||||||
federated_avatar_lookup=아바타 연동 사용여부
|
federated_avatar_lookup=아바타 연동 사용여부
|
||||||
federated_avatar_lookup_popup=libravatar 기반 오픈소스 서비스 사용 목적으로 연합 아바타 조회를 허용하기
|
federated_avatar_lookup_popup=libravatar 기반 오픈소스 서비스 사용 목적으로 연합 아바타 조회를 허용하기
|
||||||
disable_registration=사용자 등록 비활성화
|
disable_registration=사용자 등록 비활성화
|
||||||
@@ -509,6 +513,8 @@ confirm_delete_account=삭제 승인
|
|||||||
delete_account_title=사용자 계정 삭제
|
delete_account_title=사용자 계정 삭제
|
||||||
delete_account_desc=이 계정을 정말로 삭제하시겠습니까?
|
delete_account_desc=이 계정을 정말로 삭제하시겠습니까?
|
||||||
|
|
||||||
|
email_notifications.enable=이메일 알림 켜기
|
||||||
|
email_notifications.disable=이메일 알림 끄기
|
||||||
|
|
||||||
[repo]
|
[repo]
|
||||||
owner=소유자
|
owner=소유자
|
||||||
@@ -879,6 +885,7 @@ milestones.filter_sort.most_complete=완료율이 높은 순
|
|||||||
milestones.filter_sort.most_issues=이슈 많은 순
|
milestones.filter_sort.most_issues=이슈 많은 순
|
||||||
milestones.filter_sort.least_issues=이슈 적은 순
|
milestones.filter_sort.least_issues=이슈 적은 순
|
||||||
|
|
||||||
|
|
||||||
ext_wiki=외부 위키
|
ext_wiki=외부 위키
|
||||||
ext_wiki.desc=외부 위키에 연결하기.
|
ext_wiki.desc=외부 위키에 연결하기.
|
||||||
|
|
||||||
@@ -960,6 +967,8 @@ settings.basic_settings=기본 설정
|
|||||||
settings.mirror_settings=미러 설정
|
settings.mirror_settings=미러 설정
|
||||||
settings.sync_mirror=지금 동기화
|
settings.sync_mirror=지금 동기화
|
||||||
settings.mirror_sync_in_progress=미러 동기화 진행중입니다. 잠시 후 다시 확인해주십시오.
|
settings.mirror_sync_in_progress=미러 동기화 진행중입니다. 잠시 후 다시 확인해주십시오.
|
||||||
|
settings.email_notifications.enable=이메일 알림 켜기
|
||||||
|
settings.email_notifications.disable=이메일 알림 끄기
|
||||||
settings.site=웹 사이트
|
settings.site=웹 사이트
|
||||||
settings.update_settings=설정 저장
|
settings.update_settings=설정 저장
|
||||||
settings.advanced_settings=고급 설정
|
settings.advanced_settings=고급 설정
|
||||||
@@ -1080,6 +1089,8 @@ settings.protected_branch_can_push_yes=푸시할 수 있습니다.
|
|||||||
settings.protected_branch_can_push_no=푸시할 수 없습니다.
|
settings.protected_branch_can_push_no=푸시할 수 없습니다.
|
||||||
settings.branch_protection='<b>%s</b>' 브랜치 보호
|
settings.branch_protection='<b>%s</b>' 브랜치 보호
|
||||||
settings.protect_this_branch=브랜치 보호 활성화
|
settings.protect_this_branch=브랜치 보호 활성화
|
||||||
|
settings.protect_disable_push=푸시 끄기
|
||||||
|
settings.protect_enable_push=푸시 켜기
|
||||||
settings.protect_whitelist_search_users=사용자 찾기...
|
settings.protect_whitelist_search_users=사용자 찾기...
|
||||||
settings.protect_whitelist_search_teams=팀 찾기...
|
settings.protect_whitelist_search_teams=팀 찾기...
|
||||||
settings.protect_merge_whitelist_committers=머지 화이트리스트 활성화
|
settings.protect_merge_whitelist_committers=머지 화이트리스트 활성화
|
||||||
@@ -1511,6 +1522,7 @@ monitor.process=실행중인 프로세스들
|
|||||||
monitor.desc=설명
|
monitor.desc=설명
|
||||||
monitor.start=시작 시간
|
monitor.start=시작 시간
|
||||||
monitor.execute_time=실행 시간
|
monitor.execute_time=실행 시간
|
||||||
|
monitor.queue.configuration=초기 설정
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1596,7 +1596,7 @@ settings.full_name=Pilns vārds, uzvārds
|
|||||||
settings.website=Mājas lapa
|
settings.website=Mājas lapa
|
||||||
settings.location=Atrašanās vieta
|
settings.location=Atrašanās vieta
|
||||||
settings.permission=Tiesības
|
settings.permission=Tiesības
|
||||||
settings.repoadminchangeteam=Repozitorija administrators var pievienot vain noņemt piekļuvi komandām
|
settings.repoadminchangeteam=Repozitorija administrators var pievienot vai noņemt piekļuvi komandām
|
||||||
settings.visibility=Redzamība
|
settings.visibility=Redzamība
|
||||||
settings.visibility.public=Publiska
|
settings.visibility.public=Publiska
|
||||||
settings.visibility.limited=Ierobežota (redzama tikai autorizētiem lietotājiem)
|
settings.visibility.limited=Ierobežota (redzama tikai autorizētiem lietotājiem)
|
||||||
@@ -2025,8 +2025,54 @@ monitor.execute_time=Izpildes laiks
|
|||||||
monitor.process.cancel=Atcelt procesu
|
monitor.process.cancel=Atcelt procesu
|
||||||
monitor.process.cancel_desc=Procesa atcelšana var radīt datu zaudējumus
|
monitor.process.cancel_desc=Procesa atcelšana var radīt datu zaudējumus
|
||||||
monitor.process.cancel_notices=Atcelt: <strong>%s</strong>?
|
monitor.process.cancel_notices=Atcelt: <strong>%s</strong>?
|
||||||
|
monitor.queues=Rindas
|
||||||
|
monitor.queue=Rinda: %s
|
||||||
|
monitor.queue.name=Nosaukums
|
||||||
|
monitor.queue.type=Veids
|
||||||
|
monitor.queue.exemplar=Eksemplāra veids
|
||||||
|
monitor.queue.numberworkers=Strādņu skaits
|
||||||
|
monitor.queue.maxnumberworkers=Maksimālais strādņu skaits
|
||||||
|
monitor.queue.review=Pārbaudīt konfigurāciju
|
||||||
|
monitor.queue.review_add=Pārbaudīt/Pievienot strādņus
|
||||||
|
monitor.queue.configuration=Sākotnējā konfigurācija
|
||||||
|
monitor.queue.nopool.title=Nav strādņu pūla
|
||||||
|
monitor.queue.nopool.desc=Šī rinda apvieno citas rindas un tai nav strādņu pūla.
|
||||||
|
monitor.queue.wrapped.desc=Apvienojošā rinda apvieno lēni startējošās rindas, uzkrājot sarindotos pieprasījumus kanālā. Tai nav strādņu pūla.
|
||||||
|
monitor.queue.persistable-channel.desc=Patstāvīgas kanāli apvieno divas rindas, kanāla rindu, kurai ir savs strādņu pūls un līmeņu rindu patstāvīgajiem pieprasījumiem no iepriekšejām izslēgšanām. Tai nav strādņu pūla.
|
||||||
|
monitor.queue.pool.timeout=Noildze
|
||||||
|
monitor.queue.pool.addworkers.title=Pievienot strādņus
|
||||||
|
monitor.queue.pool.addworkers.submit=Pievienot
|
||||||
|
monitor.queue.pool.addworkers.desc=Pievienot strādņus šim pūlam ar vai bez noildzes. Ja uzstādīsies noildzi, tad šie strādņi tiks noņemti no pūla, kad noildze būs iestājusies.
|
||||||
|
monitor.queue.pool.addworkers.numberworkers.placeholder=Strādņu skaits
|
||||||
|
monitor.queue.pool.addworkers.timeout.placeholder=Norādiet 0, lai nebūtu noildzes
|
||||||
|
monitor.queue.pool.addworkers.mustnumbergreaterzero=Strādņu skaitam, ko pievienot, ir jābūt lielākam par nulli
|
||||||
|
monitor.queue.pool.addworkers.musttimeoutduration=Noildzei ir jābūt norādītai kā ilgumam, piemēram, 5m vai 0
|
||||||
|
|
||||||
|
monitor.queue.settings.title=Pūla iestatījumi
|
||||||
|
monitor.queue.settings.desc=Pūli var dinamiski augt un paildzinātu atbildi uz strādņu rindas bloķēšanu. Šis izmaiņas ietekmēs pašreizējās strādņu grupas.
|
||||||
|
monitor.queue.settings.timeout=Pagarināt noildzi
|
||||||
|
monitor.queue.settings.timeout.placeholder=Pašalaik %[1]v
|
||||||
|
monitor.queue.settings.timeout.error=Noildzei ir jābūt norādītai kā ilgumam, piemēram, 5m vai 0
|
||||||
|
monitor.queue.settings.numberworkers=Palielināt strādņu skaitu
|
||||||
|
monitor.queue.settings.numberworkers.placeholder=Pašalaik %[1]d
|
||||||
|
monitor.queue.settings.numberworkers.error=Strādņu skaitam ir jābūt lielākam vai vienādam ar nulli
|
||||||
|
monitor.queue.settings.maxnumberworkers=Maksimālais strādņu skaits
|
||||||
|
monitor.queue.settings.maxnumberworkers.placeholder=Pašalaik %[1]d
|
||||||
|
monitor.queue.settings.maxnumberworkers.error=Maksimālajam strādņu skaitam ir jābūt skaitlim
|
||||||
|
monitor.queue.settings.submit=Saglabāt iestatījumus
|
||||||
|
monitor.queue.settings.changed=Iestatījumi saglabāti
|
||||||
|
monitor.queue.settings.blocktimeout=Pašreizējās grupas noildze
|
||||||
|
monitor.queue.settings.blocktimeout.value=%[1]v
|
||||||
|
|
||||||
|
monitor.queue.pool.none=Rindai nav pūla
|
||||||
|
monitor.queue.pool.added=Strādņu grupa pievienota
|
||||||
|
monitor.queue.pool.max_changed=Maksimālais strādņu skaits mainīts
|
||||||
|
monitor.queue.pool.workers.title=Aktīvās strādņu grupas
|
||||||
|
monitor.queue.pool.workers.none=Nav strādņu grupu.
|
||||||
|
monitor.queue.pool.cancel=Izslēgt strādņu grupu
|
||||||
|
monitor.queue.pool.cancelling=Strādņu grupa tiek izslēgta
|
||||||
|
monitor.queue.pool.cancel_notices=Izslēgt šo grupu ar %s strādņiem?
|
||||||
|
monitor.queue.pool.cancel_desc=Atstājot rindu bez nevienas strādņu grupas, var radīt pieprasījumu bloķēšanos.
|
||||||
|
|
||||||
notices.system_notice_list=Sistēmas paziņojumi
|
notices.system_notice_list=Sistēmas paziņojumi
|
||||||
notices.view_detail_header=Skatīt paziņojuma detaļas
|
notices.view_detail_header=Skatīt paziņojuma detaļas
|
||||||
@@ -2120,4 +2166,3 @@ error.probable_bad_default_signature=BRĪDINĀJUMS! Lai arī šai atslēgai ir n
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Jums nav tiesību aplūkot nevienu šī repozitorija sadaļu.
|
error.no_unit_allowed_repo=Jums nav tiesību aplūkot nevienu šī repozitorija sadaļu.
|
||||||
error.unit_not_allowed=Jums nav tiesību piekļūt šai repozitorija sadaļai.
|
error.unit_not_allowed=Jums nav tiesību piekļūt šai repozitorija sadaļai.
|
||||||
|
|
||||||
|
|||||||
@@ -2100,4 +2100,3 @@ error.probable_bad_default_signature=OSTRZEŻENIE! Pomimo, że domyślny klucz p
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Nie masz uprawnień do żadnej sekcji tego repozytorium.
|
error.no_unit_allowed_repo=Nie masz uprawnień do żadnej sekcji tego repozytorium.
|
||||||
error.unit_not_allowed=Nie masz uprawnień do tej sekcji repozytorium.
|
error.unit_not_allowed=Nie masz uprawnień do tej sekcji repozytorium.
|
||||||
|
|
||||||
|
|||||||
@@ -1062,6 +1062,8 @@ pulls.no_merge_desc=O merge deste pull request não pode ser aplicado porque tod
|
|||||||
pulls.no_merge_helper=Habilite as opções de merge nas configurações do repositório ou faça o merge do pull request manualmente.
|
pulls.no_merge_helper=Habilite as opções de merge nas configurações do repositório ou faça o merge do pull request manualmente.
|
||||||
pulls.no_merge_wip=O merge deste pull request não pode ser aplicado porque está marcado como um trabalho em andamento.
|
pulls.no_merge_wip=O merge deste pull request não pode ser aplicado porque está marcado como um trabalho em andamento.
|
||||||
pulls.no_merge_status_check=Este pull request não pode ter seu merge aplicado porque nem todas as verificações de status necessárias foram bem sucedidas.
|
pulls.no_merge_status_check=Este pull request não pode ter seu merge aplicado porque nem todas as verificações de status necessárias foram bem sucedidas.
|
||||||
|
pulls.no_merge_not_ready=Este pull request não está pronto para ser realizado o merge, verifique o status da revisão e as verificações de status.
|
||||||
|
pulls.no_merge_access=Você não está autorizado para realizar o merge deste pull request.
|
||||||
pulls.merge_pull_request=Aplicar merge do pull request
|
pulls.merge_pull_request=Aplicar merge do pull request
|
||||||
pulls.rebase_merge_pull_request=Aplicar Rebase e Merge
|
pulls.rebase_merge_pull_request=Aplicar Rebase e Merge
|
||||||
pulls.rebase_merge_commit_pull_request=Aplicar Rebase e Merge (--no-ff)
|
pulls.rebase_merge_commit_pull_request=Aplicar Rebase e Merge (--no-ff)
|
||||||
@@ -1412,6 +1414,8 @@ settings.protect_approvals_whitelist_enabled=Restringir aprovações a usuários
|
|||||||
settings.protect_approvals_whitelist_enabled_desc=Somente as avaliações de usuários ou equipes da lista permitida serão contadas com as aprovações necessárias. Sem aprovação da lista permitida, as revisões de qualquer pessoa com acesso de escrita contam para as aprovações necessárias.
|
settings.protect_approvals_whitelist_enabled_desc=Somente as avaliações de usuários ou equipes da lista permitida serão contadas com as aprovações necessárias. Sem aprovação da lista permitida, as revisões de qualquer pessoa com acesso de escrita contam para as aprovações necessárias.
|
||||||
settings.protect_approvals_whitelist_users=Usuários com permissão de revisão:
|
settings.protect_approvals_whitelist_users=Usuários com permissão de revisão:
|
||||||
settings.protect_approvals_whitelist_teams=Equipes com permissão de revisão:
|
settings.protect_approvals_whitelist_teams=Equipes com permissão de revisão:
|
||||||
|
settings.dismiss_stale_approvals=Descartar aprovações obsoletas
|
||||||
|
settings.dismiss_stale_approvals_desc=Quando novos commits que mudam o conteúdo do pull request são enviados para o branch, as antigas aprovações serão descartadas.
|
||||||
settings.add_protected_branch=Habilitar proteção
|
settings.add_protected_branch=Habilitar proteção
|
||||||
settings.delete_protected_branch=Desabilitar proteção
|
settings.delete_protected_branch=Desabilitar proteção
|
||||||
settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada.
|
settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada.
|
||||||
@@ -1747,6 +1751,7 @@ users.new_account=Criar conta de usuário
|
|||||||
users.name=Nome de usuário
|
users.name=Nome de usuário
|
||||||
users.activated=Ativado
|
users.activated=Ativado
|
||||||
users.admin=Administrador
|
users.admin=Administrador
|
||||||
|
users.restricted=Restrito
|
||||||
users.repos=Repositórios
|
users.repos=Repositórios
|
||||||
users.created=Criado
|
users.created=Criado
|
||||||
users.last_login=Último acesso
|
users.last_login=Último acesso
|
||||||
@@ -1765,6 +1770,7 @@ users.max_repo_creation_desc=(Use -1 para usar o limite padrão global.)
|
|||||||
users.is_activated=Conta de usuário está ativada
|
users.is_activated=Conta de usuário está ativada
|
||||||
users.prohibit_login=Desabilitar acesso
|
users.prohibit_login=Desabilitar acesso
|
||||||
users.is_admin=É administrador
|
users.is_admin=É administrador
|
||||||
|
users.is_restricted=Está restrito
|
||||||
users.allow_git_hook=Pode criar hooks Git
|
users.allow_git_hook=Pode criar hooks Git
|
||||||
users.allow_import_local=Pode importar repositórios locais
|
users.allow_import_local=Pode importar repositórios locais
|
||||||
users.allow_create_organization=Pode criar organizações
|
users.allow_create_organization=Pode criar organizações
|
||||||
@@ -2166,4 +2172,3 @@ error.probable_bad_default_signature=AVISO! Embora a chave padrão tenha este ID
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Você não tem permissão para acessar nenhuma seção deste repositório.
|
error.no_unit_allowed_repo=Você não tem permissão para acessar nenhuma seção deste repositório.
|
||||||
error.unit_not_allowed=Você não tem permissão para acessar esta seção do repositório.
|
error.unit_not_allowed=Você não tem permissão para acessar esta seção do repositório.
|
||||||
|
|
||||||
|
|||||||
@@ -2113,4 +2113,3 @@ error.probable_bad_default_signature=UYARI! Varsayılan anahtarın bu kimliği o
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=Bu deponun hiçbir bölümüne erişme izniniz yok.
|
error.no_unit_allowed_repo=Bu deponun hiçbir bölümüne erişme izniniz yok.
|
||||||
error.unit_not_allowed=Bu depo bölümüne erişme izniniz yok.
|
error.unit_not_allowed=Bu depo bölümüne erişme izniniz yok.
|
||||||
|
|
||||||
|
|||||||
@@ -2115,4 +2115,3 @@ error.probable_bad_default_signature=УВАГА! Хоча типовий клю
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=У вас немає доступу до жодного розділу цього репозитория.
|
error.no_unit_allowed_repo=У вас немає доступу до жодного розділу цього репозитория.
|
||||||
error.unit_not_allowed=У вас немає доступу до жодного розділу цього репозитория.
|
error.unit_not_allowed=У вас немає доступу до жодного розділу цього репозитория.
|
||||||
|
|
||||||
|
|||||||
@@ -2166,4 +2166,3 @@ error.probable_bad_default_signature=警告!虽然默认密钥拥有此ID,
|
|||||||
[units]
|
[units]
|
||||||
error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。
|
error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。
|
||||||
error.unit_not_allowed=您没有权限访问此仓库单元
|
error.unit_not_allowed=您没有权限访问此仓库单元
|
||||||
|
|
||||||
|
|||||||
1
public/vendor/plugins/fomantic/semantic.css
vendored
1
public/vendor/plugins/fomantic/semantic.css
vendored
@@ -8,7 +8,6 @@
|
|||||||
* http://opensource.org/licenses/MIT
|
* http://opensource.org/licenses/MIT
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin&display=swap');
|
|
||||||
/*!
|
/*!
|
||||||
* # Fomantic-UI - Reset
|
* # Fomantic-UI - Reset
|
||||||
* http://github.com/fomantic/Fomantic-UI/
|
* http://github.com/fomantic/Fomantic-UI/
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
* Released under the MIT license
|
* Released under the MIT license
|
||||||
* http://opensource.org/licenses/MIT
|
* http://opensource.org/licenses/MIT
|
||||||
*
|
*
|
||||||
*/
|
*//*!
|
||||||
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin&display=swap);/*!
|
|
||||||
* # Fomantic-UI - Reset
|
* # Fomantic-UI - Reset
|
||||||
* http://github.com/fomantic/Fomantic-UI/
|
* http://github.com/fomantic/Fomantic-UI/
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ func parseLDAPConfig(form auth.AuthenticationForm) *models.LDAPConfig {
|
|||||||
SearchPageSize: pageSize,
|
SearchPageSize: pageSize,
|
||||||
Filter: form.Filter,
|
Filter: form.Filter,
|
||||||
AdminFilter: form.AdminFilter,
|
AdminFilter: form.AdminFilter,
|
||||||
|
AllowDeactivateAll: form.AllowDeactivateAll,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ func SearchIssues(ctx *context.APIContext) {
|
|||||||
// description: repository to prioritize in the results
|
// description: repository to prioritize in the results
|
||||||
// type: integer
|
// type: integer
|
||||||
// format: int64
|
// format: int64
|
||||||
|
// - name: type
|
||||||
|
// in: query
|
||||||
|
// description: filter by type (issues / pulls) if set
|
||||||
|
// type: string
|
||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/IssueList"
|
// "$ref": "#/responses/IssueList"
|
||||||
@@ -67,20 +71,24 @@ func SearchIssues(ctx *context.APIContext) {
|
|||||||
|
|
||||||
// find repos user can access (for issue search)
|
// find repos user can access (for issue search)
|
||||||
repoIDs := make([]int64, 0)
|
repoIDs := make([]int64, 0)
|
||||||
|
opts := &models.SearchRepoOptions{
|
||||||
|
PageSize: 15,
|
||||||
|
Private: false,
|
||||||
|
AllPublic: true,
|
||||||
|
TopicOnly: false,
|
||||||
|
Collaborate: util.OptionalBoolNone,
|
||||||
|
UserIsAdmin: ctx.IsUserSiteAdmin(),
|
||||||
|
OrderBy: models.SearchOrderByRecentUpdated,
|
||||||
|
}
|
||||||
|
if ctx.IsSigned {
|
||||||
|
opts.Private = true
|
||||||
|
opts.AllLimited = true
|
||||||
|
opts.UserID = ctx.User.ID
|
||||||
|
}
|
||||||
issueCount := 0
|
issueCount := 0
|
||||||
for page := 1; ; page++ {
|
for page := 1; ; page++ {
|
||||||
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
|
opts.Page = page
|
||||||
Page: page,
|
repos, count, err := models.SearchRepositoryByName(opts)
|
||||||
PageSize: 15,
|
|
||||||
Private: true,
|
|
||||||
Keyword: "",
|
|
||||||
OwnerID: ctx.User.ID,
|
|
||||||
TopicOnly: false,
|
|
||||||
Collaborate: util.OptionalBoolNone,
|
|
||||||
UserIsAdmin: ctx.IsUserSiteAdmin(),
|
|
||||||
UserID: ctx.User.ID,
|
|
||||||
OrderBy: models.SearchOrderByRecentUpdated,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
|
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
|
||||||
return
|
return
|
||||||
@@ -125,6 +133,16 @@ func SearchIssues(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPull util.OptionalBool
|
||||||
|
switch ctx.Query("type") {
|
||||||
|
case "pulls":
|
||||||
|
isPull = util.OptionalBoolTrue
|
||||||
|
case "issues":
|
||||||
|
isPull = util.OptionalBoolFalse
|
||||||
|
default:
|
||||||
|
isPull = util.OptionalBoolNone
|
||||||
|
}
|
||||||
|
|
||||||
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
||||||
// This would otherwise return all issues if no issues were found by the search.
|
// This would otherwise return all issues if no issues were found by the search.
|
||||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||||
@@ -137,6 +155,7 @@ func SearchIssues(ctx *context.APIContext) {
|
|||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
SortType: "priorityrepo",
|
SortType: "priorityrepo",
|
||||||
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
|
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
|
||||||
|
IsPull: isPull,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +207,10 @@ func ListIssues(ctx *context.APIContext) {
|
|||||||
// in: query
|
// in: query
|
||||||
// description: search string
|
// description: search string
|
||||||
// type: string
|
// type: string
|
||||||
|
// - name: type
|
||||||
|
// in: query
|
||||||
|
// description: filter by type (issues / pulls) if set
|
||||||
|
// type: string
|
||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/IssueList"
|
// "$ref": "#/responses/IssueList"
|
||||||
@@ -223,6 +246,16 @@ func ListIssues(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPull util.OptionalBool
|
||||||
|
switch ctx.Query("type") {
|
||||||
|
case "pulls":
|
||||||
|
isPull = util.OptionalBoolTrue
|
||||||
|
case "issues":
|
||||||
|
isPull = util.OptionalBoolFalse
|
||||||
|
default:
|
||||||
|
isPull = util.OptionalBoolNone
|
||||||
|
}
|
||||||
|
|
||||||
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
// Only fetch the issues if we either don't have a keyword or the search returned issues
|
||||||
// This would otherwise return all issues if no issues were found by the search.
|
// This would otherwise return all issues if no issues were found by the search.
|
||||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||||
@@ -233,6 +266,7 @@ func ListIssues(ctx *context.APIContext) {
|
|||||||
IsClosed: isClosed,
|
IsClosed: isClosed,
|
||||||
IssueIDs: issueIDs,
|
IssueIDs: issueIDs,
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
|
IsPull: isPull,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,6 +491,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
issue.Repo = ctx.Repo.Repository
|
issue.Repo = ctx.Repo.Repository
|
||||||
|
canWrite := ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
||||||
|
|
||||||
err = issue.LoadAttributes()
|
err = issue.LoadAttributes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -464,7 +499,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if !issue.IsPoster(ctx.User.ID) && !canWrite {
|
||||||
ctx.Status(http.StatusForbidden)
|
ctx.Status(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -477,7 +512,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update or remove the deadline, only if set and allowed
|
// Update or remove the deadline, only if set and allowed
|
||||||
if (form.Deadline != nil || form.RemoveDeadline != nil) && ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if (form.Deadline != nil || form.RemoveDeadline != nil) && canWrite {
|
||||||
var deadlineUnix timeutil.TimeStamp
|
var deadlineUnix timeutil.TimeStamp
|
||||||
|
|
||||||
if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() {
|
if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() {
|
||||||
@@ -501,7 +536,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||||
|
|
||||||
if ctx.Repo.CanWrite(models.UnitTypeIssues) && (form.Assignees != nil || form.Assignee != nil) {
|
if canWrite && (form.Assignees != nil || form.Assignee != nil) {
|
||||||
oneAssignee := ""
|
oneAssignee := ""
|
||||||
if form.Assignee != nil {
|
if form.Assignee != nil {
|
||||||
oneAssignee = *form.Assignee
|
oneAssignee = *form.Assignee
|
||||||
@@ -514,7 +549,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Repo.CanWrite(models.UnitTypeIssues) && form.Milestone != nil &&
|
if canWrite && form.Milestone != nil &&
|
||||||
issue.MilestoneID != *form.Milestone {
|
issue.MilestoneID != *form.Milestone {
|
||||||
oldMilestoneID := issue.MilestoneID
|
oldMilestoneID := issue.MilestoneID
|
||||||
issue.MilestoneID = *form.Milestone
|
issue.MilestoneID = *form.Milestone
|
||||||
@@ -600,7 +635,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||||
ctx.Error(http.StatusForbidden, "", "Not repo writer")
|
ctx.Error(http.StatusForbidden, "", "Not repo writer")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
|
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
|
||||||
ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
|
ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
|
|||||||
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err)
|
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment.Issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {
|
||||||
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
|
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||||
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
|
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.I
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||||
ctx.Status(http.StatusForbidden)
|
ctx.Status(http.StatusForbidden)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
status := &models.CommitStatus{
|
status := &models.CommitStatus{
|
||||||
State: models.CommitStatusState(form.State),
|
State: api.CommitStatusState(form.State),
|
||||||
TargetURL: form.TargetURL,
|
TargetURL: form.TargetURL,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Context: form.Context,
|
Context: form.Context,
|
||||||
@@ -220,13 +220,13 @@ func getCommitStatuses(ctx *context.APIContext, sha string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type combinedCommitStatus struct {
|
type combinedCommitStatus struct {
|
||||||
State models.CommitStatusState `json:"state"`
|
State api.CommitStatusState `json:"state"`
|
||||||
SHA string `json:"sha"`
|
SHA string `json:"sha"`
|
||||||
TotalCount int `json:"total_count"`
|
TotalCount int `json:"total_count"`
|
||||||
Statuses []*api.Status `json:"statuses"`
|
Statuses []*api.Status `json:"statuses"`
|
||||||
Repo *api.Repository `json:"repository"`
|
Repo *api.Repository `json:"repository"`
|
||||||
CommitURL string `json:"commit_url"`
|
CommitURL string `json:"commit_url"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCombinedCommitStatusByRef returns the combined status for any given commit hash
|
// GetCombinedCommitStatusByRef returns the combined status for any given commit hash
|
||||||
@@ -293,7 +293,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
|
|||||||
retStatus.Statuses = make([]*api.Status, 0, len(statuses))
|
retStatus.Statuses = make([]*api.Status, 0, len(statuses))
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
retStatus.Statuses = append(retStatus.Statuses, status.APIFormat())
|
retStatus.Statuses = append(retStatus.Statuses, status.APIFormat())
|
||||||
if status.State.IsWorseThan(retStatus.State) {
|
if status.State.NoBetterThan(retStatus.State) {
|
||||||
retStatus.State = status.State
|
retStatus.State = status.State
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,12 +157,12 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
|||||||
ctx.ServerError("OpenRepository", err)
|
ctx.ServerError("OpenRepository", err)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
|
defer headGitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// user should have permission to read baseRepo's codes and pulls, NOT headRepo's
|
// user should have permission to read baseRepo's codes and pulls, NOT headRepo's
|
||||||
permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
|
permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.ServerError("GetUserRepoPermission", err)
|
ctx.ServerError("GetUserRepoPermission", err)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
@@ -173,42 +173,40 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
|||||||
baseRepo,
|
baseRepo,
|
||||||
permBase)
|
permBase)
|
||||||
}
|
}
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.NotFound("ParseCompareInfo", nil)
|
ctx.NotFound("ParseCompareInfo", nil)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// user should have permission to read headrepo's codes
|
if !isSameRepo {
|
||||||
permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
|
// user should have permission to read headrepo's codes
|
||||||
if err != nil {
|
permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
|
||||||
headGitRepo.Close()
|
if err != nil {
|
||||||
ctx.ServerError("GetUserRepoPermission", err)
|
ctx.ServerError("GetUserRepoPermission", err)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
if !permHead.CanRead(models.UnitTypeCode) {
|
if !permHead.CanRead(models.UnitTypeCode) {
|
||||||
if log.IsTrace() {
|
if log.IsTrace() {
|
||||||
log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
|
log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
|
||||||
ctx.User,
|
ctx.User,
|
||||||
headRepo,
|
headRepo,
|
||||||
permHead)
|
permHead)
|
||||||
|
}
|
||||||
|
ctx.NotFound("ParseCompareInfo", nil)
|
||||||
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.NotFound("ParseCompareInfo", nil)
|
|
||||||
return nil, nil, nil, nil, "", ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if head branch is valid.
|
// Check if head branch is valid.
|
||||||
headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch)
|
headIsCommit := headGitRepo.IsCommitExist(headBranch)
|
||||||
headIsBranch := headGitRepo.IsBranchExist(headBranch)
|
headIsBranch := headGitRepo.IsBranchExist(headBranch)
|
||||||
headIsTag := headGitRepo.IsTagExist(headBranch)
|
headIsTag := headGitRepo.IsTagExist(headBranch)
|
||||||
if !headIsCommit && !headIsBranch && !headIsTag {
|
if !headIsCommit && !headIsBranch && !headIsTag {
|
||||||
// Check if headBranch is short sha commit hash
|
// Check if headBranch is short sha commit hash
|
||||||
if headCommit, _ := ctx.Repo.GitRepo.GetCommit(headBranch); headCommit != nil {
|
if headCommit, _ := headGitRepo.GetCommit(headBranch); headCommit != nil {
|
||||||
headBranch = headCommit.ID.String()
|
headBranch = headCommit.ID.String()
|
||||||
ctx.Data["HeadBranch"] = headBranch
|
ctx.Data["HeadBranch"] = headBranch
|
||||||
headIsCommit = true
|
headIsCommit = true
|
||||||
} else {
|
} else {
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.NotFound("IsRefExist", nil)
|
ctx.NotFound("IsRefExist", nil)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
@@ -229,14 +227,12 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
|||||||
baseRepo,
|
baseRepo,
|
||||||
permBase)
|
permBase)
|
||||||
}
|
}
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.NotFound("ParseCompareInfo", nil)
|
ctx.NotFound("ParseCompareInfo", nil)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch)
|
compareInfo, err := headGitRepo.GetCompareInfo(baseRepo.RepoPath(), baseBranch, headBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
headGitRepo.Close()
|
|
||||||
ctx.ServerError("GetCompareInfo", err)
|
ctx.ServerError("GetCompareInfo", err)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
@@ -385,7 +381,8 @@ func CompareDiff(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
defer headGitRepo.Close()
|
defer headGitRepo.Close()
|
||||||
|
|
||||||
if err := parseBaseRepoInfo(ctx, headRepo); err != nil {
|
var err error
|
||||||
|
if err = parseBaseRepoInfo(ctx, headRepo); err != nil {
|
||||||
ctx.ServerError("parseBaseRepoInfo", err)
|
ctx.ServerError("parseBaseRepoInfo", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -418,7 +415,7 @@ func CompareDiff(ctx *context.Context) {
|
|||||||
|
|
||||||
if !nothingToCompare {
|
if !nothingToCompare {
|
||||||
// Setup information for new form.
|
// Setup information for new form.
|
||||||
RetrieveRepoMetas(ctx, ctx.Repo.Repository)
|
RetrieveRepoMetas(ctx, ctx.Repo.Repository, true)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -427,6 +424,11 @@ func CompareDiff(ctx *context.Context) {
|
|||||||
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
|
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
|
||||||
afterCommitID := ctx.Data["AfterCommitID"].(string)
|
afterCommitID := ctx.Data["AfterCommitID"].(string)
|
||||||
|
|
||||||
|
if ctx.Data["Assignees"], err = ctx.Repo.Repository.GetAssignees(); err != nil {
|
||||||
|
ctx.ServerError("GetAssignees", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID)
|
ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID)
|
||||||
|
|
||||||
ctx.Data["IsRepoToolbarCommits"] = true
|
ctx.Data["IsRepoToolbarCommits"] = true
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/lfs"
|
"code.gitea.io/gitea/modules/lfs"
|
||||||
@@ -33,7 +34,12 @@ func ServeData(ctx *context.Context, name string, reader io.Reader) error {
|
|||||||
name = strings.Replace(name, ",", " ", -1)
|
name = strings.Replace(name, ",", " ", -1)
|
||||||
|
|
||||||
if base.IsTextFile(buf) || ctx.QueryBool("render") {
|
if base.IsTextFile(buf) || ctx.QueryBool("render") {
|
||||||
ctx.Resp.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
cs, err := charset.DetectEncoding(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Detect raw file %s charset failed: %v, using by default utf-8", name, err)
|
||||||
|
cs = "utf-8"
|
||||||
|
}
|
||||||
|
ctx.Resp.Header().Set("Content-Type", "text/plain; charset="+strings.ToLower(cs))
|
||||||
} else if base.IsImageFile(buf) || base.IsPDFFile(buf) {
|
} else if base.IsImageFile(buf) || base.IsPDFFile(buf) {
|
||||||
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
|
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
gocontext "context"
|
gocontext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -65,11 +67,12 @@ func HTTP(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPull bool
|
var isPull, receivePack bool
|
||||||
service := ctx.Query("service")
|
service := ctx.Query("service")
|
||||||
if service == "git-receive-pack" ||
|
if service == "git-receive-pack" ||
|
||||||
strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") {
|
strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") {
|
||||||
isPull = false
|
isPull = false
|
||||||
|
receivePack = true
|
||||||
} else if service == "git-upload-pack" ||
|
} else if service == "git-upload-pack" ||
|
||||||
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
|
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
|
||||||
isPull = true
|
isPull = true
|
||||||
@@ -282,6 +285,11 @@ func HTTP(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !repoExist {
|
if !repoExist {
|
||||||
|
if !receivePack {
|
||||||
|
ctx.HandleText(http.StatusNotFound, "Repository not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
||||||
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
||||||
return
|
return
|
||||||
@@ -290,6 +298,13 @@ func HTTP(ctx *context.Context) {
|
|||||||
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for users.")
|
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for users.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return dummy payload if GET receive-pack
|
||||||
|
if ctx.Req.Method == http.MethodGet {
|
||||||
|
dummyInfoRefs(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
repo, err = repo_service.PushCreateRepo(authUser, owner, reponame)
|
repo, err = repo_service.PushCreateRepo(authUser, owner, reponame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("pushCreateRepo: %v", err)
|
log.Error("pushCreateRepo: %v", err)
|
||||||
@@ -352,6 +367,48 @@ func HTTP(ctx *context.Context) {
|
|||||||
ctx.NotFound("Smart Git HTTP", nil)
|
ctx.NotFound("Smart Git HTTP", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
infoRefsCache []byte
|
||||||
|
infoRefsOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
func dummyInfoRefs(ctx *context.Context) {
|
||||||
|
infoRefsOnce.Do(func() {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-info-refs-cache")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to create temp dir for git-receive-pack cache: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(tmpDir); err != nil {
|
||||||
|
log.Error("RemoveAll: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := git.InitRepository(tmpDir, true); err != nil {
|
||||||
|
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
refs, err := git.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunInDirBytes(tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("populating infoRefsCache: \n%s", string(refs))
|
||||||
|
infoRefsCache = refs
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.Header().Set("Expires", "Fri, 01 Jan 1980 00:00:00 GMT")
|
||||||
|
ctx.Header().Set("Pragma", "no-cache")
|
||||||
|
ctx.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate")
|
||||||
|
ctx.Header().Set("Content-Type", "application/x-git-receive-pack-advertisement")
|
||||||
|
_, _ = ctx.Write(packetWrite("# service=git-receive-pack\n"))
|
||||||
|
_, _ = ctx.Write([]byte("0000"))
|
||||||
|
_, _ = ctx.Write(infoRefsCache)
|
||||||
|
}
|
||||||
|
|
||||||
type serviceConfig struct {
|
type serviceConfig struct {
|
||||||
UploadPack bool
|
UploadPack bool
|
||||||
ReceivePack bool
|
ReceivePack bool
|
||||||
|
|||||||
@@ -63,13 +63,12 @@ var (
|
|||||||
// If locked and user has permissions to write to the repository,
|
// If locked and user has permissions to write to the repository,
|
||||||
// then the comment is allowed, else it is blocked
|
// then the comment is allowed, else it is blocked
|
||||||
func MustAllowUserComment(ctx *context.Context) {
|
func MustAllowUserComment(ctx *context.Context) {
|
||||||
|
|
||||||
issue := GetActionIssue(ctx)
|
issue := GetActionIssue(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
|
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
|
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
|
||||||
ctx.Redirect(issue.HTMLURL())
|
ctx.Redirect(issue.HTMLURL())
|
||||||
return
|
return
|
||||||
@@ -348,8 +347,8 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveRepoMetas find all the meta information of a repository
|
// RetrieveRepoMetas find all the meta information of a repository
|
||||||
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.Label {
|
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository, isPull bool) []*models.Label {
|
||||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
if !ctx.Repo.CanWriteIssuesOrPulls(isPull) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +372,7 @@ func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.
|
|||||||
ctx.Data["Branches"] = brs
|
ctx.Data["Branches"] = brs
|
||||||
|
|
||||||
// Contains true if the user can create issue dependencies
|
// Contains true if the user can create issue dependencies
|
||||||
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User)
|
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, isPull)
|
||||||
|
|
||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
@@ -443,7 +442,7 @@ func NewIssue(ctx *context.Context) {
|
|||||||
setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
|
setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
|
||||||
renderAttachmentSettings(ctx)
|
renderAttachmentSettings(ctx)
|
||||||
|
|
||||||
RetrieveRepoMetas(ctx, ctx.Repo.Repository)
|
RetrieveRepoMetas(ctx, ctx.Repo.Repository, false)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -458,7 +457,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm, isPull b
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository)
|
labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository, isPull)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return nil, nil, 0
|
return nil, nil, 0
|
||||||
}
|
}
|
||||||
@@ -670,6 +669,14 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
ctx.Data["PageIsIssueList"] = true
|
ctx.Data["PageIsIssueList"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if issue.IsPull && !ctx.Repo.CanRead(models.UnitTypeIssues) {
|
||||||
|
ctx.Data["IssueType"] = "pulls"
|
||||||
|
} else if !issue.IsPull && !ctx.Repo.CanRead(models.UnitTypePullRequests) {
|
||||||
|
ctx.Data["IssueType"] = "issues"
|
||||||
|
} else {
|
||||||
|
ctx.Data["IssueType"] = "all"
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["RequireHighlightJS"] = true
|
ctx.Data["RequireHighlightJS"] = true
|
||||||
ctx.Data["RequireDropzone"] = true
|
ctx.Data["RequireDropzone"] = true
|
||||||
ctx.Data["RequireTribute"] = true
|
ctx.Data["RequireTribute"] = true
|
||||||
@@ -807,7 +814,7 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user can use the dependencies
|
// Check if the user can use the dependencies
|
||||||
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User)
|
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull)
|
||||||
|
|
||||||
// check if dependencies can be created across repositories
|
// check if dependencies can be created across repositories
|
||||||
ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
|
ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
|
||||||
@@ -998,7 +1005,6 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
|
ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
|
||||||
ctx.Data["IsIssueWriter"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
ctx.Data["IsIssueWriter"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
||||||
ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.User.IsAdmin)
|
ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.User.IsAdmin)
|
||||||
ctx.Data["IsRepoIssuesWriter"] = ctx.IsSigned && (ctx.Repo.CanWrite(models.UnitTypeIssues) || ctx.User.IsAdmin)
|
|
||||||
ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
|
ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
|
||||||
ctx.HTML(200, tplIssueView)
|
ctx.HTML(200, tplIssueView)
|
||||||
}
|
}
|
||||||
@@ -1259,9 +1265,10 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Error(403)
|
ctx.Error(403)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
|
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
|
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
|
||||||
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
|
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -14,14 +14,6 @@ import (
|
|||||||
|
|
||||||
// AddDependency adds new dependencies
|
// AddDependency adds new dependencies
|
||||||
func AddDependency(ctx *context.Context) {
|
func AddDependency(ctx *context.Context) {
|
||||||
// Check if the Repo is allowed to have dependencies
|
|
||||||
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
|
|
||||||
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
depID := ctx.QueryInt64("newDependency")
|
|
||||||
|
|
||||||
issueIndex := ctx.ParamsInt64("index")
|
issueIndex := ctx.ParamsInt64("index")
|
||||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -29,6 +21,14 @@ func AddDependency(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the Repo is allowed to have dependencies
|
||||||
|
if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
|
||||||
|
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
depID := ctx.QueryInt64("newDependency")
|
||||||
|
|
||||||
if err = issue.LoadRepo(); err != nil {
|
if err = issue.LoadRepo(); err != nil {
|
||||||
ctx.ServerError("LoadRepo", err)
|
ctx.ServerError("LoadRepo", err)
|
||||||
return
|
return
|
||||||
@@ -73,14 +73,6 @@ func AddDependency(ctx *context.Context) {
|
|||||||
|
|
||||||
// RemoveDependency removes the dependency
|
// RemoveDependency removes the dependency
|
||||||
func RemoveDependency(ctx *context.Context) {
|
func RemoveDependency(ctx *context.Context) {
|
||||||
// Check if the Repo is allowed to have dependencies
|
|
||||||
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
|
|
||||||
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
depID := ctx.QueryInt64("removeDependencyID")
|
|
||||||
|
|
||||||
issueIndex := ctx.ParamsInt64("index")
|
issueIndex := ctx.ParamsInt64("index")
|
||||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,14 +80,19 @@ func RemoveDependency(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the Repo is allowed to have dependencies
|
||||||
|
if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
|
||||||
|
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
depID := ctx.QueryInt64("removeDependencyID")
|
||||||
|
|
||||||
if err = issue.LoadRepo(); err != nil {
|
if err = issue.LoadRepo(); err != nil {
|
||||||
ctx.ServerError("LoadRepo", err)
|
ctx.ServerError("LoadRepo", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect
|
|
||||||
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
|
|
||||||
|
|
||||||
// Dependency Type
|
// Dependency Type
|
||||||
depTypeStr := ctx.Req.PostForm.Get("dependencyType")
|
depTypeStr := ctx.Req.PostForm.Get("dependencyType")
|
||||||
|
|
||||||
@@ -126,4 +123,7 @@ func RemoveDependency(ctx *context.Context) {
|
|||||||
ctx.ServerError("RemoveIssueDependency", err)
|
ctx.ServerError("RemoveIssueDependency", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redirect
|
||||||
|
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,7 +403,9 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
|
state := pull_service.MergeRequiredContextsCommitStatus(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
|
||||||
|
ctx.Data["RequiredStatusCheckState"] = state
|
||||||
|
ctx.Data["IsRequiredStatusCheckSuccess"] = state.IsSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
|
ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func SubmitReview(ctx *context.Context, form auth.SubmitReviewForm) {
|
|||||||
|
|
||||||
// can not approve/reject your own PR
|
// can not approve/reject your own PR
|
||||||
case models.ReviewTypeApprove, models.ReviewTypeReject:
|
case models.ReviewTypeApprove, models.ReviewTypeReject:
|
||||||
if issue.Poster.ID == ctx.User.ID {
|
if issue.IsPoster(ctx.User.ID) {
|
||||||
var translated string
|
var translated string
|
||||||
if reviewType == models.ReviewTypeApprove {
|
if reviewType == models.ReviewTypeApprove {
|
||||||
translated = ctx.Tr("repo.issues.review.self.approval")
|
translated = ctx.Tr("repo.issues.review.self.approval")
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ func AddTeamPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.Query("team")))
|
name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.Query("team")))
|
||||||
if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
|
if len(name) == 0 {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
||||||
m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
|
m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
|
||||||
m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
|
m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
|
||||||
m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
|
m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Group("/auths", func() {
|
m.Group("/auths", func() {
|
||||||
@@ -503,19 +503,13 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
reqRepoReleaseWriter := context.RequireRepoWriter(models.UnitTypeReleases)
|
reqRepoReleaseWriter := context.RequireRepoWriter(models.UnitTypeReleases)
|
||||||
reqRepoReleaseReader := context.RequireRepoReader(models.UnitTypeReleases)
|
reqRepoReleaseReader := context.RequireRepoReader(models.UnitTypeReleases)
|
||||||
reqRepoWikiWriter := context.RequireRepoWriter(models.UnitTypeWiki)
|
reqRepoWikiWriter := context.RequireRepoWriter(models.UnitTypeWiki)
|
||||||
|
reqRepoIssueWriter := context.RequireRepoWriter(models.UnitTypeIssues)
|
||||||
reqRepoIssueReader := context.RequireRepoReader(models.UnitTypeIssues)
|
reqRepoIssueReader := context.RequireRepoReader(models.UnitTypeIssues)
|
||||||
reqRepoPullsWriter := context.RequireRepoWriter(models.UnitTypePullRequests)
|
reqRepoPullsWriter := context.RequireRepoWriter(models.UnitTypePullRequests)
|
||||||
reqRepoPullsReader := context.RequireRepoReader(models.UnitTypePullRequests)
|
reqRepoPullsReader := context.RequireRepoReader(models.UnitTypePullRequests)
|
||||||
reqRepoIssuesOrPullsWriter := context.RequireRepoWriterOr(models.UnitTypeIssues, models.UnitTypePullRequests)
|
reqRepoIssuesOrPullsWriter := context.RequireRepoWriterOr(models.UnitTypeIssues, models.UnitTypePullRequests)
|
||||||
reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(models.UnitTypeIssues, models.UnitTypePullRequests)
|
reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(models.UnitTypeIssues, models.UnitTypePullRequests)
|
||||||
|
|
||||||
reqRepoIssueWriter := func(ctx *context.Context) {
|
|
||||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
|
||||||
ctx.Error(403)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ***** START: Organization *****
|
// ***** START: Organization *****
|
||||||
m.Group("/org", func() {
|
m.Group("/org", func() {
|
||||||
m.Group("", func() {
|
m.Group("", func() {
|
||||||
@@ -563,6 +557,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
|
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
|
||||||
m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
|
m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
|
||||||
m.Post("/telegram/new", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
|
m.Post("/telegram/new", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
|
||||||
|
m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
|
||||||
m.Get("/:id", repo.WebHooksEdit)
|
m.Get("/:id", repo.WebHooksEdit)
|
||||||
m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||||
m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost)
|
m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost)
|
||||||
@@ -570,6 +565,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
||||||
m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
|
m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
|
||||||
m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
|
m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
|
||||||
|
m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||||
|
|||||||
@@ -1284,7 +1284,7 @@ func ForgotPasswdPost(ctx *context.Context) {
|
|||||||
ctx.HTML(200, tplForgotPassword)
|
ctx.HTML(200, tplForgotPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonResetPassword(ctx *context.Context) *models.User {
|
func commonResetPassword(ctx *context.Context) (*models.User, *models.TwoFactor) {
|
||||||
code := ctx.Query("code")
|
code := ctx.Query("code")
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Tr("auth.reset_password")
|
ctx.Data["Title"] = ctx.Tr("auth.reset_password")
|
||||||
@@ -1296,14 +1296,25 @@ func commonResetPassword(ctx *context.Context) *models.User {
|
|||||||
|
|
||||||
if len(code) == 0 {
|
if len(code) == 0 {
|
||||||
ctx.Flash.Error(ctx.Tr("auth.invalid_code"))
|
ctx.Flash.Error(ctx.Tr("auth.invalid_code"))
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail early, don't frustrate the user
|
// Fail early, don't frustrate the user
|
||||||
u := models.VerifyUserActiveCode(code)
|
u := models.VerifyUserActiveCode(code)
|
||||||
if u == nil {
|
if u == nil {
|
||||||
ctx.Flash.Error(ctx.Tr("auth.invalid_code"))
|
ctx.Flash.Error(ctx.Tr("auth.invalid_code"))
|
||||||
return nil
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
twofa, err := models.GetTwoFactorByUID(u.ID)
|
||||||
|
if err != nil {
|
||||||
|
if !models.IsErrTwoFactorNotEnrolled(err) {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "CommonResetPassword", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.Data["has_two_factor"] = true
|
||||||
|
ctx.Data["scratch_code"] = ctx.QueryBool("scratch_code")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the user that they are affecting the account that they intended to
|
// Show the user that they are affecting the account that they intended to
|
||||||
@@ -1311,10 +1322,10 @@ func commonResetPassword(ctx *context.Context) *models.User {
|
|||||||
|
|
||||||
if nil != ctx.User && u.ID != ctx.User.ID {
|
if nil != ctx.User && u.ID != ctx.User.ID {
|
||||||
ctx.Flash.Error(ctx.Tr("auth.reset_password_wrong_user", ctx.User.Email, u.Email))
|
ctx.Flash.Error(ctx.Tr("auth.reset_password_wrong_user", ctx.User.Email, u.Email))
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return u
|
return u, twofa
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetPasswd render the account recovery page
|
// ResetPasswd render the account recovery page
|
||||||
@@ -1322,13 +1333,19 @@ func ResetPasswd(ctx *context.Context) {
|
|||||||
ctx.Data["IsResetForm"] = true
|
ctx.Data["IsResetForm"] = true
|
||||||
|
|
||||||
commonResetPassword(ctx)
|
commonResetPassword(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.HTML(200, tplResetPassword)
|
ctx.HTML(200, tplResetPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetPasswdPost response from account recovery request
|
// ResetPasswdPost response from account recovery request
|
||||||
func ResetPasswdPost(ctx *context.Context) {
|
func ResetPasswdPost(ctx *context.Context) {
|
||||||
u := commonResetPassword(ctx)
|
u, twofa := commonResetPassword(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if u == nil {
|
if u == nil {
|
||||||
// Flash error has been set
|
// Flash error has been set
|
||||||
@@ -1350,6 +1367,39 @@ func ResetPasswdPost(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle two-factor
|
||||||
|
regenerateScratchToken := false
|
||||||
|
if twofa != nil {
|
||||||
|
if ctx.QueryBool("scratch_code") {
|
||||||
|
if !twofa.VerifyScratchToken(ctx.Query("token")) {
|
||||||
|
ctx.Data["IsResetForm"] = true
|
||||||
|
ctx.Data["Err_Token"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("auth.twofa_scratch_token_incorrect"), tplResetPassword, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
regenerateScratchToken = true
|
||||||
|
} else {
|
||||||
|
passcode := ctx.Query("passcode")
|
||||||
|
ok, err := twofa.ValidateTOTP(passcode)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !ok || twofa.LastUsedPasscode == passcode {
|
||||||
|
ctx.Data["IsResetForm"] = true
|
||||||
|
ctx.Data["Err_Passcode"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("auth.twofa_passcode_incorrect"), tplResetPassword, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
twofa.LastUsedPasscode = passcode
|
||||||
|
if err = models.UpdateTwoFactor(twofa); err != nil {
|
||||||
|
ctx.ServerError("ResetPasswdPost: UpdateTwoFactor", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if u.Rands, err = models.GetUserSalt(); err != nil {
|
if u.Rands, err = models.GetUserSalt(); err != nil {
|
||||||
ctx.ServerError("UpdateUser", err)
|
ctx.ServerError("UpdateUser", err)
|
||||||
@@ -1359,7 +1409,6 @@ func ResetPasswdPost(ctx *context.Context) {
|
|||||||
ctx.ServerError("UpdateUser", err)
|
ctx.ServerError("UpdateUser", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
u.HashPassword(passwd)
|
u.HashPassword(passwd)
|
||||||
u.MustChangePassword = false
|
u.MustChangePassword = false
|
||||||
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "rands", "salt"); err != nil {
|
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "rands", "salt"); err != nil {
|
||||||
@@ -1368,9 +1417,27 @@ func ResetPasswdPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("User password reset: %s", u.Name)
|
log.Trace("User password reset: %s", u.Name)
|
||||||
|
|
||||||
ctx.Data["IsResetFailed"] = true
|
ctx.Data["IsResetFailed"] = true
|
||||||
remember := len(ctx.Query("remember")) != 0
|
remember := len(ctx.Query("remember")) != 0
|
||||||
|
|
||||||
|
if regenerateScratchToken {
|
||||||
|
// Invalidate the scratch token.
|
||||||
|
_, err = twofa.GenerateScratchToken()
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("UserSignIn", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = models.UpdateTwoFactor(twofa); err != nil {
|
||||||
|
ctx.ServerError("UserSignIn", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSignInFull(ctx, u, remember, false)
|
||||||
|
ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
|
||||||
|
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
handleSignInFull(ctx, u, remember, true)
|
handleSignInFull(ctx, u, remember, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ func (diffFile *DiffFile) GetHighlightClass() string {
|
|||||||
|
|
||||||
// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file
|
// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file
|
||||||
func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {
|
func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {
|
||||||
if diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {
|
if len(diffFile.Sections) == 0 || diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
leftCommit, err := gitRepo.GetCommit(leftCommitID)
|
leftCommit, err := gitRepo.GetCommit(leftCommitID)
|
||||||
|
|||||||
@@ -194,10 +194,16 @@ func TestPullRequests(ctx context.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetPullRequestByID[%s]: %v", prID, err)
|
log.Error("GetPullRequestByID[%s]: %v", prID, err)
|
||||||
continue
|
continue
|
||||||
|
} else if pr.Status != models.PullRequestStatusChecking {
|
||||||
|
continue
|
||||||
} else if manuallyMerged(pr) {
|
} else if manuallyMerged(pr) {
|
||||||
continue
|
continue
|
||||||
} else if err = TestPatch(pr); err != nil {
|
} else if err = TestPatch(pr); err != nil {
|
||||||
log.Error("testPatch[%d]: %v", pr.ID, err)
|
log.Error("testPatch[%d]: %v", pr.ID, err)
|
||||||
|
pr.Status = models.PullRequestStatusError
|
||||||
|
if err := pr.UpdateCols("status"); err != nil {
|
||||||
|
log.Error("Unable to update status of pr %d: %v", pr.ID, err)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
checkAndUpdateStatus(pr)
|
checkAndUpdateStatus(pr)
|
||||||
|
|||||||
@@ -8,15 +8,47 @@ package pull
|
|||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MergeRequiredContextsCommitStatus returns a commit status state for given required contexts
|
||||||
|
func MergeRequiredContextsCommitStatus(commitStatuses []*models.CommitStatus, requiredContexts []string) structs.CommitStatusState {
|
||||||
|
if len(requiredContexts) == 0 {
|
||||||
|
status := models.CalcCommitStatus(commitStatuses)
|
||||||
|
if status != nil {
|
||||||
|
return status.State
|
||||||
|
}
|
||||||
|
return structs.CommitStatusSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnedStatus = structs.CommitStatusPending
|
||||||
|
for _, ctx := range requiredContexts {
|
||||||
|
var targetStatus structs.CommitStatusState
|
||||||
|
for _, commitStatus := range commitStatuses {
|
||||||
|
if commitStatus.Context == ctx {
|
||||||
|
targetStatus = commitStatus.State
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetStatus == "" {
|
||||||
|
targetStatus = structs.CommitStatusPending
|
||||||
|
}
|
||||||
|
if targetStatus.NoBetterThan(returnedStatus) {
|
||||||
|
returnedStatus = targetStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnedStatus
|
||||||
|
}
|
||||||
|
|
||||||
// IsCommitStatusContextSuccess returns true if all required status check contexts succeed.
|
// IsCommitStatusContextSuccess returns true if all required status check contexts succeed.
|
||||||
func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, requiredContexts []string) bool {
|
func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, requiredContexts []string) bool {
|
||||||
// If no specific context is required, require that last commit status is a success
|
// If no specific context is required, require that last commit status is a success
|
||||||
if len(requiredContexts) == 0 {
|
if len(requiredContexts) == 0 {
|
||||||
status := models.CalcCommitStatus(commitStatuses)
|
status := models.CalcCommitStatus(commitStatuses)
|
||||||
if status == nil || status.State != models.CommitStatusSuccess {
|
if status == nil || status.State != structs.CommitStatusSuccess {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -26,7 +58,7 @@ func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, require
|
|||||||
var found bool
|
var found bool
|
||||||
for _, commitStatus := range commitStatuses {
|
for _, commitStatus := range commitStatuses {
|
||||||
if commitStatus.Context == ctx {
|
if commitStatus.Context == ctx {
|
||||||
if commitStatus.State != models.CommitStatusSuccess {
|
if commitStatus.State != structs.CommitStatusSuccess {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,30 +82,39 @@ func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state, err := GetPullRequestCommitStatusState(pr)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return state.IsSuccess(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequestCommitStatusState returns pull request merged commit status state
|
||||||
|
func GetPullRequestCommitStatusState(pr *models.PullRequest) (structs.CommitStatusState, error) {
|
||||||
// check if all required status checks are successful
|
// check if all required status checks are successful
|
||||||
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
|
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "OpenRepository")
|
return "", errors.Wrap(err, "OpenRepository")
|
||||||
}
|
}
|
||||||
defer headGitRepo.Close()
|
defer headGitRepo.Close()
|
||||||
|
|
||||||
if !headGitRepo.IsBranchExist(pr.HeadBranch) {
|
if !headGitRepo.IsBranchExist(pr.HeadBranch) {
|
||||||
return false, errors.New("Head branch does not exist, can not merge")
|
return "", errors.New("Head branch does not exist, can not merge")
|
||||||
}
|
}
|
||||||
|
|
||||||
sha, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
|
sha, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "GetBranchCommitID")
|
return "", errors.Wrap(err, "GetBranchCommitID")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pr.LoadBaseRepo(); err != nil {
|
if err := pr.LoadBaseRepo(); err != nil {
|
||||||
return false, errors.Wrap(err, "LoadBaseRepo")
|
return "", errors.Wrap(err, "LoadBaseRepo")
|
||||||
}
|
}
|
||||||
|
|
||||||
commitStatuses, err := models.GetLatestCommitStatus(pr.BaseRepo, sha, 0)
|
commitStatuses, err := models.GetLatestCommitStatus(pr.BaseRepo, sha, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "GetLatestCommitStatus")
|
return "", errors.Wrap(err, "GetLatestCommitStatus")
|
||||||
}
|
}
|
||||||
|
|
||||||
return IsCommitStatusContextSuccess(commitStatuses, pr.ProtectedBranch.StatusCheckContexts), nil
|
return MergeRequiredContextsCommitStatus(commitStatuses, pr.ProtectedBranch.StatusCheckContexts), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,8 +374,10 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
close := (ref.RefAction == references.XRefActionCloses)
|
close := (ref.RefAction == references.XRefActionCloses)
|
||||||
if err = issue_service.ChangeStatus(ref.Issue, doer, close); err != nil {
|
if close != ref.Issue.IsClosed {
|
||||||
return err
|
if err = issue_service.ChangeStatus(ref.Issue, doer, close); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label for="allow_deactivate_all"><strong>{{.i18n.Tr "admin.auths.allow_deactivate_all"}}</strong></label>
|
||||||
|
<input id="allow_deactivate_all" name="allow_deactivate_all" type="checkbox" {{if $cfg.AllowDeactivateAll}}checked{{end}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- SMTP -->
|
<!-- SMTP -->
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
{{ template "repo/issue/view_content/pull". }}
|
{{ template "repo/issue/view_content/pull". }}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .IsSigned}}
|
{{if .IsSigned}}
|
||||||
{{ if and (or .IsRepoAdmin .IsRepoIssuesWriter (or (not .Issue.IsLocked))) (not .Repository.IsArchived) }}
|
{{ if and (or .IsRepoAdmin .IsIssueWriter (or (not .Issue.IsLocked))) (not .Repository.IsArchived) }}
|
||||||
<div class="comment form">
|
<div class="comment form">
|
||||||
<a class="avatar" href="{{.SignedUser.HomeLink}}">
|
<a class="avatar" href="{{.SignedUser.HomeLink}}">
|
||||||
<img src="{{.SignedUser.RelAvatarLink}}">
|
<img src="{{.SignedUser.RelAvatarLink}}">
|
||||||
|
|||||||
@@ -277,10 +277,20 @@
|
|||||||
<span class="text grey">
|
<span class="text grey">
|
||||||
{{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink (.Poster.GetDisplayName|Escape) $createdStr | Safe}}
|
{{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink (.Poster.GetDisplayName|Escape) $createdStr | Safe}}
|
||||||
</span>
|
</span>
|
||||||
<div class="detail">
|
{{if .DependentIssue}}
|
||||||
<span class="octicon octicon-plus"></span>
|
<div class="detail">
|
||||||
<span class="text grey"><a href="{{$.RepoLink}}/issues/{{.DependentIssue.Index}}">#{{.DependentIssue.Index}} {{.DependentIssue.Title}}</a></span>
|
<span class="octicon octicon-plus"></span>
|
||||||
</div>
|
<span class="text grey">
|
||||||
|
<a href="{{.DependentIssue.HTMLURL}}">
|
||||||
|
{{if eq .DependentIssue.RepoID .Issue.RepoID}}
|
||||||
|
#{{.DependentIssue.Index}} {{.DependentIssue.Title}}
|
||||||
|
{{else}}
|
||||||
|
{{.DependentIssue.Repo.FullName}}#{{.DependentIssue.Index}} - {{.DependentIssue.Title}}
|
||||||
|
{{end}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Type 20}}
|
{{else if eq .Type 20}}
|
||||||
<div class="event" id="{{.HashTag}}">
|
<div class="event" id="{{.HashTag}}">
|
||||||
@@ -291,10 +301,20 @@
|
|||||||
<span class="text grey">
|
<span class="text grey">
|
||||||
{{$.i18n.Tr "repo.issues.dependency.removed_dependency" .Poster.HomeLink (.Poster.GetDisplayName|Escape) $createdStr | Safe}}
|
{{$.i18n.Tr "repo.issues.dependency.removed_dependency" .Poster.HomeLink (.Poster.GetDisplayName|Escape) $createdStr | Safe}}
|
||||||
</span>
|
</span>
|
||||||
<div class="detail">
|
{{if .DependentIssue}}
|
||||||
<span class="text grey octicon octicon-trashcan"></span>
|
<div class="detail">
|
||||||
<span class="text grey"><a href="{{$.RepoLink}}/issues/{{.DependentIssue.Index}}">#{{.DependentIssue.Index}} {{.DependentIssue.Title}}</a></span>
|
<span class="text grey octicon octicon-trashcan"></span>
|
||||||
</div>
|
<span class="text grey">
|
||||||
|
<a href="{{.DependentIssue.HTMLURL}}">
|
||||||
|
{{if eq .DependentIssue.RepoID .Issue.RepoID}}
|
||||||
|
#{{.DependentIssue.Index}} {{.DependentIssue.Title}}
|
||||||
|
{{else}}
|
||||||
|
{{.DependentIssue.Repo.FullName}}#{{.DependentIssue.Index}} - {{.DependentIssue.Title}}
|
||||||
|
{{end}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Type 22}}
|
{{else if eq .Type 22}}
|
||||||
<div class="event" id="{{.HashTag}}">
|
<div class="event" id="{{.HashTag}}">
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
{{else if .IsPullRequestBroken}}red
|
{{else if .IsPullRequestBroken}}red
|
||||||
{{else if .IsBlockedByApprovals}}red
|
{{else if .IsBlockedByApprovals}}red
|
||||||
{{else if .IsBlockedByRejection}}red
|
{{else if .IsBlockedByRejection}}red
|
||||||
{{else if and .EnableStatusCheck (not .IsRequiredStatusCheckSuccess)}}red
|
{{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsFailure .RequiredStatusCheckState.IsError)}}red
|
||||||
|
{{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsPending .RequiredStatusCheckState.IsWarning)}}yellow
|
||||||
{{else if .Issue.PullRequest.IsChecking}}yellow
|
{{else if .Issue.PullRequest.IsChecking}}yellow
|
||||||
{{else if .Issue.PullRequest.CanAutoMerge}}green
|
{{else if .Issue.PullRequest.CanAutoMerge}}green
|
||||||
{{else}}red{{end}}"><span class="mega-octicon octicon-git-merge"></span></a>
|
{{else}}red{{end}}"><span class="mega-octicon octicon-git-merge"></span></a>
|
||||||
@@ -117,7 +118,7 @@
|
|||||||
{{$.i18n.Tr "repo.pulls.required_status_check_failed"}}
|
{{$.i18n.Tr "repo.pulls.required_status_check_failed"}}
|
||||||
</div>
|
</div>
|
||||||
{{else if .Issue.PullRequest.CanAutoMerge}}
|
{{else if .Issue.PullRequest.CanAutoMerge}}
|
||||||
{{if and .EnableStatusCheck (not .IsRequiredStatusCheckSuccess)}}
|
{{if and .EnableStatusCheck (or .RequiredStatusCheckState.IsError .RequiredStatusCheckState.IsFailure)}}
|
||||||
<div class="item text red">
|
<div class="item text red">
|
||||||
<span class="octicon octicon-x"></span>
|
<span class="octicon octicon-x"></span>
|
||||||
{{$.i18n.Tr "repo.pulls.required_status_check_failed"}}
|
{{$.i18n.Tr "repo.pulls.required_status_check_failed"}}
|
||||||
|
|||||||
@@ -428,6 +428,7 @@
|
|||||||
<input type="hidden" id="repolink" value="{{$.RepoRelPath}}">
|
<input type="hidden" id="repolink" value="{{$.RepoRelPath}}">
|
||||||
<input type="hidden" id="repoId" value="{{.Repository.ID}}">
|
<input type="hidden" id="repoId" value="{{.Repository.ID}}">
|
||||||
<input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}">
|
<input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}">
|
||||||
|
<input type="hidden" id="type" value="{{.IssueType}}">
|
||||||
<!-- I know, there is probably a better way to do this -->
|
<!-- I know, there is probably a better way to do this -->
|
||||||
<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>
|
<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>
|
||||||
|
|
||||||
|
|||||||
@@ -1173,6 +1173,12 @@
|
|||||||
"description": "repository to prioritize in the results",
|
"description": "repository to prioritize in the results",
|
||||||
"name": "priority_repo_id",
|
"name": "priority_repo_id",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "filter by type (issues / pulls) if set",
|
||||||
|
"name": "type",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -2903,6 +2909,12 @@
|
|||||||
"description": "search string",
|
"description": "search string",
|
||||||
"name": "q",
|
"name": "q",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "filter by type (issues / pulls) if set",
|
||||||
|
"name": "type",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@@ -10179,6 +10191,10 @@
|
|||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"x-go-name": "Deadline"
|
"x-go-name": "Deadline"
|
||||||
},
|
},
|
||||||
|
"html_url": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "HTMLURL"
|
||||||
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
{{if .IsResetForm}}
|
{{if .IsResetForm}}
|
||||||
<div class="required inline field {{if .Err_Password}}error{{end}}">
|
<div class="required inline field {{if .Err_Password}}error{{end}}">
|
||||||
<label for="password">{{.i18n.Tr "password"}}</label>
|
<label for="password">{{.i18n.Tr "settings.new_password"}}</label>
|
||||||
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" autofocus required>
|
<input id="password" name="password" type="password" value="{{.password}}" autocomplete="off" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{if not .user_signed_in}}
|
{{if not .user_signed_in}}
|
||||||
@@ -30,10 +30,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if .has_two_factor}}
|
||||||
|
<h4 class="ui dividing header">
|
||||||
|
{{.i18n.Tr "twofa"}}
|
||||||
|
</h4>
|
||||||
|
<div class="ui warning visible message">{{.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}</div>
|
||||||
|
{{if .scratch_code}}
|
||||||
|
<div class="required inline field {{if .Err_Token}}error{{end}}">
|
||||||
|
<label for="token">{{.i18n.Tr "auth.scratch_code"}}</label>
|
||||||
|
<input id="token" name="token" type="text" autocomplete="off" autofocus required>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="scratch_code" value="true">
|
||||||
|
{{else}}
|
||||||
|
<div class="required inline field {{if .Err_Passcode}}error{{end}}">
|
||||||
|
<label for="passcode">{{.i18n.Tr "passcode"}}</label>
|
||||||
|
<input id="passcode" name="passcode" type="number" autocomplete="off" autofocus required>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label></label>
|
<label></label>
|
||||||
<button class="ui blue button">{{.i18n.Tr "auth.reset_password_helper"}}</button>
|
<button class="ui blue button">{{.i18n.Tr "auth.reset_password_helper"}}</button>
|
||||||
|
{{if and .has_two_factor (not .scratch_code)}}
|
||||||
|
<a href="{{.Link}}?code={{.Code}}&scratch_code=true">{{.i18n.Tr "auth.use_scratch_code" | Str2html}}</a>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="center">{{.i18n.Tr "auth.invalid_code"}}</p>
|
<p class="center">{{.i18n.Tr "auth.invalid_code"}}</p>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
<div class="milestone list">
|
<div class="milestone list">
|
||||||
{{range .Milestones}}
|
{{range .Milestones}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<div class="ui label">{{if not $.RepoIDs}}{{.Repo.FullName}}{{end}}</div>
|
<div class="ui label">{{.Repo.FullName}}</div>
|
||||||
<i class="octicon octicon-milestone"></i> <a href="{{.Repo.Link }}/milestone/{{.ID}}">{{.Name}}</a>
|
<i class="octicon octicon-milestone"></i> <a href="{{.Repo.Link }}/milestone/{{.ID}}">{{.Name}}</a>
|
||||||
<div class="ui right green progress" data-percent="{{.Completeness}}">
|
<div class="ui right green progress" data-percent="{{.Completeness}}">
|
||||||
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
|
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ if (typeof (Dropzone) !== 'undefined') {
|
|||||||
Dropzone.autoDiscover = false;
|
Dropzone.autoDiscover = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Silence fomantic's error logging when tabs are used without a target content element
|
||||||
|
$.fn.tab.settings.silent = true;
|
||||||
|
|
||||||
function initCommentPreviewTab($form) {
|
function initCommentPreviewTab($form) {
|
||||||
const $tabMenu = $form.find('.tabular.menu');
|
const $tabMenu = $form.find('.tabular.menu');
|
||||||
$tabMenu.find('.item').tab();
|
$tabMenu.find('.item').tab();
|
||||||
@@ -320,12 +323,14 @@ function initSimpleMDEImagePaste(simplemde, files) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let autoSimpleMDE;
|
||||||
|
|
||||||
function initCommentForm() {
|
function initCommentForm() {
|
||||||
if ($('.comment.form').length === 0) {
|
if ($('.comment.form').length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)'));
|
autoSimpleMDE = setCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)'));
|
||||||
initBranchSelector();
|
initBranchSelector();
|
||||||
initCommentPreviewTab($('.comment.form'));
|
initCommentPreviewTab($('.comment.form'));
|
||||||
initImagePaste($('.comment.form textarea'));
|
initImagePaste($('.comment.form textarea'));
|
||||||
@@ -823,25 +828,27 @@ function initRepository() {
|
|||||||
$('.quote-reply').click(function (event) {
|
$('.quote-reply').click(function (event) {
|
||||||
$(this).closest('.dropdown').find('.menu').toggle('visible');
|
$(this).closest('.dropdown').find('.menu').toggle('visible');
|
||||||
const target = $(this).data('target');
|
const target = $(this).data('target');
|
||||||
|
const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> ');
|
||||||
|
const content = `> ${quote}\n\n`;
|
||||||
|
|
||||||
let $content;
|
let $content;
|
||||||
if ($(this).hasClass('quote-reply-diff')) {
|
if ($(this).hasClass('quote-reply-diff')) {
|
||||||
const $parent = $(this).closest('.comment-code-cloud');
|
const $parent = $(this).closest('.comment-code-cloud');
|
||||||
$parent.find('button.comment-form-reply').click();
|
$parent.find('button.comment-form-reply').click();
|
||||||
$content = $parent.find('[name="content"]');
|
$content = $parent.find('[name="content"]');
|
||||||
} else {
|
if ($content.val() !== '') {
|
||||||
$content = $('#content');
|
$content.val(`${$content.val()}\n\n${content}`);
|
||||||
|
} else {
|
||||||
|
$content.val(`${content}`);
|
||||||
|
}
|
||||||
|
$content.focus();
|
||||||
|
} else if (autoSimpleMDE !== null) {
|
||||||
|
if (autoSimpleMDE.value() !== '') {
|
||||||
|
autoSimpleMDE.value(`${autoSimpleMDE.value()}\n\n${content}`);
|
||||||
|
} else {
|
||||||
|
autoSimpleMDE.value(`${content}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> ');
|
|
||||||
const content = `> ${quote}\n\n`;
|
|
||||||
|
|
||||||
if ($content.val() !== '') {
|
|
||||||
$content.val(`${$content.val()}\n\n${content}`);
|
|
||||||
} else {
|
|
||||||
$content.val(`${content}`);
|
|
||||||
}
|
|
||||||
$content.focus();
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3448,9 +3455,10 @@ function initIssueList() {
|
|||||||
const repolink = $('#repolink').val();
|
const repolink = $('#repolink').val();
|
||||||
const repoId = $('#repoId').val();
|
const repoId = $('#repoId').val();
|
||||||
const crossRepoSearch = $('#crossRepoSearch').val();
|
const crossRepoSearch = $('#crossRepoSearch').val();
|
||||||
let issueSearchUrl = `${suburl}/api/v1/repos/${repolink}/issues?q={query}`;
|
const tp = $('#type').val();
|
||||||
|
let issueSearchUrl = `${suburl}/api/v1/repos/${repolink}/issues?q={query}&type=${tp}`;
|
||||||
if (crossRepoSearch === 'true') {
|
if (crossRepoSearch === 'true') {
|
||||||
issueSearchUrl = `${suburl}/api/v1/repos/issues/search?q={query}&priority_repo_id=${repoId}`;
|
issueSearchUrl = `${suburl}/api/v1/repos/issues/search?q={query}&priority_repo_id=${repoId}&type=${tp}`;
|
||||||
}
|
}
|
||||||
$('#new-dependency-drop-list')
|
$('#new-dependency-drop-list')
|
||||||
.dropdown({
|
.dropdown({
|
||||||
|
|||||||
@@ -774,6 +774,7 @@ footer {
|
|||||||
.container {
|
.container {
|
||||||
width: 100vw !important;
|
width: 100vw !important;
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
|
max-width: calc(100vw - 1rem) !important;
|
||||||
|
|
||||||
.fa {
|
.fa {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ module.exports = {
|
|||||||
[
|
[
|
||||||
'@babel/preset-env',
|
'@babel/preset-env',
|
||||||
{
|
{
|
||||||
useBuiltIns: 'entry',
|
useBuiltIns: 'usage',
|
||||||
corejs: 3,
|
corejs: 3,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user