mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-21 17:41:16 +02:00
Compare commits
76 Commits
v1.11.0-rc
...
v1.11.0
Author | SHA1 | Date | |
---|---|---|---|
|
9169b39458 | ||
|
80eb50655a | ||
|
b16c555541 | ||
|
b5b44364e3 | ||
|
6af58022c8 | ||
|
e48b460a0a | ||
|
2cd2614eaa | ||
|
0129e76ef5 | ||
|
6896dad675 | ||
|
1ed4323005 | ||
|
049af0d3d0 | ||
|
f5727d83dd | ||
|
912ce27421 | ||
|
b3549bb5ec | ||
|
491cbeca67 | ||
|
895d92ffe5 | ||
|
4b11f967bd | ||
|
1e73dd2446 | ||
|
315026c2c5 | ||
|
16dfd9ffbe | ||
|
16f7b43903 | ||
|
043febdbc9 | ||
|
60f91d56f0 | ||
|
16fc15ae6a | ||
|
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,57 @@
|
||||
# The full repository name
|
||||
repo: go-gitea/gitea
|
||||
|
||||
# Service type (gitea or github)
|
||||
service: github
|
||||
|
||||
# Base URL for Gitea instance if using gitea service type (optional)
|
||||
# Default: https://gitea.com
|
||||
base-url:
|
||||
|
||||
# Changelog groups and which labeled PRs to add to each group
|
||||
groups:
|
||||
-
|
||||
-
|
||||
name: BREAKING
|
||||
labels:
|
||||
- kind/breaking
|
||||
-
|
||||
-
|
||||
name: FEATURE
|
||||
labels:
|
||||
- kind/feature
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- kind/security
|
||||
-
|
||||
name: BUGFIXES
|
||||
labels:
|
||||
- kind/bug
|
||||
-
|
||||
-
|
||||
name: ENHANCEMENT
|
||||
labels:
|
||||
- kind/enhancement
|
||||
- kind/refactor
|
||||
- kind/ui
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- kind/security
|
||||
-
|
||||
name: TESTING
|
||||
labels:
|
||||
- kind/testing
|
||||
-
|
||||
-
|
||||
name: TRANSLATION
|
||||
labels:
|
||||
- kind/translation
|
||||
-
|
||||
-
|
||||
name: BUILD
|
||||
labels:
|
||||
- kind/build
|
||||
- kind/lint
|
||||
-
|
||||
-
|
||||
name: DOCS
|
||||
labels:
|
||||
- kind/docs
|
||||
-
|
||||
-
|
||||
name: MISC
|
||||
default: true
|
||||
default: true
|
||||
|
||||
# regex indicating which labels to skip for the changelog
|
||||
skip-labels: skip-changelog|backport\/.+
|
||||
|
408
.drone.yml
408
.drone.yml
@@ -1,6 +1,61 @@
|
||||
---
|
||||
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:
|
||||
os: linux
|
||||
@@ -25,15 +80,9 @@ services:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: testgitea
|
||||
|
||||
- name: pgsql
|
||||
pull: default
|
||||
image: postgres:9.5
|
||||
environment:
|
||||
POSTGRES_DB: test
|
||||
|
||||
- name: mssql
|
||||
pull: default
|
||||
image: microsoft/mssql-server-linux:latest
|
||||
image: mcr.microsoft.com/mssql/server:latest
|
||||
environment:
|
||||
ACCEPT_EULA: Y
|
||||
MSSQL_PID: Standard
|
||||
@@ -54,52 +103,23 @@ steps:
|
||||
exclude:
|
||||
- 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
|
||||
pull: always
|
||||
image: golang:1.13
|
||||
commands:
|
||||
- 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
|
||||
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: tag-pre-condition
|
||||
pull: always
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
|
||||
|
||||
- name: unit-test
|
||||
pull: always
|
||||
image: golang:1.13
|
||||
@@ -108,70 +128,8 @@ steps:
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
depends_on:
|
||||
- build
|
||||
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
|
||||
GITHUB_READ_TOKEN:
|
||||
from_secret: github_read_token
|
||||
|
||||
- name: test-mysql
|
||||
pull: always
|
||||
@@ -187,30 +145,6 @@ steps:
|
||||
TEST_LDAP: 1
|
||||
depends_on:
|
||||
- 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
|
||||
pull: always
|
||||
@@ -227,21 +161,6 @@ steps:
|
||||
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
|
||||
|
||||
- name: test-mssql
|
||||
pull: always
|
||||
image: golang:1.13
|
||||
@@ -293,13 +212,89 @@ steps:
|
||||
- push
|
||||
- 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
|
||||
name: translations
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
arch: arm64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
@@ -378,7 +373,8 @@ trigger:
|
||||
- push
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- testing-amd64
|
||||
- testing-arm64
|
||||
- translations
|
||||
|
||||
steps:
|
||||
@@ -476,7 +472,8 @@ trigger:
|
||||
- tag
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- testing-arm64
|
||||
- testing-amd64
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
@@ -545,17 +542,14 @@ name: docs
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- name: build-docs
|
||||
pull: always
|
||||
image: webhippie/hugo:latest
|
||||
image: plugins/hugo:latest
|
||||
commands:
|
||||
- apk add --no-cache make bash curl
|
||||
- cd docs
|
||||
- make trans-copy
|
||||
- make clean
|
||||
@@ -563,7 +557,7 @@ steps:
|
||||
|
||||
- name: publish-docs
|
||||
pull: always
|
||||
image: lucap/drone-netlify:latest
|
||||
image: techknowlogick/drone-netlify:latest
|
||||
settings:
|
||||
path: docs/public/
|
||||
site_id: d2260bae-7861-4c02-8646-8f6440b12672
|
||||
@@ -578,7 +572,7 @@ steps:
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-linux-amd64
|
||||
name: docker-linux-amd64-release
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
@@ -589,13 +583,13 @@ workspace:
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- testing-amd64
|
||||
- testing-arm64
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
- "refs/pull/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
@@ -603,23 +597,6 @@ steps:
|
||||
image: docker:git
|
||||
commands:
|
||||
- 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
|
||||
pull: always
|
||||
@@ -641,7 +618,7 @@ steps:
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-linux-arm64
|
||||
name: docker-linux-arm64-dry-run
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
@@ -652,25 +629,13 @@ workspace:
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- compliance
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
- "refs/pull/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: dryrun
|
||||
pull: always
|
||||
image: plugins/docker:linux-arm64
|
||||
@@ -684,6 +649,33 @@ steps:
|
||||
event:
|
||||
- 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
|
||||
pull: always
|
||||
image: plugins/docker:linux-arm64
|
||||
@@ -729,45 +721,49 @@ trigger:
|
||||
- "refs/tags/**"
|
||||
|
||||
depends_on:
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
- docker-linux-amd64-release
|
||||
- docker-linux-arm64-release
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: notify
|
||||
name: notifications
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
arch: arm64
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
when:
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
- "release/*"
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
status:
|
||||
- success
|
||||
- failure
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- testing-amd64
|
||||
- testing-arm64
|
||||
- translations
|
||||
- release-version
|
||||
- release-master
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
- docker-linux-amd64-release
|
||||
- docker-linux-arm64-release
|
||||
- docker-manifest
|
||||
- docs
|
||||
|
||||
steps:
|
||||
- name: discord
|
||||
pull: always
|
||||
image: appleboy/drone-discord:1.0.0
|
||||
environment:
|
||||
DISCORD_WEBHOOK_ID:
|
||||
image: appleboy/drone-discord:1.2.4
|
||||
settings:
|
||||
message: "{{#success build.status}} ✅ Build #{{build.number}} of `{{repo.name}}` succeeded.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{else}} ❌ Build #{{build.number}} of `{{repo.name}}` failed.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{/success}}\n"
|
||||
webhook_id:
|
||||
from_secret: discord_webhook_id
|
||||
DISCORD_WEBHOOK_TOKEN:
|
||||
webhook_token:
|
||||
from_secret: discord_webhook_token
|
||||
|
107
CHANGELOG.md
107
CHANGELOG.md
@@ -4,13 +4,22 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.11.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.11.0-rc1) - 2020-01-07
|
||||
## [1.11.0](https://github.com/go-gitea/gitea/releases/tag/v1.11.0) - 2020-02-10
|
||||
* BREAKING
|
||||
* Fix followers and following tabs in profile (#10202) (#10203)
|
||||
* Make CertFile and KeyFile relative to CustomPath (#9868) (#9874)
|
||||
* Remove unused endpoints (#9538)
|
||||
* Prefix all user-generated IDs in markup (#9477)
|
||||
* Enforce Gitea environment for pushes (#8982)
|
||||
* Hide some user information via API if user have no enough permission (#8655)
|
||||
* Hide some user information via API if user have not enough permissions (#8655)
|
||||
* Move startpage/homepage translation to crowdin (#8596)
|
||||
* SECURITY
|
||||
* Never allow an empty password to validate (#9682) (#9683)
|
||||
* Prevent redirect to Host (#9678) (#9679)
|
||||
* Swagger hide search field (#9554)
|
||||
* Add "search" to reserved usernames (#9063)
|
||||
* Switch to fomantic-ui (#9374)
|
||||
* Only serve attachments when linked to issue/release and if accessible by user (#9340)
|
||||
* FEATURES
|
||||
* Webhooks should only show sender if it makes sense (#9601)
|
||||
* Provide Default messages for merges (#9393)
|
||||
@@ -44,6 +53,68 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Sign merges, CRUD, Wiki and Repository initialisation with gpg key (#7631)
|
||||
* Add basic repository lfs management (#7199)
|
||||
* BUGFIXES
|
||||
* Fix code-expansion arc-green theme bug (#10180) (#10185)
|
||||
* Prevent double wait-group decrement (#10170) (#10175)
|
||||
* Allow emoji on review head comments (#10159) (#10174)
|
||||
* Fix issue/pull link (#10158) (#10173)
|
||||
* Fix push-create SSH bugs (#10145) (#10151)
|
||||
* Prevent DeleteUser API abuse (#10125) (#10128)
|
||||
* Fix issues/pulls dashboard paging error (#10114) (#10115)
|
||||
* Add button to revert SimpleMDE to plain textarea (#10099) (#10102)
|
||||
* Fix branch page pull request title and link error (#10092) (#10097)
|
||||
* Fix PR API: Only try to get HeadBranch if HeadRepo exist (#10029) (#10088)
|
||||
* Update topics repo count when deleting repository (#10051) (#10081)
|
||||
* Show pull icon on pull requests (#10061) (#10062)
|
||||
* Fix milestone API state parameter unhandled (#10049) (#10052)
|
||||
* Move to using a temporary repo for pushing new PRs (#10009) (#10042)
|
||||
* Fix wiki raw view on sub path (#10002) (#10040)
|
||||
* Ensure that feeds are appropriately restricted (#10018) (#10019)
|
||||
* Sanitize credentials in mirror form (#9975) (#9991)
|
||||
* Close related pull requests when deleting head repository or head branch (#9927) (#9974)
|
||||
* Switch to use -f instead of -F for sendmail (#9961) (#9970)
|
||||
* Fix file rename/copy not supported by indexer (#9965) (#9967)
|
||||
* Fix repo indexer not updating upon push (#9957) (#9963)
|
||||
* Don't convert ellipsis in markdown (#9905) (#9937)
|
||||
* Fixed repo link in generated comment for cross repository dependency (#9863) (#9935)
|
||||
* Check if diff actually contains sections when rendering (#9926) (#9933)
|
||||
* Fix wrong hint when status checking is running on pull request view (#9886) (#9928)
|
||||
* Fix RocketChat (#9908) (#9921)
|
||||
* Do not try to recreate ldap user if they are already created (#9900) (#9919)
|
||||
* Create terminated channel in queue_redis (#9910) (#9911)
|
||||
* Prevent empty LDAP search result from deactivating all users (#9879) (#9896)
|
||||
* Fix wrong permissions check when issues/prs shared operations (#9885) (#9889)
|
||||
* Check user != nil before checking values (#9881) (#9883)
|
||||
* Allow hyphen in language name (#9873) (#9880)
|
||||
* Ensure that 2fa is checked on reset-password (#9857) (#9876)
|
||||
* Fix issues/pulls dependencies problems (#9842) (#9864)
|
||||
* Fix markdown anchor links (#9673) (#9840)
|
||||
* Allow assignee on Pull Creation when Issue Unit is deactivated (#9836) (#9837)
|
||||
* Fix download file wrong content-type (#9825) (#9834)
|
||||
* Fix wrong poster identity on a migrated pull request when submit review (#9827) (#9830)
|
||||
* Fix database dump when log directory is missing (#9818) (#9819)
|
||||
* Fix compare (#9808) (#9814)
|
||||
* Fix push-to-create (#9772) (#9797)
|
||||
* Fix missing msteam webhook on organization (#9781) (#9794)
|
||||
* Fix missing unlock in uniquequeue (#9790) (#9791)
|
||||
* Fix add team on collaborator page when same name as organization (#9778)
|
||||
* DeleteRepoFile incorrectly handles Delete to new branch (#9769) (#9775)
|
||||
* Fix milestones page (#9771)
|
||||
* Fix SimpleMDE quote reply (#9757) (#9768)
|
||||
* Fix missing updated time on migrated issues and comments (#9744) (#9764)
|
||||
* Move Errored PRs out of StatusChecking (#9675) (#9726)
|
||||
* Make hook status printing configurable with delay (#9641) (#9725)
|
||||
* Fix /repos/issues/search (#9698) (#9724)
|
||||
* Silence fomantic error regarding tabs (#9713) (#9718)
|
||||
* Remove unused lock (#9709) (#9710)
|
||||
* Remove q.lock.Unlock() in setInternal to prevent panic (#9705) (#9706)
|
||||
* Load milestone in API PR list (#9671) (#9700)
|
||||
* Don't attempt to close issue if already closed (#9696) (#9699)
|
||||
* Remove google font call (#9668) (#9681)
|
||||
* Eliminate horizontal scroll caused by footer (#9674)
|
||||
* Fix nil reference in repo generation (#9660) (#9666)
|
||||
* Add HTML URL to API Issues (#9654) (#9661)
|
||||
* Add PR review webhook to Telegram (#9653) (#9655)
|
||||
* Use filepath.IsAbs instead of path.IsAbs (#9651) (#9652)
|
||||
* Disable remove button on repository teams when have access to all (#9640)
|
||||
* Clean up old references on branch delete (#9614)
|
||||
* Hide public repos owned by private orgs (#9609)
|
||||
@@ -175,6 +246,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Fix migrate mirror 500 bug (#8526)
|
||||
* Fix password complexity regex for special characters (on master) (#8525)
|
||||
* ENHANCEMENTS
|
||||
* Explicitly refer to PR in squash-merge commit message in case of external tracker (#9844) (#9855)
|
||||
* Add a /user/login landing page option (#9622)
|
||||
* Some more e-mail notification fixes (#9596)
|
||||
* Add branch protection option to block merge on requested changes. (#9592)
|
||||
@@ -291,12 +363,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* wiki - add 'write' 'preview' buttons to wiki edit like in issues (#7241)
|
||||
* Change target branch for pull request (#6488)
|
||||
* Display PR commits and diffs using base repo rather than forked (#3648)
|
||||
* SECURITY
|
||||
* Swagger hide search field (#9554)
|
||||
* Add "search" to reserved usernames (#9063)
|
||||
* Switch to fomantic-ui (#9374)
|
||||
* Only serve attachments when linked to issue/release and if accessible by user (#9340)
|
||||
* Hide credentials when submitting migration through API (#9102)
|
||||
* TESTING
|
||||
* Add debug option to serv to help debug problems (#9492)
|
||||
* Fix the intermittent TestGPGGit failures (#9360)
|
||||
@@ -310,10 +376,12 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Update Github Migration Tests (#8893) (#8938)
|
||||
* Update heatmap fixtures to restore tests (#8615)
|
||||
* TRANSLATION
|
||||
* Fix Korean locales (#9761) (#9780)
|
||||
* Fix placeholders in the error message (#9060)
|
||||
* Fix spelling of admin.users.max_repo_creation (#8934)
|
||||
* Improve german translation of homepage (#8549)
|
||||
* BUILD
|
||||
* Fix webpack polyfills (#9735) (#9738)
|
||||
* Update gitea.com/macaron to 1.4.0 (#9608)
|
||||
* Upgrade lato fonts to v16. (#9498)
|
||||
* Update alpine to 3.11 (#9440)
|
||||
@@ -344,6 +412,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Update the provided gitea.service to mention socket activation (#8531)
|
||||
* Doc added how to setup email (#8520)
|
||||
* MISC
|
||||
* Backport Locales [2020-01-14] (#9773)
|
||||
* Add translatable Powered by Gitea text in footer (#9600)
|
||||
* Add contrib/environment-to-ini (#9519)
|
||||
* Remove unnecessary loading of settings in update hook (#9496)
|
||||
@@ -384,6 +453,24 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Update CodeMirror to version 5.49.0 (#8381)
|
||||
* 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
|
||||
* BUGFIXES
|
||||
* Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
|
||||
@@ -1483,13 +1570,13 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* BUGFIXES
|
||||
* Allow resend of confirmation email when logged in (#6482) (#6487)
|
||||
|
||||
## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
|
||||
## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
|
||||
* BUGFIXES
|
||||
* Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
|
||||
* Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
|
||||
* Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
|
||||
|
||||
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
|
||||
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
|
||||
* SECURITY
|
||||
* Fix potential XSS vulnerability in repository description. (#6306) (#6308)
|
||||
* BUGFIXES
|
||||
|
11
Makefile
11
Makefile
@@ -119,6 +119,13 @@ go-check:
|
||||
exit 1; \
|
||||
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
|
||||
node-check:
|
||||
$(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
|
||||
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
|
||||
vendor:
|
||||
@@ -376,7 +383,7 @@ integrations.mssql.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'
|
||||
|
||||
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
|
||||
|
||||
.PHONY: migrations.mysql.test
|
||||
|
@@ -61,6 +61,10 @@ var (
|
||||
Name: "admin-filter",
|
||||
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{
|
||||
Name: "username-attribute",
|
||||
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") {
|
||||
config.Source.AdminFilter = c.String("admin-filter")
|
||||
}
|
||||
if c.IsSet("allow-deactivate-all") {
|
||||
config.Source.AllowDeactivateAll = c.Bool("allow-deactivate-all")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -151,8 +151,10 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
fatal("Failed to include log: %v", err)
|
||||
if com.IsExist(setting.LogRootPath) {
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
fatal("Failed to include log: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = z.Close(); err != nil {
|
||||
|
148
cmd/hook.go
148
cmd/hook.go
@@ -8,10 +8,12 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"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 {
|
||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||
return nil
|
||||
@@ -101,6 +182,18 @@ Gitea or set your environment appropriately.`, "")
|
||||
total := 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() {
|
||||
// TODO: support news feeds for wiki
|
||||
if isWiki {
|
||||
@@ -124,12 +217,10 @@ Gitea or set your environment appropriately.`, "")
|
||||
newCommitIDs[count] = newCommitID
|
||||
refFullNames[count] = refFullName
|
||||
count++
|
||||
fmt.Fprintf(os.Stdout, "*")
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, "*")
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
@@ -147,12 +238,10 @@ Gitea or set your environment appropriately.`, "")
|
||||
lastline = 0
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stdout, ".")
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, ".")
|
||||
}
|
||||
if lastline >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, "\n")
|
||||
lastline = 0
|
||||
}
|
||||
}
|
||||
@@ -162,8 +251,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||
|
||||
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
|
||||
switch statusCode {
|
||||
@@ -173,14 +261,11 @@ Gitea or set your environment appropriately.`, "")
|
||||
fail(msg, "")
|
||||
}
|
||||
} else if lastline > 0 {
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, "\n")
|
||||
lastline = 0
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, "Checked %d references in total\n", total)
|
||||
os.Stdout.Sync()
|
||||
|
||||
fmt.Fprintf(out, "Checked %d references in total\n", total)
|
||||
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
|
||||
repoUser := os.Getenv(models.EnvRepoUsername)
|
||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||
@@ -241,7 +339,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, ".")
|
||||
fmt.Fprintf(out, ".")
|
||||
oldCommitIDs[count] = string(fields[0])
|
||||
newCommitIDs[count] = string(fields[1])
|
||||
refFullNames[count] = string(fields[2])
|
||||
@@ -250,16 +348,15 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
count++
|
||||
total++
|
||||
os.Stdout.Sync()
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
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)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
return nil
|
||||
}
|
||||
@@ -288,19 +385,18 @@ Gitea or set your environment appropriately.`, "")
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
|
||||
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
|
||||
os.Stdout.Sync()
|
||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||
|
||||
if wasEmpty && masterPushed {
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
|
||||
return nil
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -72,6 +73,7 @@ var (
|
||||
"git-receive-pack": models.AccessModeWrite,
|
||||
lfsAuthenticateVerb: models.AccessModeNone,
|
||||
}
|
||||
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
|
||||
)
|
||||
|
||||
func fail(userMessage, logMessage string, args ...interface{}) {
|
||||
@@ -147,6 +149,10 @@ func runServ(c *cli.Context) error {
|
||||
username := strings.ToLower(rr[0])
|
||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||
|
||||
if alphaDashDotPattern.MatchString(reponame) {
|
||||
fail("Invalid repo name", "Invalid repo name: %s", reponame)
|
||||
}
|
||||
|
||||
if setting.EnablePprof || c.Bool("enable-pprof") {
|
||||
if err := os.MkdirAll(setting.PprofDataPath, os.ModePerm); err != nil {
|
||||
fail("Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
||||
|
@@ -275,8 +275,9 @@ DISABLE_ROUTER_LOG = false
|
||||
; not forget to export the private key):
|
||||
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
|
||||
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
||||
CERT_FILE = custom/https/cert.pem
|
||||
KEY_FILE = custom/https/key.pem
|
||||
; Paths are relative to CUSTOM_PATH
|
||||
CERT_FILE = https/cert.pem
|
||||
KEY_FILE = https/key.pem
|
||||
; Root directory containing templates and static files.
|
||||
; default is the path where Gitea is executed
|
||||
STATIC_ROOT_PATH =
|
||||
|
@@ -18,7 +18,7 @@ params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.10.2
|
||||
version: 1.11.0
|
||||
|
||||
outputs:
|
||||
home:
|
||||
|
@@ -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.
|
||||
- `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.
|
||||
- `CERT_FILE`: **custom/https/cert.pem**: Cert file path used for HTTPS.
|
||||
- `KEY_FILE`: **custom/https/key.pem**: Key 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`: **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_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.
|
||||
@@ -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.
|
||||
- `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
|
||||
- `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`)
|
||||
- `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.
|
||||
|
||||
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
|
||||
|
||||
|
47
integrations/api_issue_milestone_test.go
Normal file
47
integrations/api_issue_milestone_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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 integrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAPIIssuesMilestone(t *testing.T) {
|
||||
defer prepareTestEnv(t)()
|
||||
|
||||
milestone := models.AssertExistsAndLoadBean(t, &models.Milestone{ID: 1}).(*models.Milestone)
|
||||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: milestone.RepoID}).(*models.Repository)
|
||||
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
|
||||
assert.Equal(t, int64(1), int64(milestone.NumIssues))
|
||||
assert.Equal(t, structs.StateOpen, milestone.State())
|
||||
|
||||
session := loginUser(t, owner.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
|
||||
// update values of issue
|
||||
milestoneState := "closed"
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/milestones/%d?token=%s", owner.Name, repo.Name, milestone.ID, token)
|
||||
req := NewRequestWithJSON(t, "PATCH", urlStr, structs.EditMilestoneOption{
|
||||
State: &milestoneState,
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiMilestone structs.Milestone
|
||||
DecodeJSON(t, resp, &apiMilestone)
|
||||
assert.EqualValues(t, "closed", apiMilestone.State)
|
||||
|
||||
req = NewRequest(t, "GET", urlStr)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiMilestone2 structs.Milestone
|
||||
DecodeJSON(t, resp, &apiMilestone2)
|
||||
assert.EqualValues(t, "closed", apiMilestone2.State)
|
||||
}
|
@@ -7,6 +7,7 @@ package integrations
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
@@ -120,3 +121,47 @@ func TestAPIEditIssue(t *testing.T) {
|
||||
assert.Equal(t, body, issueAfter.Content)
|
||||
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)
|
||||
}
|
||||
|
@@ -422,6 +422,9 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", ctx.Reponame)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = git.NewCommand("clone", u.String()).RunInDir(tmpDir)
|
||||
assert.Error(t, err)
|
||||
|
||||
err = git.InitRepository(tmpDir, false)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -449,6 +452,13 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
|
||||
_, err = git.NewCommand("remote", "add", "origin", u.String()).RunInDir(tmpDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
invalidCtx := ctx
|
||||
invalidCtx.Reponame = fmt.Sprintf("invalid/repo-tmp-push-create-%s", u.Scheme)
|
||||
u.Path = invalidCtx.GitPath()
|
||||
|
||||
_, err = git.NewCommand("remote", "add", "invalid", u.String()).RunInDir(tmpDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Push to create disabled
|
||||
setting.Repository.EnablePushCreateUser = false
|
||||
_, err = git.NewCommand("push", "origin", "master").RunInDir(tmpDir)
|
||||
@@ -456,6 +466,12 @@ func doPushCreate(ctx APITestContext, u *url.URL) func(t *testing.T) {
|
||||
|
||||
// Push to create enabled
|
||||
setting.Repository.EnablePushCreateUser = true
|
||||
|
||||
// Invalid repo
|
||||
_, err = git.NewCommand("push", "invalid", "master").RunInDir(tmpDir)
|
||||
assert.Error(t, err)
|
||||
|
||||
// Valid repo
|
||||
_, err = git.NewCommand("push", "origin", "master").RunInDir(tmpDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
|
||||
423313fbd38093bb10d0c8387db9105409c6f196
|
||||
|
@@ -106,3 +106,57 @@ func TestPullCreate_TitleEscape(t *testing.T) {
|
||||
assert.Equal(t, "<u>XSS PR</u>", titleHTML)
|
||||
})
|
||||
}
|
||||
|
||||
func testUIDeleteBranch(t *testing.T, session *TestSession, ownerName, repoName, branchName string) {
|
||||
relURL := "/" + path.Join(ownerName, repoName, "branches")
|
||||
req := NewRequest(t, "GET", relURL)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
req = NewRequestWithValues(t, "POST", relURL+"/delete", map[string]string{
|
||||
"_csrf": getCsrf(t, htmlDoc.doc),
|
||||
"name": branchName,
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
func testDeleteRepository(t *testing.T, session *TestSession, ownerName, repoName string) {
|
||||
relURL := "/" + path.Join(ownerName, repoName, "settings")
|
||||
req := NewRequest(t, "GET", relURL)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
req = NewRequestWithValues(t, "POST", relURL+"?action=delete", map[string]string{
|
||||
"_csrf": getCsrf(t, htmlDoc.doc),
|
||||
"repo_name": repoName,
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusFound)
|
||||
}
|
||||
|
||||
func TestPullBranchDelete(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
defer prepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testCreateBranch(t, session, "user1", "repo1", "branch/master", "master1", http.StatusFound)
|
||||
testEditFile(t, session, "user1", "repo1", "master1", "README.md", "Hello, World (Edited)\n")
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master1", "This is a pull title")
|
||||
|
||||
// check the redirected URL
|
||||
url := resp.HeaderMap.Get("Location")
|
||||
assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
|
||||
req := NewRequest(t, "GET", url)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// delete head branch and confirm pull page is ok
|
||||
testUIDeleteBranch(t, session, "user1", "repo1", "master1")
|
||||
req = NewRequest(t, "GET", url)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// delete head repository and confirm pull page is ok
|
||||
testDeleteRepository(t, session, "user1", "repo1")
|
||||
req = NewRequest(t, "GET", url)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
})
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -48,20 +47,20 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
|
||||
commitID := path.Base(commitURL)
|
||||
|
||||
statusList := []models.CommitStatusState{
|
||||
models.CommitStatusPending,
|
||||
models.CommitStatusError,
|
||||
models.CommitStatusFailure,
|
||||
models.CommitStatusWarning,
|
||||
models.CommitStatusSuccess,
|
||||
statusList := []api.CommitStatusState{
|
||||
api.CommitStatusPending,
|
||||
api.CommitStatusError,
|
||||
api.CommitStatusFailure,
|
||||
api.CommitStatusWarning,
|
||||
api.CommitStatusSuccess,
|
||||
}
|
||||
|
||||
statesIcons := map[models.CommitStatusState]string{
|
||||
models.CommitStatusPending: "circle icon yellow",
|
||||
models.CommitStatusSuccess: "check icon green",
|
||||
models.CommitStatusError: "warning icon red",
|
||||
models.CommitStatusFailure: "remove icon red",
|
||||
models.CommitStatusWarning: "warning sign icon yellow",
|
||||
statesIcons := map[api.CommitStatusState]string{
|
||||
api.CommitStatusPending: "circle icon yellow",
|
||||
api.CommitStatusSuccess: "check icon green",
|
||||
api.CommitStatusError: "warning icon red",
|
||||
api.CommitStatusFailure: "remove icon red",
|
||||
api.CommitStatusWarning: "warning sign icon yellow",
|
||||
}
|
||||
|
||||
// Update commit status, and check if icon is updated as well
|
||||
|
@@ -432,6 +432,8 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
|
||||
}
|
||||
|
||||
cond = cond.And(builder.In("repo_id", repoIDs))
|
||||
} else {
|
||||
cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.RequestingUserID)))
|
||||
}
|
||||
|
||||
cond = cond.And(builder.Eq{"user_id": opts.RequestedUser.ID})
|
||||
|
@@ -19,52 +19,19 @@ import (
|
||||
"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
|
||||
type CommitStatus struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||
Repo *Repository `xorm:"-"`
|
||||
State CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
|
||||
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
|
||||
TargetURL string `xorm:"TEXT"`
|
||||
Description string `xorm:"TEXT"`
|
||||
ContextHash string `xorm:"char(40) index"`
|
||||
Context string `xorm:"TEXT"`
|
||||
Creator *User `xorm:"-"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
|
||||
Repo *Repository `xorm:"-"`
|
||||
State api.CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
|
||||
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
|
||||
TargetURL string `xorm:"TEXT"`
|
||||
Description string `xorm:"TEXT"`
|
||||
ContextHash string `xorm:"char(40) index"`
|
||||
Context string `xorm:"TEXT"`
|
||||
Creator *User `xorm:"-"`
|
||||
CreatorID int64
|
||||
|
||||
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
|
||||
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
||||
var lastStatus *CommitStatus
|
||||
var state CommitStatusState
|
||||
var state api.CommitStatusState
|
||||
for _, status := range statuses {
|
||||
if status.State.IsWorseThan(state) {
|
||||
if status.State.NoBetterThan(state) {
|
||||
state = status.State
|
||||
lastStatus = status
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ package models
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -23,22 +24,22 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||
assert.Len(t, statuses, 5)
|
||||
|
||||
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, "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, "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, "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, "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())
|
||||
}
|
||||
|
@@ -381,6 +381,7 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
|
||||
apiIssue := &api.Issue{
|
||||
ID: issue.ID,
|
||||
URL: issue.APIURL(),
|
||||
HTMLURL: issue.HTMLURL(),
|
||||
Index: issue.Index,
|
||||
Poster: issue.Poster.APIFormat(),
|
||||
Title: issue.Title,
|
||||
@@ -402,11 +403,12 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
|
||||
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
|
||||
}
|
||||
|
||||
issue.loadMilestone(e)
|
||||
if issue.Milestone != nil {
|
||||
apiIssue.Milestone = issue.Milestone.APIFormat()
|
||||
}
|
||||
issue.loadAssignees(e)
|
||||
|
||||
issue.loadAssignees(e)
|
||||
if len(issue.Assignees) > 0 {
|
||||
for _, assignee := range issue.Assignees {
|
||||
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.
|
||||
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 {
|
||||
|
@@ -376,6 +376,11 @@ func (comments CommentList) loadDependentIssues(e Engine) error {
|
||||
for _, comment := range comments {
|
||||
if comment.DependentIssue == nil {
|
||||
comment.DependentIssue = issues[comment.DependentIssueID]
|
||||
if comment.DependentIssue != nil {
|
||||
if err := comment.DependentIssue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@@ -6,6 +6,7 @@ package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
@@ -95,6 +96,8 @@ func NewMilestone(m *Milestone) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Name = strings.TrimSpace(m.Name)
|
||||
|
||||
if _, err = sess.Insert(m); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -268,6 +271,7 @@ func GetMilestones(repoID int64, page int, isClosed bool, sortType string) (Mile
|
||||
}
|
||||
|
||||
func updateMilestone(e Engine, m *Milestone) error {
|
||||
m.Name = strings.TrimSpace(m.Name)
|
||||
_, err := e.ID(m.ID).AllCols().
|
||||
SetExpr("num_issues", builder.Select("count(*)").From("issue").Where(
|
||||
builder.Eq{"milestone_id": m.ID},
|
||||
@@ -283,12 +287,33 @@ func updateMilestone(e Engine, m *Milestone) error {
|
||||
}
|
||||
|
||||
// UpdateMilestone updates information of given milestone.
|
||||
func UpdateMilestone(m *Milestone) error {
|
||||
if err := updateMilestone(x, m); err != nil {
|
||||
func UpdateMilestone(m *Milestone, oldIsClosed bool) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return updateMilestoneCompleteness(x, m.ID)
|
||||
if m.IsClosed && !oldIsClosed {
|
||||
m.ClosedDateUnix = timeutil.TimeStampNow()
|
||||
}
|
||||
|
||||
if err := updateMilestone(sess, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := updateMilestoneCompleteness(sess, m.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if IsClosed changed, update milestone numbers of repository
|
||||
if oldIsClosed != m.IsClosed {
|
||||
if err := updateRepoMilestoneNum(sess, m.RepoID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func updateMilestoneCompleteness(e Engine, milestoneID int64) error {
|
||||
|
@@ -158,10 +158,11 @@ func TestUpdateMilestone(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
milestone := AssertExistsAndLoadBean(t, &Milestone{ID: 1}).(*Milestone)
|
||||
milestone.Name = "newMilestoneName"
|
||||
milestone.Name = " newMilestoneName "
|
||||
milestone.Content = "newMilestoneContent"
|
||||
assert.NoError(t, UpdateMilestone(milestone))
|
||||
AssertExistsAndLoadBean(t, milestone)
|
||||
assert.NoError(t, UpdateMilestone(milestone, milestone.IsClosed))
|
||||
milestone = AssertExistsAndLoadBean(t, &Milestone{ID: 1}).(*Milestone)
|
||||
assert.EqualValues(t, "newMilestoneName", milestone.Name)
|
||||
CheckConsistencyFor(t, &Milestone{})
|
||||
}
|
||||
|
||||
|
@@ -461,7 +461,7 @@ var (
|
||||
|
||||
// LoginViaLDAP queries if login/password is valid against the LDAP directory pool,
|
||||
// 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)
|
||||
if sr == nil {
|
||||
// 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
|
||||
if isExist, err := IsUserExist(0, sr.Username); err != nil {
|
||||
return nil, err
|
||||
} else if isExist &&
|
||||
!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
|
||||
} else if isExist {
|
||||
if user == nil {
|
||||
user, err = GetUserByName(sr.Username)
|
||||
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) {
|
||||
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,
|
||||
// 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.
|
||||
if len(cfg.AllowedDomains) > 0 {
|
||||
idx := strings.Index(login, "@")
|
||||
@@ -625,7 +633,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !autoRegister {
|
||||
if 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,
|
||||
// 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 strings.Contains(err.Error(), "Authentication failure") {
|
||||
return nil, ErrUserNotExist{0, login, 0}
|
||||
@@ -665,7 +673,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !autoRegister {
|
||||
if 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.
|
||||
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 {
|
||||
return nil, ErrLoginSourceNotActived
|
||||
}
|
||||
@@ -691,11 +699,11 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
|
||||
var err error
|
||||
switch source.Type {
|
||||
case LoginLDAP, LoginDLDAP:
|
||||
user, err = LoginViaLDAP(user, login, password, source, autoRegister)
|
||||
user, err = LoginViaLDAP(user, login, password, source)
|
||||
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:
|
||||
user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
|
||||
user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig))
|
||||
default:
|
||||
return nil, ErrUnsupportedLoginType
|
||||
}
|
||||
@@ -775,7 +783,7 @@ func UserSignIn(username, password string) (*User, error) {
|
||||
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
|
||||
continue
|
||||
}
|
||||
authUser, err := ExternalUserLogin(nil, username, password, source, true)
|
||||
authUser, err := ExternalUserLogin(nil, username, password, source)
|
||||
if err == nil {
|
||||
return authUser, nil
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@ const (
|
||||
PullRequestStatusChecking
|
||||
PullRequestStatusMergeable
|
||||
PullRequestStatusManuallyMerged
|
||||
PullRequestStatusError
|
||||
)
|
||||
|
||||
// PullRequest represents relation between pull request and repositories.
|
||||
@@ -67,7 +68,11 @@ type PullRequest struct {
|
||||
// MustHeadUserName returns the HeadRepo's username if failed return blank
|
||||
func (pr *PullRequest) MustHeadUserName() string {
|
||||
if err := pr.LoadHeadRepo(); err != nil {
|
||||
log.Error("LoadHeadRepo: %v", err)
|
||||
if !IsErrRepoNotExist(err) {
|
||||
log.Error("LoadHeadRepo: %v", err)
|
||||
} else {
|
||||
log.Warn("LoadHeadRepo %d but repository does not exist: %v", pr.HeadRepoID, err)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return pr.HeadRepo.MustOwnerName()
|
||||
@@ -384,6 +389,13 @@ func (pr *PullRequest) GetDefaultSquashMessage() string {
|
||||
log.Error("LoadIssue: %v", err)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -408,7 +420,7 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
||||
err error
|
||||
)
|
||||
if err = pr.Issue.loadRepo(e); err != nil {
|
||||
log.Error("loadRepo[%d]: %v", pr.ID, err)
|
||||
log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
}
|
||||
apiIssue := pr.Issue.apiFormat(e)
|
||||
@@ -419,19 +431,14 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if pr.HeadRepo == nil {
|
||||
if pr.HeadRepoID != 0 && pr.HeadRepo == nil {
|
||||
pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID)
|
||||
if err != nil {
|
||||
if err != nil && !IsErrRepoNotExist(err) {
|
||||
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err = pr.Issue.loadRepo(e); err != nil {
|
||||
log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
apiPullRequest := &api.PullRequest{
|
||||
ID: pr.ID,
|
||||
URL: pr.Issue.HTMLURL(),
|
||||
@@ -483,37 +490,45 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
||||
apiPullRequest.Base = apiBaseBranchInfo
|
||||
}
|
||||
|
||||
headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch)
|
||||
if err != nil {
|
||||
if git.IsErrBranchNotExist(err) {
|
||||
apiPullRequest.Head = nil
|
||||
} else {
|
||||
log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
apiHeadBranchInfo := &api.PRBranchInfo{
|
||||
Name: pr.HeadBranch,
|
||||
Ref: pr.HeadBranch,
|
||||
RepoID: pr.HeadRepoID,
|
||||
Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
|
||||
}
|
||||
headCommit, err = headBranch.GetCommit()
|
||||
if pr.HeadRepo != nil {
|
||||
headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
apiHeadBranchInfo.Sha = ""
|
||||
if git.IsErrBranchNotExist(err) {
|
||||
apiPullRequest.Head = nil
|
||||
} else {
|
||||
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
|
||||
log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
apiHeadBranchInfo.Sha = headCommit.ID.String()
|
||||
apiHeadBranchInfo := &api.PRBranchInfo{
|
||||
Name: pr.HeadBranch,
|
||||
Ref: pr.HeadBranch,
|
||||
RepoID: pr.HeadRepoID,
|
||||
Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
|
||||
}
|
||||
headCommit, err = headBranch.GetCommit()
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
apiHeadBranchInfo.Sha = ""
|
||||
} else {
|
||||
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
apiHeadBranchInfo.Sha = headCommit.ID.String()
|
||||
}
|
||||
apiPullRequest.Head = apiHeadBranchInfo
|
||||
}
|
||||
} else {
|
||||
apiPullRequest.Head = &api.PRBranchInfo{
|
||||
Name: pr.HeadBranch,
|
||||
Ref: fmt.Sprintf("refs/pull/%d/head", pr.Index),
|
||||
RepoID: -1,
|
||||
}
|
||||
apiPullRequest.Head = apiHeadBranchInfo
|
||||
}
|
||||
|
||||
if pr.Status != PullRequestStatusChecking {
|
||||
mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
|
||||
mergeable := !(pr.Status == PullRequestStatusConflict || pr.Status == PullRequestStatusError) && !pr.IsWorkInProgress()
|
||||
apiPullRequest.Mergeable = mergeable
|
||||
}
|
||||
if pr.HasMerged {
|
||||
|
@@ -204,6 +204,14 @@ type Repository struct {
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// SanitizedOriginalURL returns a sanitized OriginalURL
|
||||
func (repo *Repository) SanitizedOriginalURL() string {
|
||||
if repo.OriginalURL == "" {
|
||||
return ""
|
||||
}
|
||||
return util.SanitizeURLCredentials(repo.OriginalURL, false)
|
||||
}
|
||||
|
||||
// ColorFormat returns a colored string to represent this repo
|
||||
func (repo *Repository) ColorFormat(s fmt.State) {
|
||||
var ownerName interface{}
|
||||
@@ -1902,6 +1910,12 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(repo.Topics) > 0 {
|
||||
if err = removeTopicsFromRepo(sess, repo.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Remove repository files should be executed after transaction succeed.
|
||||
repoPath := repo.repoPath(sess)
|
||||
removeAllWithNotice(sess, "Delete repository files", repoPath)
|
||||
|
@@ -124,41 +124,43 @@ func generateRepoCommit(e Engine, repo, templateRepo, generateRepo *Repository,
|
||||
return fmt.Errorf("checkGiteaTemplate: %v", err)
|
||||
}
|
||||
|
||||
if err := os.Remove(gt.Path); err != nil {
|
||||
return fmt.Errorf("remove .giteatemplate: %v", err)
|
||||
}
|
||||
if gt != nil {
|
||||
if err := os.Remove(gt.Path); err != nil {
|
||||
return fmt.Errorf("remove .giteatemplate: %v", err)
|
||||
}
|
||||
|
||||
// Avoid walking tree if there are no globs
|
||||
if len(gt.Globs()) > 0 {
|
||||
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
|
||||
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
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
|
||||
// Avoid walking tree if there are no globs
|
||||
if len(gt.Globs()) > 0 {
|
||||
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
|
||||
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
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
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -315,6 +315,17 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
|
||||
|
||||
// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
|
||||
func accessibleRepositoryCondition(userID int64) builder.Cond {
|
||||
if userID <= 0 {
|
||||
return builder.And(
|
||||
builder.Eq{"`repository`.is_private": false},
|
||||
builder.Or(
|
||||
// A. Aren't in organisations __OR__
|
||||
builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})),
|
||||
// B. Is a public organisation.
|
||||
builder.In("`repository`.owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"visibility": structs.VisibleTypePublic}))),
|
||||
)
|
||||
}
|
||||
|
||||
return builder.Or(
|
||||
// 1. Be able to see all non-private repositories that either:
|
||||
builder.And(
|
||||
@@ -349,6 +360,12 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
return SearchRepository(opts)
|
||||
}
|
||||
|
||||
// AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered.
|
||||
func AccessibleRepoIDsQuery(userID int64) *builder.Builder {
|
||||
// NB: Please note this code needs to still work if user is nil
|
||||
return builder.Select("id").From("repository").Where(accessibleRepositoryCondition(userID))
|
||||
}
|
||||
|
||||
// FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id
|
||||
func FindUserAccessibleRepoIDs(userID int64) ([]int64, error) {
|
||||
var accessCond builder.Cond = builder.Eq{"is_private": false}
|
||||
|
@@ -129,7 +129,7 @@ func addTopicByNameToRepo(e Engine, repoID int64, topicName string) (*Topic, err
|
||||
}
|
||||
|
||||
// removeTopicFromRepo remove a topic from a repo and decrements the topic repo count
|
||||
func removeTopicFromRepo(repoID int64, topic *Topic, e Engine) error {
|
||||
func removeTopicFromRepo(e Engine, repoID int64, topic *Topic) error {
|
||||
topic.RepoCount--
|
||||
if _, err := e.ID(topic.ID).Cols("repo_count").Update(topic); err != nil {
|
||||
return err
|
||||
@@ -145,6 +145,24 @@ func removeTopicFromRepo(repoID int64, topic *Topic, e Engine) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeTopicsFromRepo remove all topics from the repo and decrements respective topics repo count
|
||||
func removeTopicsFromRepo(e Engine, repoID int64) error {
|
||||
_, err := e.Where(
|
||||
builder.In("id",
|
||||
builder.Select("topic_id").From("repo_topic").Where(builder.Eq{"repo_id": repoID}),
|
||||
),
|
||||
).Cols("repo_count").SetExpr("repo_count", "repo_count-1").Update(&Topic{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = e.Delete(&RepoTopic{RepoID: repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindTopicOptions represents the options when fdin topics
|
||||
type FindTopicOptions struct {
|
||||
RepoID int64
|
||||
@@ -217,7 +235,7 @@ func DeleteTopic(repoID int64, topicName string) (*Topic, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err = removeTopicFromRepo(repoID, topic, x)
|
||||
err = removeTopicFromRepo(x, repoID, topic)
|
||||
|
||||
return topic, err
|
||||
}
|
||||
@@ -278,7 +296,7 @@ func SaveTopics(repoID int64, topicNames ...string) error {
|
||||
}
|
||||
|
||||
for _, topic := range removeTopics {
|
||||
err := removeTopicFromRepo(repoID, topic, sess)
|
||||
err := removeTopicFromRepo(sess, repoID, topic)
|
||||
if 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
|
||||
func (u *User) IsPasswordSet() bool {
|
||||
return len(u.Passwd) > 0
|
||||
return !u.ValidatePassword("")
|
||||
}
|
||||
|
||||
// UploadAvatar saves custom avatar for user.
|
||||
@@ -1760,6 +1760,15 @@ func SyncExternalUsers(ctx context.Context) {
|
||||
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 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
@@ -30,6 +30,7 @@ type AuthenticationForm struct {
|
||||
SearchPageSize int
|
||||
Filter string
|
||||
AdminFilter string
|
||||
AllowDeactivateAll bool
|
||||
IsActive bool
|
||||
IsSyncEnabled bool
|
||||
SMTPAuth string
|
||||
|
@@ -47,6 +47,7 @@ type Source struct {
|
||||
Filter string // Query filter to validate entry
|
||||
AdminFilter string // Query filter to check if user is admin
|
||||
Enabled bool // if this source is disabled
|
||||
AllowDeactivateAll bool // Allow an empty search response to deactivate all users from this source
|
||||
}
|
||||
|
||||
// SearchResult : user data
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// 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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -122,7 +123,7 @@ func (ctx *Context) RedirectToFirst(location ...string) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@@ -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?
|
||||
isAssigned, _ := models.IsUserAssignedToIssue(issue, user)
|
||||
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.
|
||||
func (r *Repository) CanCreateIssueDependencies(user *models.User) bool {
|
||||
return r.Permission.CanWrite(models.UnitTypeIssues) && r.Repository.IsDependenciesEnabled()
|
||||
func (r *Repository) CanCreateIssueDependencies(user *models.User, isPull bool) bool {
|
||||
return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull)
|
||||
}
|
||||
|
||||
// GetCommitsCount returns cached commit count for current view
|
||||
|
@@ -7,10 +7,12 @@ package graceful
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -99,12 +101,25 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string, serve ServeFuncti
|
||||
}
|
||||
|
||||
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 {
|
||||
log.Error("Failed to load https cert file %s for %s:%s: %v", certFile, srv.network, srv.address, 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)
|
||||
}
|
||||
|
||||
@@ -201,9 +216,12 @@ func (wl *wrappedListener) Accept() (net.Conn, error) {
|
||||
}
|
||||
}
|
||||
|
||||
closed := int32(0)
|
||||
|
||||
c = wrappedConn{
|
||||
Conn: c,
|
||||
server: wl.server,
|
||||
closed: &closed,
|
||||
}
|
||||
|
||||
wl.server.wg.Add(1)
|
||||
@@ -227,12 +245,12 @@ func (wl *wrappedListener) File() (*os.File, error) {
|
||||
type wrappedConn struct {
|
||||
net.Conn
|
||||
server *Server
|
||||
closed *int32
|
||||
}
|
||||
|
||||
func (w wrappedConn) Close() error {
|
||||
err := w.Conn.Close()
|
||||
if err == nil {
|
||||
if atomic.CompareAndSwapInt32(w.closed, 0, 1) {
|
||||
w.server.wg.Done()
|
||||
}
|
||||
return err
|
||||
return w.Conn.Close()
|
||||
}
|
||||
|
@@ -116,7 +116,12 @@ func nonGenesisChanges(repo *models.Repository, revision string) (*repoChanges,
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
filename := strings.TrimSpace(line[1:])
|
||||
fields := strings.Split(line, "\t")
|
||||
if len(fields) < 2 {
|
||||
log.Warn("Unparseable output for diff --name-status: `%s`)", line)
|
||||
continue
|
||||
}
|
||||
filename := fields[1]
|
||||
if len(filename) == 0 {
|
||||
continue
|
||||
} else if filename[0] == '"' {
|
||||
@@ -126,11 +131,31 @@ func nonGenesisChanges(repo *models.Repository, revision string) (*repoChanges,
|
||||
}
|
||||
}
|
||||
|
||||
switch status := line[0]; status {
|
||||
switch status := fields[0][0]; status {
|
||||
case 'M', 'A':
|
||||
updatedFilenames = append(updatedFilenames, filename)
|
||||
case 'D':
|
||||
changes.RemovedFilenames = append(changes.RemovedFilenames, filename)
|
||||
case 'R', 'C':
|
||||
if len(fields) < 3 {
|
||||
log.Warn("Unparseable output for diff --name-status: `%s`)", line)
|
||||
continue
|
||||
}
|
||||
dest := fields[2]
|
||||
if len(dest) == 0 {
|
||||
log.Warn("Unparseable output for diff --name-status: `%s`)", line)
|
||||
continue
|
||||
}
|
||||
if dest[0] == '"' {
|
||||
dest, err = strconv.Unquote(dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if status == 'R' {
|
||||
changes.RemovedFilenames = append(changes.RemovedFilenames, filename)
|
||||
}
|
||||
updatedFilenames = append(updatedFilenames, dest)
|
||||
default:
|
||||
log.Warn("Unrecognized status: %c (line=%s)", status, line)
|
||||
}
|
||||
|
@@ -79,6 +79,9 @@ func (g *GiteaASTTransformer) Transform(node *ast.Document, reader text.Reader,
|
||||
}
|
||||
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
|
||||
}
|
||||
return ast.WalkContinue, nil
|
||||
|
@@ -48,8 +48,9 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
|
||||
common.FootnoteExtension,
|
||||
extension.NewTypographer(
|
||||
extension.WithTypographicSubstitutions(extension.TypographicSubstitutions{
|
||||
extension.EnDash: nil,
|
||||
extension.EmDash: nil,
|
||||
extension.EnDash: nil,
|
||||
extension.EmDash: nil,
|
||||
extension.Ellipsis: nil,
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
@@ -38,7 +38,7 @@ func NewSanitizer() {
|
||||
func ReplaceSanitizer() {
|
||||
sanitizer.policy = bluemonday.UGCPolicy()
|
||||
// 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
|
||||
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
|
||||
|
@@ -14,6 +14,7 @@ type Comment struct {
|
||||
PosterName string
|
||||
PosterEmail string
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
Content string
|
||||
Reactions *Reactions
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ type Issue struct {
|
||||
State string // closed, open
|
||||
IsLocked bool
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
Closed *time.Time
|
||||
Labels []*Label
|
||||
Reactions *Reactions
|
||||
|
@@ -21,6 +21,7 @@ type PullRequest struct {
|
||||
Milestone string
|
||||
State string
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
Closed *time.Time
|
||||
Labels []*Label
|
||||
PatchURL string
|
||||
|
@@ -332,6 +332,7 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error {
|
||||
MilestoneID: milestoneID,
|
||||
Labels: labels,
|
||||
CreatedUnix: timeutil.TimeStamp(issue.Created.Unix()),
|
||||
UpdatedUnix: timeutil.TimeStamp(issue.Updated.Unix()),
|
||||
}
|
||||
|
||||
userid, ok := g.userMap[issue.PosterID]
|
||||
@@ -406,6 +407,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
|
||||
Type: models.CommentTypeComment,
|
||||
Content: comment.Content,
|
||||
CreatedUnix: timeutil.TimeStamp(comment.Created.Unix()),
|
||||
UpdatedUnix: timeutil.TimeStamp(comment.Updated.Unix()),
|
||||
}
|
||||
|
||||
if userid > 0 {
|
||||
@@ -574,6 +576,7 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
|
||||
IsLocked: pr.IsLocked,
|
||||
Labels: labels,
|
||||
CreatedUnix: timeutil.TimeStamp(pr.Created.Unix()),
|
||||
UpdatedUnix: timeutil.TimeStamp(pr.Updated.Unix()),
|
||||
}
|
||||
|
||||
userid, ok := g.userMap[pr.PosterID]
|
||||
|
@@ -24,6 +24,8 @@ import (
|
||||
var (
|
||||
_ base.Downloader = &GithubDownloaderV3{}
|
||||
_ base.DownloaderFactory = &GithubDownloaderV3Factory{}
|
||||
// GithubLimitRateRemaining limit to wait for new rate to apply
|
||||
GithubLimitRateRemaining = 0
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -115,7 +117,7 @@ func (g *GithubDownloaderV3) SetContext(ctx context.Context) {
|
||||
}
|
||||
|
||||
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))
|
||||
select {
|
||||
case <-g.ctx.Done():
|
||||
@@ -124,15 +126,24 @@ func (g *GithubDownloaderV3) sleep() {
|
||||
case <-timer.C:
|
||||
}
|
||||
|
||||
rates, _, err := g.client.RateLimits(g.ctx)
|
||||
err := g.RefreshRate()
|
||||
if err != nil {
|
||||
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
|
||||
func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
|
||||
g.sleep()
|
||||
@@ -385,6 +396,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
|
||||
Milestone: milestone,
|
||||
State: *issue.State,
|
||||
Created: *issue.CreatedAt,
|
||||
Updated: *issue.UpdatedAt,
|
||||
Labels: labels,
|
||||
Reactions: reactions,
|
||||
Closed: issue.ClosedAt,
|
||||
@@ -428,6 +440,7 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er
|
||||
PosterEmail: email,
|
||||
Content: *comment.Body,
|
||||
Created: *comment.CreatedAt,
|
||||
Updated: *comment.UpdatedAt,
|
||||
Reactions: reactions,
|
||||
})
|
||||
}
|
||||
@@ -523,6 +536,7 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
|
||||
Milestone: milestone,
|
||||
State: *pr.State,
|
||||
Created: *pr.CreatedAt,
|
||||
Updated: *pr.UpdatedAt,
|
||||
Closed: pr.ClosedAt,
|
||||
Labels: labels,
|
||||
Merged: merged,
|
||||
|
@@ -6,6 +6,7 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -62,7 +63,11 @@ func assertLabelEqual(t *testing.T, name, color, description string, label *base
|
||||
}
|
||||
|
||||
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()
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, &base.Repository{
|
||||
@@ -157,6 +162,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterName: "guillep2k",
|
||||
State: "closed",
|
||||
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{
|
||||
{
|
||||
Name: "bug",
|
||||
@@ -189,6 +195,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterName: "mrsdizzie",
|
||||
State: "closed",
|
||||
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{
|
||||
{
|
||||
Name: "duplicate",
|
||||
@@ -219,6 +226,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterID: 1669571,
|
||||
PosterName: "mrsdizzie",
|
||||
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",
|
||||
Reactions: &base.Reactions{
|
||||
TotalCount: 1,
|
||||
@@ -235,6 +243,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterID: 1669571,
|
||||
PosterName: "mrsdizzie",
|
||||
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",
|
||||
Reactions: &base.Reactions{
|
||||
TotalCount: 0,
|
||||
@@ -266,6 +275,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterName: "mrsdizzie",
|
||||
State: "closed",
|
||||
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{
|
||||
{
|
||||
Name: "documentation",
|
||||
@@ -302,6 +312,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
PosterName: "mrsdizzie",
|
||||
State: "open",
|
||||
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{
|
||||
{
|
||||
Name: "bug",
|
||||
|
@@ -6,6 +6,7 @@ package indexer
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
code_indexer "code.gitea.io/gitea/modules/indexer/code"
|
||||
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -118,7 +119,7 @@ func (r *indexerNotifier) NotifyMigrateRepository(doer *models.User, u *models.U
|
||||
}
|
||||
|
||||
func (r *indexerNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) {
|
||||
if setting.Indexer.RepoIndexerEnabled && refName == repo.DefaultBranch {
|
||||
if setting.Indexer.RepoIndexerEnabled && refName == git.BranchPrefix+repo.DefaultBranch {
|
||||
code_indexer.UpdateRepoIndexer(repo)
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -33,6 +34,7 @@ type PersistableChannelQueueConfiguration struct {
|
||||
type PersistableChannelQueue struct {
|
||||
*ChannelQueue
|
||||
delayedStarter
|
||||
lock sync.Mutex
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
|
@@ -84,11 +84,12 @@ func NewRedisQueue(handle HandlerFunc, cfg, exemplar interface{}) (Queue, error)
|
||||
boostWorkers: config.BoostWorkers,
|
||||
maxNumberOfWorkers: config.MaxWorkers,
|
||||
},
|
||||
queueName: config.QueueName,
|
||||
exemplar: exemplar,
|
||||
closed: make(chan struct{}),
|
||||
workers: config.Workers,
|
||||
name: config.Name,
|
||||
queueName: config.QueueName,
|
||||
exemplar: exemplar,
|
||||
closed: make(chan struct{}),
|
||||
terminated: make(chan struct{}),
|
||||
workers: config.Workers,
|
||||
name: config.Name,
|
||||
}
|
||||
if len(dbs) == 0 {
|
||||
return nil, errors.New("no redis host specified")
|
||||
|
@@ -28,7 +28,6 @@ type WrappedQueueConfiguration struct {
|
||||
}
|
||||
|
||||
type delayedStarter struct {
|
||||
lock sync.Mutex
|
||||
internal Queue
|
||||
underlying Type
|
||||
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)
|
||||
if err == nil {
|
||||
q.internal = queue
|
||||
q.lock.Unlock()
|
||||
break
|
||||
}
|
||||
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
|
||||
type WrappedQueue struct {
|
||||
delayedStarter
|
||||
lock sync.Mutex
|
||||
handle HandlerFunc
|
||||
exemplar interface{}
|
||||
channel chan Data
|
||||
|
@@ -103,8 +103,8 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*m
|
||||
refMarked[key] = true
|
||||
|
||||
// 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
|
||||
cancomment := canclose || perm.CanRead(models.UnitTypeIssues)
|
||||
canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWriteIssuesOrPulls(refIssue.IsPull) || refIssue.PosterID == doer.ID
|
||||
cancomment := canclose || perm.CanReadIssuesOrPulls(refIssue.IsPull)
|
||||
|
||||
// Don't proceed if the user can't comment
|
||||
if !cancomment {
|
||||
@@ -137,9 +137,11 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*m
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := changeIssueStatus(refRepo, refIssue, doer, ref.Action == references.XRefActionCloses); err != nil {
|
||||
return err
|
||||
close := (ref.Action == references.XRefActionCloses)
|
||||
if close != refIssue.IsClosed {
|
||||
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 opts.NewBranch != opts.OldBranch {
|
||||
newBranch, err := repo.GetBranch(opts.NewBranch)
|
||||
if git.IsErrNotExist(err) {
|
||||
if err != nil && !git.IsErrBranchNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
if newBranch != nil {
|
||||
|
@@ -475,9 +475,18 @@ func PushUpdate(repo *models.Repository, branch string, opts PushUpdateOptions)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("TriggerTask '%s/%s' by %s", repo.Name, branch, pusher.Name)
|
||||
if !isDelRef {
|
||||
if err = models.RemoveDeletedBranch(repo.ID, opts.Branch); err != nil {
|
||||
log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, opts.Branch, err)
|
||||
}
|
||||
|
||||
go pull_service.AddTestPullRequestTask(pusher, repo.ID, branch, true)
|
||||
log.Trace("TriggerTask '%s/%s' by %s", repo.Name, branch, pusher.Name)
|
||||
|
||||
go pull_service.AddTestPullRequestTask(pusher, repo.ID, branch, true)
|
||||
// close all related pulls
|
||||
} else if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil {
|
||||
log.Error("close related pull request failed: %v", err)
|
||||
}
|
||||
|
||||
if err = models.WatchIfAuto(opts.PusherID, repo.ID, true); err != nil {
|
||||
log.Warn("Fail to perform auto watch on user %v for repo %v: %v", opts.PusherID, repo.ID, err)
|
||||
@@ -524,12 +533,15 @@ func PushUpdates(repo *models.Repository, optsList []*PushUpdateOptions) error {
|
||||
if err = models.RemoveDeletedBranch(repo.ID, opts.Branch); err != nil {
|
||||
log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, opts.Branch, err)
|
||||
}
|
||||
|
||||
log.Trace("TriggerTask '%s/%s' by %s", repo.Name, opts.Branch, pusher.Name)
|
||||
|
||||
go pull_service.AddTestPullRequestTask(pusher, repo.ID, opts.Branch, true)
|
||||
// close all related pulls
|
||||
} else if err = pull_service.CloseBranchPulls(pusher, repo.ID, opts.Branch); err != nil {
|
||||
log.Error("close related pull request failed: %v", err)
|
||||
}
|
||||
|
||||
log.Trace("TriggerTask '%s/%s' by %s", repo.Name, opts.Branch, pusher.Name)
|
||||
|
||||
go pull_service.AddTestPullRequestTask(pusher, repo.ID, opts.Branch, true)
|
||||
|
||||
if err = models.WatchIfAuto(opts.PusherID, repo.ID, true); err != nil {
|
||||
log.Warn("Fail to perform auto watch on user %v for repo %v: %v", opts.PusherID, repo.ID, err)
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ var (
|
||||
MaxGitDiffLines int
|
||||
MaxGitDiffLineCharacters int
|
||||
MaxGitDiffFiles int
|
||||
VerbosePush bool
|
||||
VerbosePushDelay time.Duration
|
||||
GCArgs []string `ini:"GC_ARGS" delim:" "`
|
||||
EnableAutoGitWireProtocol bool
|
||||
Timeout struct {
|
||||
@@ -36,6 +38,8 @@ var (
|
||||
MaxGitDiffLines: 1000,
|
||||
MaxGitDiffLineCharacters: 5000,
|
||||
MaxGitDiffFiles: 100,
|
||||
VerbosePush: true,
|
||||
VerbosePushDelay: 5 * time.Second,
|
||||
GCArgs: []string{},
|
||||
EnableAutoGitWireProtocol: true,
|
||||
Timeout: struct {
|
||||
|
@@ -7,6 +7,7 @@ package setting
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -44,7 +45,7 @@ func GetQueueSettings(name string) QueueSettings {
|
||||
q := QueueSettings{}
|
||||
sec := Cfg.Section("queue." + name)
|
||||
// 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
|
||||
q.QueueName = name + Queue.QueueName
|
||||
for _, key := range sec.Keys() {
|
||||
@@ -55,8 +56,8 @@ func GetQueueSettings(name string) QueueSettings {
|
||||
q.QueueName = key.MustString(q.QueueName)
|
||||
}
|
||||
}
|
||||
if !path.IsAbs(q.DataDir) {
|
||||
q.DataDir = path.Join(AppDataPath, q.DataDir)
|
||||
if !filepath.IsAbs(q.DataDir) {
|
||||
q.DataDir = filepath.Join(AppDataPath, q.DataDir)
|
||||
}
|
||||
sec.Key("DATADIR").SetValue(q.DataDir)
|
||||
// The rest are...
|
||||
@@ -82,8 +83,8 @@ func GetQueueSettings(name string) QueueSettings {
|
||||
func NewQueueService() {
|
||||
sec := Cfg.Section("queue")
|
||||
Queue.DataDir = sec.Key("DATADIR").MustString("queues/")
|
||||
if !path.IsAbs(Queue.DataDir) {
|
||||
Queue.DataDir = path.Join(AppDataPath, Queue.DataDir)
|
||||
if !filepath.IsAbs(Queue.DataDir) {
|
||||
Queue.DataDir = filepath.Join(AppDataPath, Queue.DataDir)
|
||||
}
|
||||
Queue.Length = sec.Key("LENGTH").MustInt(20)
|
||||
Queue.BatchLength = sec.Key("BATCH_LENGTH").MustInt(20)
|
||||
|
@@ -554,6 +554,12 @@ func NewContext() {
|
||||
Protocol = HTTPS
|
||||
CertFile = sec.Key("CERT_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":
|
||||
Protocol = FCGI
|
||||
case "fcgi+unix":
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package structs // import "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
import (
|
||||
"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 {
|
||||
ID int64 `json:"id"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Index int64 `json:"number"`
|
||||
Poster *User `json:"user"`
|
||||
OriginalAuthor string `json:"original_author"`
|
||||
|
@@ -82,6 +82,7 @@ func (q *UniqueQueue) AddFunc(id interface{}, fn func()) {
|
||||
idStr := com.ToStr(id)
|
||||
q.table.lock.Lock()
|
||||
if _, ok := q.table.pool[idStr]; ok {
|
||||
q.table.lock.Unlock()
|
||||
return
|
||||
}
|
||||
q.table.pool[idStr] = struct{}{}
|
||||
|
@@ -7,6 +7,8 @@ package util
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
// urlSafeError wraps an error whose message may contain a sensitive URL
|
||||
@@ -36,6 +38,7 @@ func SanitizeMessage(message, unsanitizedURL string) string {
|
||||
func SanitizeURLCredentials(unsanitizedURL string, usePlaceholder bool) string {
|
||||
u, err := url.Parse(unsanitizedURL)
|
||||
if err != nil {
|
||||
log.Error("parse url %s failed: %v", unsanitizedURL, err)
|
||||
// don't log the error, since it might contain unsanitized URL.
|
||||
return "(unparsable url)"
|
||||
}
|
||||
|
25
modules/util/sanitize_test.go
Normal file
25
modules/util/sanitize_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSanitizeURLCredentials(t *testing.T) {
|
||||
var kases = map[string]string{
|
||||
"https://github.com/go-gitea/test_repo.git": "https://github.com/go-gitea/test_repo.git",
|
||||
"https://mytoken@github.com/go-gitea/test_repo.git": "https://github.com/go-gitea/test_repo.git",
|
||||
"http://github.com/go-gitea/test_repo.git": "http://github.com/go-gitea/test_repo.git",
|
||||
"/test/repos/repo1": "/test/repos/repo1",
|
||||
"git@github.com:go-gitea/test_repo.git": "(unparsable url)",
|
||||
}
|
||||
|
||||
for source, value := range kases {
|
||||
assert.EqualValues(t, value, SanitizeURLCredentials(source, false))
|
||||
}
|
||||
}
|
@@ -142,7 +142,7 @@ func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) {
|
||||
Title: issueTitle,
|
||||
HideAvatar: "0",
|
||||
SingleTitle: "view issue",
|
||||
SingleURL: p.Issue.URL,
|
||||
SingleURL: p.Issue.HTMLURL,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
@@ -236,7 +236,7 @@ func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPa
|
||||
{
|
||||
Title: text,
|
||||
Description: attachmentText,
|
||||
URL: p.Issue.URL,
|
||||
URL: p.Issue.HTMLURL,
|
||||
Color: color,
|
||||
Author: DiscordEmbedAuthor{
|
||||
Name: p.Sender.UserName,
|
||||
|
@@ -299,7 +299,7 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) {
|
||||
Targets: []MSTeamsActionTarget{
|
||||
{
|
||||
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{{
|
||||
Color: fmt.Sprintf("%x", color),
|
||||
Title: issueTitle,
|
||||
TitleLink: p.Issue.URL,
|
||||
TitleLink: p.Issue.HTMLURL,
|
||||
Text: attachmentText,
|
||||
}}
|
||||
}
|
||||
@@ -232,8 +232,10 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
|
||||
Username: slack.Username,
|
||||
IconURL: slack.IconURL,
|
||||
Attachments: []SlackAttachment{{
|
||||
Color: slack.Color,
|
||||
Text: attachmentText,
|
||||
Color: slack.Color,
|
||||
Title: p.Repo.HTMLURL,
|
||||
TitleLink: p.Repo.HTMLURL,
|
||||
Text: attachmentText,
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
@@ -289,12 +291,11 @@ func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackM
|
||||
func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||
senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
||||
var text, title, attachmentText string
|
||||
var text string
|
||||
|
||||
switch p.Action {
|
||||
case api.HookRepoCreated:
|
||||
text = fmt.Sprintf("[%s] Repository created by %s", repoLink, senderLink)
|
||||
title = p.Repository.HTMLURL
|
||||
case api.HookRepoDeleted:
|
||||
text = fmt.Sprintf("[%s] Repository deleted by %s", repoLink, senderLink)
|
||||
}
|
||||
@@ -304,12 +305,6 @@ func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*Sla
|
||||
Text: text,
|
||||
Username: slack.Username,
|
||||
IconURL: slack.IconURL,
|
||||
Attachments: []SlackAttachment{{
|
||||
Color: slack.Color,
|
||||
Title: title,
|
||||
TitleLink: title,
|
||||
Text: attachmentText,
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@@ -148,6 +148,25 @@ func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload,
|
||||
}, 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) {
|
||||
var title string
|
||||
switch p.Action {
|
||||
@@ -192,6 +211,8 @@ func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string
|
||||
return getTelegramPushPayload(p.(*api.PushPayload))
|
||||
case models.HookEventPullRequest:
|
||||
return getTelegramPullRequestPayload(p.(*api.PullRequestPayload))
|
||||
case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment:
|
||||
return getTelegramPullRequestApprovalPayload(p.(*api.PullRequestPayload), event)
|
||||
case models.HookEventRepository:
|
||||
return getTelegramRepositoryPayload(p.(*api.RepositoryPayload))
|
||||
case models.HookEventRelease:
|
||||
|
@@ -2035,4 +2035,3 @@ error.probable_bad_default_signature=VAROVÁNÍ! Ačkoli výchozí klíč má to
|
||||
[units]
|
||||
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.
|
||||
|
||||
|
@@ -606,7 +606,7 @@ clone_helper=Benötigst du Hilfe beim Klonen? Öffne die <a target="_blank" rel=
|
||||
fork_repo=Repository forken
|
||||
fork_from=Fork von
|
||||
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_from=Erstelle aus
|
||||
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_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_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.rebase_merge_pull_request=Rebase und Mergen
|
||||
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_users=Freigeschaltete Reviewer:
|
||||
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.delete_protected_branch=Schutz deaktivieren
|
||||
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.activated=Aktiviert
|
||||
users.admin=Administrator
|
||||
users.restricted=Eingeschränkt
|
||||
users.repos=Repositories
|
||||
users.created=Registriert am
|
||||
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.prohibit_login=Anmelden deaktivieren
|
||||
users.is_admin=Ist Administrator
|
||||
users.is_restricted=Ist eingeschränkt
|
||||
users.allow_git_hook=Darf „Git Hooks“ erstellen
|
||||
users.allow_import_local=Darf lokale Repositories importieren
|
||||
users.allow_create_organization=Darf Organisationen erstellen
|
||||
@@ -2025,8 +2031,47 @@ monitor.execute_time=Ausführungszeit
|
||||
monitor.process.cancel=Prozess abbrechen
|
||||
monitor.process.cancel_desc=Abbrechen eines Prozesses kann Datenverlust verursachen
|
||||
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.view_detail_header=Meldungsdetails ansehen
|
||||
@@ -2120,4 +2165,3 @@ error.probable_bad_default_signature=WARNHINWEIS! Obwohl der Standardschlüssel
|
||||
[units]
|
||||
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.
|
||||
|
||||
|
@@ -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_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_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.rebase_merge_pull_request = Rebase and Merge
|
||||
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_users = Whitelisted reviewers:
|
||||
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.delete_protected_branch = Disable protection
|
||||
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.activated = Activated
|
||||
users.admin = Admin
|
||||
users.restricted = Restricted
|
||||
users.repos = Repos
|
||||
users.created = Created
|
||||
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.prohibit_login = Disable Sign-In
|
||||
users.is_admin = Is Administrator
|
||||
users.is_restricted = Is Restricted
|
||||
users.allow_git_hook = May Create Git Hooks
|
||||
users.allow_import_local = May Import Local Repositories
|
||||
users.allow_create_organization = May Create Organizations
|
||||
@@ -1820,6 +1826,7 @@ auths.attribute_surname = Surname Attribute
|
||||
auths.attribute_mail = Email Attribute
|
||||
auths.attribute_ssh_public_key = Public SSH Key Attribute
|
||||
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.search_page_size = Page Size
|
||||
auths.filter = User Filter
|
||||
|
@@ -2109,4 +2109,3 @@ error.probable_bad_default_signature=¡ADVERTENCIA! ¡La clave por defecto tiene
|
||||
[units]
|
||||
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.
|
||||
|
||||
|
@@ -2120,4 +2120,3 @@ error.probable_bad_default_signature=هشدار! اگرچه اینجا یک کل
|
||||
[units]
|
||||
error.no_unit_allowed_repo=شما اجازه دسترسی به هیچ قسمت از این مخزن را ندارید.
|
||||
error.unit_not_allowed=شما اجازه دسترسی به این قسمت مخزن را ندارید.
|
||||
|
||||
|
@@ -2096,4 +2096,3 @@ error.probable_bad_default_signature=AVERTISSEMENT ! Bien que la clé par défau
|
||||
[units]
|
||||
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.
|
||||
|
||||
|
@@ -10,6 +10,7 @@ link_account=Tautan Akun
|
||||
register=Daftar
|
||||
website=Situs Web
|
||||
version=Versi
|
||||
powered_by=Diberdayakan oleh %s
|
||||
page=Halaman
|
||||
template=Contoh
|
||||
language=Bahasa
|
||||
@@ -29,8 +30,16 @@ twofa_scratch=Kode Awal Dua Faktor
|
||||
passcode=Kode Akses
|
||||
|
||||
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_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
|
||||
|
||||
repository=Repositori
|
||||
@@ -58,25 +67,51 @@ forks=Garpu
|
||||
activities=Aktivitas
|
||||
pull_requests=Tarik Permintaan
|
||||
issues=Masalah
|
||||
milestones=Tonggak
|
||||
|
||||
cancel=Batal
|
||||
add=Tambah
|
||||
add_all=Tambah Semua
|
||||
remove=Buang
|
||||
remove_all=Buang Semua
|
||||
|
||||
write=Tulis
|
||||
preview=Pratinjau
|
||||
loading=Memuat…
|
||||
|
||||
[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=Pemasangan
|
||||
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_type=Tipe Basis Data
|
||||
host=Host
|
||||
user=Nama Pengguna
|
||||
password=Kata Sandi
|
||||
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
|
||||
charset=Jenis karakter
|
||||
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.
|
||||
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
|
||||
app_name=Judul Situs
|
||||
@@ -111,13 +146,20 @@ server_service_title=Server dan Pengaturan Layanan Pihak Ketiga
|
||||
offline_mode=Aktifkan Mode Lokal
|
||||
offline_mode_popup=Non-aktifkan jaringan pengiriman konten dari pihak ketiga dan layani semua sumber daya secara lokal.
|
||||
disable_gravatar=Non-aktifkan Gravatar
|
||||
federated_avatar_lookup=Aktifkan Avatar Terfederasi
|
||||
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_popup=Aktifkan masuk pengguna lewat OpenID.
|
||||
openid_signup=Aktifkan Pendaftaran OpenID
|
||||
openid_signup_popup=Aktifkan pendaftaran berdasarkan OpenID.
|
||||
enable_captcha=Aktifkan CAPTCHA
|
||||
enable_captcha_popup=Membutukan CAPTCHA untuk pendaftaran.
|
||||
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_name=Nama Pengguna Admin
|
||||
admin_password=Kata sandi
|
||||
@@ -127,7 +169,15 @@ install_btn_confirm=Memasang Gitea
|
||||
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').
|
||||
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
|
||||
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]
|
||||
uname_holder=Nama Pengguna atau Alamat Surel
|
||||
@@ -161,36 +211,50 @@ social_register_helper_msg=Sudah memiliki akun? Hubungkan sekarang!
|
||||
remember_me=Ingat Saya
|
||||
forgot_password_title=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.
|
||||
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.
|
||||
resend_mail=Klik di sini untuk mengirim ulang surel aktivasi anda
|
||||
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
|
||||
scratch_code=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_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.
|
||||
login_openid=OpenID
|
||||
openid_connect_submit=Sambungkan
|
||||
openid_connect_title=Sambungkan ke akun yang sudah ada
|
||||
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]
|
||||
activate_account=Silakan aktifkan akun anda
|
||||
activate_email=Verifikasi alamat surel anda
|
||||
reset_password=Pulihkan akun Anda
|
||||
register_success=Pendaftaran berhasil
|
||||
register_notify=Selamat Datang di Gitea
|
||||
|
||||
[modal]
|
||||
yes=Ya
|
||||
no=Tidak
|
||||
modify=Perbarui
|
||||
|
||||
[form]
|
||||
UserName=Nama Pengguna
|
||||
RepoName=Nama repositori
|
||||
Email=Alamat surel
|
||||
Password=Kata Sandi
|
||||
Retype=Ketik Ulang Kata Sandi
|
||||
SSHTitle=Nama kunci SSH
|
||||
HttpsUrl=HTTPS URL
|
||||
PayloadUrl=Muatan URL
|
||||
@@ -205,6 +269,7 @@ CommitChoice=Pilihan Commit
|
||||
TreeName=Jalur berkas
|
||||
Content=Konten
|
||||
|
||||
SSPISeparatorReplacement=Pemisah
|
||||
|
||||
require_error=` tidak boleh kosong.`
|
||||
size_error=` harus berukuran %s.`
|
||||
@@ -214,53 +279,100 @@ email_error=` bukan alamat surel yang valid. `
|
||||
url_error=` bukan URL yang valid.`
|
||||
include_error=` harus mengandung substring '%s'.`
|
||||
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.
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
[user]
|
||||
change_avatar=Ganti avatar anda…
|
||||
join_on=Telah bergabung di
|
||||
repositories=Repositori
|
||||
activity=Aktivitas Publik
|
||||
followers=Pengikut
|
||||
starred=Repositori Terbintang
|
||||
following=Mengikuti
|
||||
follow=Ikuti
|
||||
unfollow=Berhenti Mengikuti
|
||||
heatmap.loading=Memuat Peta Panas…
|
||||
user_bio=Biografi
|
||||
|
||||
form.name_reserved=Nama pengguna '%s' dicadangkan.
|
||||
form.name_pattern_not_allowed=Pola '%s' tidak diperbolehkan dalam nama pengguna.
|
||||
|
||||
[settings]
|
||||
profile=Profil
|
||||
account=Akun
|
||||
password=Kata Sandi
|
||||
security=Keamanan
|
||||
avatar=Avatar
|
||||
ssh_gpg_keys=Kunci SSH / GPG
|
||||
social=Akun Sosial
|
||||
applications=Aplikasi
|
||||
orgs=Kelola organisasi
|
||||
repos=Repositori
|
||||
delete=Hapus Akun
|
||||
twofa=Otentikasi Dua-Faktor
|
||||
account_link=Akun Tertaut
|
||||
organization=Organisasi
|
||||
uid=Uid
|
||||
u2f=Kunci keamanan
|
||||
|
||||
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
|
||||
website=Situs Web
|
||||
location=Lokasi
|
||||
update_theme=Perbarui Tema
|
||||
update_profile=Perbarui Profil
|
||||
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
|
||||
cancel=Batalkan
|
||||
language=Bahasa
|
||||
ui=Tema
|
||||
|
||||
lookup_avatar_by_mail=Cari Avatar melalui Alamat Email
|
||||
federated_avatar_lookup=Aktifkan Pencarian Avatar Representasi
|
||||
enable_custom_avatar=Gunakan Avatar Pilihan
|
||||
choose_new_avatar=Pilih avatar baru
|
||||
update_avatar=Perbarui Avatar
|
||||
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
|
||||
new_password=Kata Sandi Baru
|
||||
retype_new_password=Ketik Ulang Kata Sandi Baru
|
||||
password_incorrect=Kata sandi saat ini salah.
|
||||
|
||||
emails=Alamat Surel
|
||||
email_desc=Alamat surel utama anda akan digunakan untuk notifikasi dan operasi lainnya.
|
||||
@@ -318,6 +430,7 @@ confirm_delete_account=Konfirmasi Penghapusan
|
||||
owner=Pemilik
|
||||
repo_name=Nama Repositori
|
||||
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_from=Cabang Dari
|
||||
repo_desc=Deskripsi
|
||||
@@ -508,6 +621,7 @@ pulls.new=Permintaan Tarik Baru
|
||||
pulls.filter_branch=Penyaringan cabang
|
||||
pulls.no_results=Hasil tidak ditemukan.
|
||||
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.tab_conversation=Percakapan
|
||||
pulls.tab_commits=Melakukan
|
||||
@@ -625,6 +739,7 @@ settings.webhook.request=Permintaan
|
||||
settings.webhook.response=Tanggapan
|
||||
settings.webhook.headers=Tajuk
|
||||
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_name=Nama Hook
|
||||
settings.githook_content=Konten Hook
|
||||
|
@@ -1062,6 +1062,8 @@ pulls.no_merge_desc=リポジトリのマージオプションがすべて無効
|
||||
pulls.no_merge_helper=リポジトリ設定でマージを有効にするか、手動でマージしてください。
|
||||
pulls.no_merge_wip=このプルリクエストはWork in Progressとマークされているため、マージすることはできません。
|
||||
pulls.no_merge_status_check=すべての必要なステータスチェックが成功していないため、このプルリクエストはマージできません。
|
||||
pulls.no_merge_not_ready=このプルリクエストはマージする準備ができていません。 レビュー状況とステータスチェックを確認してください。
|
||||
pulls.no_merge_access=このプルリクエストをマージする権限がありません。
|
||||
pulls.merge_pull_request=プルリクエストをマージ
|
||||
pulls.rebase_merge_pull_request=リベースしてマージ
|
||||
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_users=ホワイトリストに含めるレビューア:
|
||||
settings.protect_approvals_whitelist_teams=ホワイトリストに含めるレビューチーム:
|
||||
settings.dismiss_stale_approvals=古くなった承認を取り消す
|
||||
settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える新たなコミットがブランチにプッシュされた場合、以前の承認を取り消します。
|
||||
settings.add_protected_branch=保護を有効にする
|
||||
settings.delete_protected_branch=保護を無効にする
|
||||
settings.update_protect_branch_success=ブランチ '%s' の保護を更新しました。
|
||||
@@ -1747,6 +1751,7 @@ users.new_account=ユーザーアカウントを作成
|
||||
users.name=ユーザー名
|
||||
users.activated=アクティベート済み
|
||||
users.admin=管理者
|
||||
users.restricted=制限あり
|
||||
users.repos=リポジトリ
|
||||
users.created=作成日
|
||||
users.last_login=前回のサインイン
|
||||
@@ -1765,6 +1770,7 @@ users.max_repo_creation_desc=( -1を設定するとデフォルトの制限が
|
||||
users.is_activated=ユーザーアカウントはアクティベート済み
|
||||
users.prohibit_login=サインイン無効
|
||||
users.is_admin=管理者
|
||||
users.is_restricted=制限あり
|
||||
users.allow_git_hook=Gitフックを作成可
|
||||
users.allow_import_local=ローカルリポジトリをインポート可
|
||||
users.allow_create_organization=組織を作成可
|
||||
@@ -2025,8 +2031,54 @@ monitor.execute_time=実行時間
|
||||
monitor.process.cancel=処理をキャンセル
|
||||
monitor.process.cancel_desc=処理をキャンセルするとデータが失われる可能性があります
|
||||
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.view_detail_header=通知の詳細を表示
|
||||
@@ -2120,4 +2172,3 @@ error.probable_bad_default_signature=警告! これはデフォルト鍵のIDで
|
||||
[units]
|
||||
error.no_unit_allowed_repo=このリポジトリのどのセクションにもアクセスが許可されていません。
|
||||
error.unit_not_allowed=このセクションへのアクセスが許可されていません。
|
||||
|
||||
|
@@ -3,9 +3,9 @@ dashboard=대시보드
|
||||
explore=탐색
|
||||
help=도움말
|
||||
sign_in=로그인
|
||||
sign_in_with=냐후 ㅑㅜ 쨔소
|
||||
sign_in_with=다음을 통해 로그인
|
||||
sign_out=로그아웃
|
||||
sign_up=ㄲㄷ햔ㅅㄷㄱ
|
||||
sign_up=가입하기
|
||||
link_account=계정 연결
|
||||
register=가입하기
|
||||
website=웹 사이트
|
||||
@@ -14,18 +14,18 @@ page=페이지
|
||||
template=템플릿
|
||||
language=언어
|
||||
notifications=알림
|
||||
create_new=ㅊㄱㄷㅁㅅㄷ...
|
||||
user_profile_and_more=ㅖ개랴ㅣㄷ 뭉 ㄴㄷㅅ샤ㅜㅎㄴ...
|
||||
create_new=생성하기
|
||||
user_profile_and_more=프로파일 및 설정
|
||||
signed_in_as=다음 사용자로 로그인됨
|
||||
enable_javascript=쏘ㅑㄴ ㅈ듀냣ㄷ 재간 ㅠㄷㅅㅅㄷㄱ 쟈소 ㅓㅁㅍㅁㄴㅊ갸ㅔㅅ.
|
||||
enable_javascript=이 웹사이트는 자바스크립트 활성화가 필요합니다.
|
||||
|
||||
username=사용자명
|
||||
email=뜨먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ
|
||||
email=이메일 주소
|
||||
password=비밀번호
|
||||
re_type=ㄲㄷ-쑈ㅔㄷ ㅖㅁㄴㄴ잭ㅇ
|
||||
captcha=ㅊ몠촘
|
||||
twofa=ㅆ재-ㄻㅊ색 며소두샻ㅁ샤ㅐㅜ
|
||||
twofa_scratch=ㅆ재-ㄻㅊ색 ㄴㅊㄱㅁㅅ초 챙ㄷ
|
||||
re_type=비밀번호 재입력
|
||||
captcha=보안 문자
|
||||
twofa=2단계 인증
|
||||
twofa_scratch=2단계 일회성 코드
|
||||
passcode=인증코드
|
||||
|
||||
u2f_insert_key=보안 키를 입력해주세요.
|
||||
@@ -50,12 +50,12 @@ new_mirror=새로운 미러
|
||||
new_fork=새 저장소 포크
|
||||
new_org=새로운 조직
|
||||
manage_org=조직 관리
|
||||
admin_panel=냣ㄷ ㅁ으ㅑㅜㅑㄴㅅㄱㅁ샤ㅐㅜ
|
||||
admin_panel=사이트 관리
|
||||
account_settings=계정 설정
|
||||
settings=설정
|
||||
your_profile=ㅖ개랴ㅣㄷ
|
||||
your_starred=ㄴㅅㅁㄱㄱㄷㅇ
|
||||
your_settings=ㄴㄷㅅ샤ㅜㅎㄴ
|
||||
your_profile=프로필
|
||||
your_starred=즐겨찾기
|
||||
your_settings=설정
|
||||
|
||||
all=전체
|
||||
sources=소스
|
||||
@@ -66,71 +66,75 @@ forks=포크
|
||||
activities=활동
|
||||
pull_requests=풀 리퀘스트
|
||||
issues=이슈들
|
||||
milestones=마일스톤
|
||||
|
||||
cancel=취소
|
||||
add=추가
|
||||
|
||||
write=쓰기
|
||||
preview=미리보기
|
||||
loading=불러오는 중...
|
||||
|
||||
[startpage]
|
||||
app_desc=편리한 설치형 Git 서비스
|
||||
license=오픈 소스
|
||||
|
||||
[install]
|
||||
install=설치
|
||||
title=ㅑㅜㅑ샤미 채ㅜ랴혁ㅁ샤ㅐㅜ
|
||||
title=초기 설정
|
||||
docker_helper=Gitea를 Docker에서 실행하려면 설정 전에 이 <a target="_blank" rel="noopener noreferrer" href="%s">문서</a>를 읽어보세요.
|
||||
requite_db_desc=Gitea를 실행하려면 MySQL, PostgreSQL, MSSQL 또는 SQLite3 중 하나가 필요합니다.
|
||||
db_title=데이터베이스 설정
|
||||
db_type=데이터베이스 유형
|
||||
host=호스트
|
||||
user=ㅕㄴㄷ구믇
|
||||
user=이름
|
||||
password=비밀번호
|
||||
db_name=데이터베이스 이름
|
||||
ssl_mode=ㄴ니
|
||||
ssl_mode=SSL
|
||||
charset=문자셋
|
||||
path=경로
|
||||
sqlite_helper=SQLite3 데이터베이스에 대한 파일 경로입니다.<br>Gitea를 서비스로 구동할 경우, 절대 경로를 입력해주십시오.
|
||||
err_empty_db_path=SQLite3 데이터베이스 경로는 필수 입력 값입니다.
|
||||
no_admin_and_disable_registration=ㅛㅐㅕ ㅊ무ㅜㅐㅅ 얀뮤ㅣㄷ ㅕㄴㄷㄱ ㄴ딜-ㄱㄷ햔ㅅㄱㅁ샤ㅐㅜ 쟈쇄ㅕㅅ ㅊㄱㄷㅁ샤ㅜㅎ 무 ㅁ으ㅑㅜㅑㄴㅅㄱㅁ색 ㅁㅊ채ㅕㅜㅅ.
|
||||
err_empty_admin_password=쏟 ㅁ으ㅑㅜㅑㄴㅅㄱㅁ색 ㅔㅁㄴㄴ잭ㅇ ㅊ무ㅜㅐㅅ ㅠㄷ 드ㅔ쇼.
|
||||
no_admin_and_disable_registration=관리자 계정을 만들지 않고 등록을 비활성화할 수 없습니다.
|
||||
err_empty_admin_password=관리자 비밀번호는 비어 있을 수 없습니다.
|
||||
err_empty_admin_email=관리자 이메일은 비어 있을 수 없습니다.
|
||||
err_admin_name_is_reserved=관리자 사용자 이름이 올바르지 않습니다, 제한된 사용자 이름입니다
|
||||
err_admin_name_is_invalid=관리자 사용자 이름이 올바르지 않습니다
|
||||
|
||||
general_title=ㅎ둗ㄱ미 ㄴㄷㅅ샤ㅜㅎㄴ
|
||||
app_name=냣ㄷ 쌰싣
|
||||
app_name_helper=ㅛㅐㅕ ㅊ무 둣ㄷㄱ ㅛㅐㅕㄱ 채ㅡㅔ무ㅛ ㅜ믇 ㅗㄷㄱㄷ.
|
||||
general_title=기본설정
|
||||
app_name=사이트 제목
|
||||
app_name_helper=회사이름을 넣으세요.
|
||||
repo_path=저장소 최상위 경로
|
||||
repo_path_helper=ㄲ드ㅐㅅㄷ 햣 ㄱ데ㅐ냐새갿ㄴ 쟈ㅣㅣ ㅠㄷ ㄴㅁㅍㄷㅇ 새 소ㅑㄴ 약ㄷㅊ새교.
|
||||
lfs_path=햣 ㅣㄹㄴ 깨ㅐㅅ ㅖㅁ소
|
||||
lfs_path_helper=랴ㅣㄷㄴ ㅅㄱㅁ찯ㅇ ㅠㅛ 햣 ㅣㄹㄴ 쟈ㅣㅣ ㅠㄷ ㄴ색ㄷㅇ ㅑㅜ 소ㅑㄴ 약ㄷㅊ새교. ㅣㄷㅁㅍㄷ 드ㅔ쇼 새 얀뮤ㅣㄷ.
|
||||
run_user=껴ㅜ ㅁㄴ ㅕㄴㄷ구믇
|
||||
run_user_helper=뚯ㄷㄱ 솓 ㅐㅔㄷㄱㅁ샤ㅜㅎ 뇬ㅅ드 ㅕㄴㄷ구믇 솜ㅅ 햣ㄷㅁ 겨ㅜㄴ ㅁㄴ. ㅜㅐㅅㄷ 솜ㅅ 소ㅑㄴ ㅕㄴㄷㄱ ㅡㅕㄴㅅ ㅗㅁㅍㄷ ㅁㅊㅊㄷㄴㄴ 새 솓 ㄱ데ㅐ냐새교 개ㅐㅅ ㅔㅁ소.
|
||||
domain=ㄴ노 ㄴㄷㄱㅍㄷㄱ 애ㅡ먀ㅜ
|
||||
domain_helper=애ㅡ먀ㅜ ㅐㄱ ㅙㄴㅅ ㅁㅇㅇㄱㄷㄴㄴ 랙 노ㅗ 치ㅐㅜㄷ ㅕ낀.
|
||||
repo_path_helper=Git 원격 저장소는 이 디렉터리에 저장 됩니다.
|
||||
lfs_path=Git LFS 루트 경로
|
||||
lfs_path_helper=Git LFS에 저장된 파일들은 이 디렉토리에 저장됩니다. LFS를 사용하지 않는다면 빈칸으로 남겨주세요.
|
||||
run_user=실행 사용자명
|
||||
run_user_helper=Gitea 를 실행할 시스템 사용자명을 넣으세요. 시스템 사용자는 레포지토리 루트 경로에 대한 권한이 필요합니다.
|
||||
domain=SSH 서버 도메인
|
||||
domain_helper=SSH clone URL 에 대한 도메인 또는 호스트 주소
|
||||
ssh_port=ㄴ노 ㄴㄷㄱㅍㄷㄱ ㅖㅐㄳ
|
||||
ssh_port_helper=ㅖㅐㄳ ㅜㅕㅡㅠㄷㄱ ㅛㅐㅕㄱ 노ㅗ ㄴㄷㄱㅍㄷㄱ ㅣㅑㄴㅅ둔 ㅐㅜ. ㅣㄷㅁㅍㄷ 드ㅔ쇼 새 얀뮤ㅣㄷ.
|
||||
http_port=햣ㄷㅁ ㅗㅆ쎄 ㅣㅑㄴㅅ두 ㅖㅐㄳ
|
||||
http_port_helper=ㅖㅐㄳ ㅜㅕㅡㅠㄷㄱ 솓 햣ㄷㅁㄴ ㅈ듀 ㄴㄷㄱㅍㄷㄱ 쟈ㅣㅣ ㅣㅑㄴㅅ두 ㅐㅜ.
|
||||
app_url=햣ㄷㅁ ㅠㅁㄴㄷ ㅕ끼
|
||||
app_url_helper=ㅠㅁㄴㄷ ㅁㅇㅇㄱㄷㄴㄴ 랙 ㅗㅆ쎼(ㄴ) 치ㅐㅜㄷ ㅕ낀 뭉 드먀ㅣ ㅜㅐ샤럋ㅁ샤ㅐㅜㄴ.
|
||||
ssh_port_helper=SSH 서버가 실행되고 있는 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
|
||||
http_port=Gitea HTTP 수신 포트
|
||||
http_port_helper=Gitea 웹서버가 수신할 포트 번호
|
||||
app_url=Gitea 기본 URL
|
||||
app_url_helper=HTTP(S) clone URL 및 이메일 알림 기본 주소
|
||||
log_root_path=로그 경로
|
||||
log_root_path_helper=ㅣㅐㅎ 랴ㅣㄷㄴ 쟈ㅣㅣ ㅠㄷ ㅈ걋ㅅ두 새 소ㅑㄴ 약ㄷㅊ새교.
|
||||
log_root_path_helper=로그파일은 이 디렉토리에 저장됩니다.
|
||||
|
||||
optional_title=추가설정
|
||||
email_title=뜨먀ㅣ ㄴㄷㅅ샤ㅜㅎㄴ
|
||||
email_title=이메일 설정
|
||||
smtp_host=SMTP 호스트
|
||||
smtp_from=ㄴ둥 뜨먀ㅣ ㅁㄴ
|
||||
smtp_from_helper=뜨먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ 햣ㄷㅁ 쟈ㅣㅣ ㅕㄴㄷ. 뚯ㄷㄱ ㅁ ㅔㅣ먀ㅜ 드먀ㅣ ㅁㅇㅇㄱㄷㄴㄴ ㅐㄱ ㅕㄴㄷ 솓 "ㅜ믇" <드먀ㅣ@ㄷㅌ므ㅔㅣㄷ.kr> 래금ㅅ.
|
||||
mailer_user=느쎼 ㅕㄴㄷ구믇
|
||||
mailer_password=느쎼 ㅖㅁㄴㄴ잭ㅇ
|
||||
register_confirm=ㄲㄷ벼ㅑㄱㄷ 뜨먀ㅣ 채ㅜ랴금샤ㅐㅜ 새 ㄲㄷ햔ㅅㄷㄱ
|
||||
mail_notify=뚜뮤ㅣㄷ 뜨먀ㅣ ㅜㅐ샤럋ㅁ샤ㅐㅜㄴ
|
||||
server_service_title=ㄴㄷㄱㅍㄷㄱ 뭉 쏘ㅑㄱㅇ-ㅖㅁㄱ쇼 ㄴㄷㄱ퍛ㄷ ㄴㄷㅅ샤ㅜㅎㄴ
|
||||
offline_mode=뚜뮤ㅣㄷ ㅣㅐㅊ미 ㅡㅐㅇㄷ
|
||||
offline_mode_popup=얀뮤ㅣㄷ 소ㅑㄱㅇ-ㅔㅁㄱ쇼 채ㅜㅅ둣 ㅇ디ㅑㅍㄷ교 ㅜㄷㅅ재간 뭉 ㄴㄷㄱㅍㄷ 미ㅣ ㄱㄷ내ㅕㄱㅊㄷㄴ ㅣㅐㅊ미ㅣㅛ.
|
||||
disable_gravatar=얀뮤ㅣㄷ ㅎㄱㅁㅍㅍㅁㅅㅁㄱ
|
||||
disable_gravatar_popup=얀뮤ㅣㄷ ㅎㄱㅁㅍㅁㅅㅁㄱ 뭉 소ㅑㄱㅇ-ㅔㅁㄱ쇼 ㅁㅍㅁㄴㅅㅁㄱ 내ㅕㄱㅊㄷㄴ. ㅁ ㅇㄷㄹ며ㅣㅅ ㅁㅍㅁㅅㅁㄱ 쟈ㅣㅣ ㅠㄷ ㅕㄴㄷㅇ ㅕㅟㄷㄴㄴ ㅁ ㅕㄴㄷㄱ ㅣㅐㅊ미ㅣㅛ ㅕㅔㅣㅐㅁㅇㄴ 무 ㅁㅍㅁㅅㅁㄱ.
|
||||
smtp_from=이메일 발신인
|
||||
smtp_from_helper=Gitea 가 사용할 이메일 주소. 이메일 주소 또는 "이름" <email@example.com> 형식으로 입력하세요.
|
||||
mailer_user=SMTP 사용자이름
|
||||
mailer_password=SMTP 비밀번호
|
||||
register_confirm=가입시 이메일 확인 필수
|
||||
mail_notify=이메일 알림 켜기
|
||||
server_service_title=서버 및 기타 서비스 설정
|
||||
offline_mode=로컬 모드 켜기
|
||||
offline_mode_popup=타사 콘텐츠 전송 네트워크를 사용하지 않도록 설정하고 모든 리소스를 로컬로 제공하십시오.
|
||||
disable_gravatar=Gravatar 사용안함
|
||||
disable_gravatar_popup=Gravatar 및 타사 아바타 소스를 사용하지 않도록 설정합니다. 사용자가 로컬로 아바타를 업로드하지 않는 한 기본 아바타가 사용됩니다.
|
||||
federated_avatar_lookup=아바타 연동 사용여부
|
||||
federated_avatar_lookup_popup=libravatar 기반 오픈소스 서비스 사용 목적으로 연합 아바타 조회를 허용하기
|
||||
disable_registration=사용자 등록 비활성화
|
||||
@@ -509,6 +513,8 @@ confirm_delete_account=삭제 승인
|
||||
delete_account_title=사용자 계정 삭제
|
||||
delete_account_desc=이 계정을 정말로 삭제하시겠습니까?
|
||||
|
||||
email_notifications.enable=이메일 알림 켜기
|
||||
email_notifications.disable=이메일 알림 끄기
|
||||
|
||||
[repo]
|
||||
owner=소유자
|
||||
@@ -879,6 +885,7 @@ milestones.filter_sort.most_complete=완료율이 높은 순
|
||||
milestones.filter_sort.most_issues=이슈 많은 순
|
||||
milestones.filter_sort.least_issues=이슈 적은 순
|
||||
|
||||
|
||||
ext_wiki=외부 위키
|
||||
ext_wiki.desc=외부 위키에 연결하기.
|
||||
|
||||
@@ -960,6 +967,8 @@ settings.basic_settings=기본 설정
|
||||
settings.mirror_settings=미러 설정
|
||||
settings.sync_mirror=지금 동기화
|
||||
settings.mirror_sync_in_progress=미러 동기화 진행중입니다. 잠시 후 다시 확인해주십시오.
|
||||
settings.email_notifications.enable=이메일 알림 켜기
|
||||
settings.email_notifications.disable=이메일 알림 끄기
|
||||
settings.site=웹 사이트
|
||||
settings.update_settings=설정 저장
|
||||
settings.advanced_settings=고급 설정
|
||||
@@ -1080,6 +1089,8 @@ settings.protected_branch_can_push_yes=푸시할 수 있습니다.
|
||||
settings.protected_branch_can_push_no=푸시할 수 없습니다.
|
||||
settings.branch_protection='<b>%s</b>' 브랜치 보호
|
||||
settings.protect_this_branch=브랜치 보호 활성화
|
||||
settings.protect_disable_push=푸시 끄기
|
||||
settings.protect_enable_push=푸시 켜기
|
||||
settings.protect_whitelist_search_users=사용자 찾기...
|
||||
settings.protect_whitelist_search_teams=팀 찾기...
|
||||
settings.protect_merge_whitelist_committers=머지 화이트리스트 활성화
|
||||
@@ -1511,6 +1522,7 @@ monitor.process=실행중인 프로세스들
|
||||
monitor.desc=설명
|
||||
monitor.start=시작 시간
|
||||
monitor.execute_time=실행 시간
|
||||
monitor.queue.configuration=초기 설정
|
||||
|
||||
|
||||
|
||||
|
@@ -1596,7 +1596,7 @@ settings.full_name=Pilns vārds, uzvārds
|
||||
settings.website=Mājas lapa
|
||||
settings.location=Atrašanās vieta
|
||||
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.public=Publiska
|
||||
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_desc=Procesa atcelšana var radīt datu zaudējumus
|
||||
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.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]
|
||||
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.
|
||||
|
||||
|
@@ -2100,4 +2100,3 @@ error.probable_bad_default_signature=OSTRZEŻENIE! Pomimo, że domyślny klucz p
|
||||
[units]
|
||||
error.no_unit_allowed_repo=Nie masz uprawnień do żadnej sekcji tego 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_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_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.rebase_merge_pull_request=Aplicar Rebase e Merge
|
||||
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_users=Usuários 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.delete_protected_branch=Desabilitar proteção
|
||||
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.activated=Ativado
|
||||
users.admin=Administrador
|
||||
users.restricted=Restrito
|
||||
users.repos=Repositórios
|
||||
users.created=Criado
|
||||
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.prohibit_login=Desabilitar acesso
|
||||
users.is_admin=É administrador
|
||||
users.is_restricted=Está restrito
|
||||
users.allow_git_hook=Pode criar hooks Git
|
||||
users.allow_import_local=Pode importar repositórios locais
|
||||
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]
|
||||
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.
|
||||
|
||||
|
@@ -2113,4 +2113,3 @@ error.probable_bad_default_signature=UYARI! Varsayılan anahtarın bu kimliği o
|
||||
[units]
|
||||
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.
|
||||
|
||||
|
@@ -2115,4 +2115,3 @@ error.probable_bad_default_signature=УВАГА! Хоча типовий клю
|
||||
[units]
|
||||
error.no_unit_allowed_repo=У вас немає доступу до жодного розділу цього репозитория.
|
||||
error.unit_not_allowed=У вас немає доступу до жодного розділу цього репозитория.
|
||||
|
||||
|
@@ -2166,4 +2166,3 @@ error.probable_bad_default_signature=警告!虽然默认密钥拥有此ID,
|
||||
[units]
|
||||
error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。
|
||||
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
|
||||
*
|
||||
*/
|
||||
@import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin&display=swap');
|
||||
/*!
|
||||
* # Fomantic-UI - Reset
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
|
@@ -7,8 +7,7 @@
|
||||
* Released under the MIT license
|
||||
* 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
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
|
@@ -130,6 +130,7 @@ func parseLDAPConfig(form auth.AuthenticationForm) *models.LDAPConfig {
|
||||
SearchPageSize: pageSize,
|
||||
Filter: form.Filter,
|
||||
AdminFilter: form.AdminFilter,
|
||||
AllowDeactivateAll: form.AllowDeactivateAll,
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ package admin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
@@ -226,6 +227,11 @@ func DeleteUser(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if u.IsOrganization() {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("%s is an organization not a user", u.Name))
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.DeleteUser(u); err != nil {
|
||||
if models.IsErrUserOwnRepos(err) ||
|
||||
models.IsErrUserHasOrgs(err) {
|
||||
|
@@ -51,6 +51,10 @@ func SearchIssues(ctx *context.APIContext) {
|
||||
// description: repository to prioritize in the results
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: type
|
||||
// in: query
|
||||
// description: filter by type (issues / pulls) if set
|
||||
// type: string
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/IssueList"
|
||||
@@ -67,20 +71,24 @@ func SearchIssues(ctx *context.APIContext) {
|
||||
|
||||
// find repos user can access (for issue search)
|
||||
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
|
||||
for page := 1; ; page++ {
|
||||
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Page: page,
|
||||
PageSize: 15,
|
||||
Private: true,
|
||||
Keyword: "",
|
||||
OwnerID: ctx.User.ID,
|
||||
TopicOnly: false,
|
||||
Collaborate: util.OptionalBoolNone,
|
||||
UserIsAdmin: ctx.IsUserSiteAdmin(),
|
||||
UserID: ctx.User.ID,
|
||||
OrderBy: models.SearchOrderByRecentUpdated,
|
||||
})
|
||||
opts.Page = page
|
||||
repos, count, err := models.SearchRepositoryByName(opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
|
||||
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
|
||||
// This would otherwise return all issues if no issues were found by the search.
|
||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||
@@ -137,6 +155,7 @@ func SearchIssues(ctx *context.APIContext) {
|
||||
LabelIDs: labelIDs,
|
||||
SortType: "priorityrepo",
|
||||
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
|
||||
IsPull: isPull,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -188,6 +207,10 @@ func ListIssues(ctx *context.APIContext) {
|
||||
// in: query
|
||||
// description: search string
|
||||
// type: string
|
||||
// - name: type
|
||||
// in: query
|
||||
// description: filter by type (issues / pulls) if set
|
||||
// type: string
|
||||
// responses:
|
||||
// "200":
|
||||
// "$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
|
||||
// This would otherwise return all issues if no issues were found by the search.
|
||||
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
|
||||
@@ -233,6 +266,7 @@ func ListIssues(ctx *context.APIContext) {
|
||||
IsClosed: isClosed,
|
||||
IssueIDs: issueIDs,
|
||||
LabelIDs: labelIDs,
|
||||
IsPull: isPull,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -457,6 +491,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
||||
return
|
||||
}
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
canWrite := ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
||||
|
||||
err = issue.LoadAttributes()
|
||||
if err != nil {
|
||||
@@ -464,7 +499,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
||||
return
|
||||
}
|
||||
|
||||
if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
||||
if !issue.IsPoster(ctx.User.ID) && !canWrite {
|
||||
ctx.Status(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
@@ -477,7 +512,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
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.
|
||||
// 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 := ""
|
||||
if form.Assignee != nil {
|
||||
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 {
|
||||
oldMilestoneID := issue.MilestoneID
|
||||
issue.MilestoneID = *form.Milestone
|
||||
@@ -600,7 +635,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) {
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||
ctx.Error(http.StatusForbidden, "", "Not repo writer")
|
||||
return
|
||||
}
|
||||
|
@@ -190,7 +190,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
|
||||
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")))
|
||||
return
|
||||
}
|
||||
|
@@ -179,7 +179,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
|
||||
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"))
|
||||
return
|
||||
}
|
||||
@@ -380,7 +380,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
|
||||
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"))
|
||||
return
|
||||
}
|
||||
|
@@ -170,7 +170,7 @@ func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.I
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
|
||||
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||
ctx.Status(http.StatusForbidden)
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -194,7 +194,12 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
|
||||
milestone.DeadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
|
||||
}
|
||||
|
||||
if err := models.UpdateMilestone(milestone); err != nil {
|
||||
var oldIsClosed = milestone.IsClosed
|
||||
if form.State != nil {
|
||||
milestone.IsClosed = *form.State == string(api.StateClosed)
|
||||
}
|
||||
|
||||
if err := models.UpdateMilestone(milestone, oldIsClosed); err != nil {
|
||||
ctx.ServerError("UpdateMilestone", err)
|
||||
return
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
|
||||
return
|
||||
}
|
||||
status := &models.CommitStatus{
|
||||
State: models.CommitStatusState(form.State),
|
||||
State: api.CommitStatusState(form.State),
|
||||
TargetURL: form.TargetURL,
|
||||
Description: form.Description,
|
||||
Context: form.Context,
|
||||
@@ -220,13 +220,13 @@ func getCommitStatuses(ctx *context.APIContext, sha string) {
|
||||
}
|
||||
|
||||
type combinedCommitStatus struct {
|
||||
State models.CommitStatusState `json:"state"`
|
||||
SHA string `json:"sha"`
|
||||
TotalCount int `json:"total_count"`
|
||||
Statuses []*api.Status `json:"statuses"`
|
||||
Repo *api.Repository `json:"repository"`
|
||||
CommitURL string `json:"commit_url"`
|
||||
URL string `json:"url"`
|
||||
State api.CommitStatusState `json:"state"`
|
||||
SHA string `json:"sha"`
|
||||
TotalCount int `json:"total_count"`
|
||||
Statuses []*api.Status `json:"statuses"`
|
||||
Repo *api.Repository `json:"repository"`
|
||||
CommitURL string `json:"commit_url"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// 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))
|
||||
for _, status := range statuses {
|
||||
retStatus.Statuses = append(retStatus.Statuses, status.APIFormat())
|
||||
if status.State.IsWorseThan(retStatus.State) {
|
||||
if status.State.NoBetterThan(retStatus.State) {
|
||||
retStatus.State = status.State
|
||||
}
|
||||
}
|
||||
|
@@ -115,7 +115,7 @@ func SettingsDeleteAvatar(ctx *context.Context) {
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/settings")
|
||||
}
|
||||
|
||||
// SettingsDelete response for delete repository
|
||||
// SettingsDelete response for deleting an organization
|
||||
func SettingsDelete(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("org.settings")
|
||||
ctx.Data["PageIsSettingsDelete"] = true
|
||||
|
@@ -68,7 +68,6 @@ func ServNoCommand(ctx *macaron.Context) {
|
||||
|
||||
// ServCommand returns information about the provided keyid
|
||||
func ServCommand(ctx *macaron.Context) {
|
||||
// Although we provide the verbs we don't need them at present they're just for logging purposes
|
||||
keyID := ctx.ParamsInt64(":keyid")
|
||||
ownerName := ctx.Params(":owner")
|
||||
repoName := ctx.Params(":repo")
|
||||
@@ -105,6 +104,17 @@ func ServCommand(ctx *macaron.Context) {
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
repoExist = false
|
||||
for _, verb := range ctx.QueryStrings("verb") {
|
||||
if "git-upload-pack" == verb {
|
||||
// User is fetching/cloning a non-existent repository
|
||||
ctx.JSON(http.StatusNotFound, map[string]interface{}{
|
||||
"results": results,
|
||||
"type": "ErrRepoNotExist",
|
||||
"err": fmt.Sprintf("Cannot find repository: %s/%s", results.OwnerName, results.RepoName),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Error("Unable to get repository: %s/%s Error: %v", results.OwnerName, results.RepoName, err)
|
||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
|
@@ -238,6 +238,7 @@ func loadBranches(ctx *context.Context) []*Branch {
|
||||
} else {
|
||||
repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo
|
||||
}
|
||||
pr.Issue.Repo = pr.BaseRepo
|
||||
|
||||
if pr.HasMerged {
|
||||
baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID]
|
||||
@@ -260,7 +261,6 @@ func loadBranches(ctx *context.Context) []*Branch {
|
||||
mergeMovedOn = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
isIncluded := divergence.Ahead == 0 && ctx.Repo.Repository.DefaultBranch != branchName
|
||||
|
@@ -157,12 +157,12 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
||||
ctx.ServerError("OpenRepository", err)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
defer headGitRepo.Close()
|
||||
}
|
||||
|
||||
// user should have permission to read baseRepo's codes and pulls, NOT headRepo's
|
||||
permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
|
||||
if err != nil {
|
||||
headGitRepo.Close()
|
||||
ctx.ServerError("GetUserRepoPermission", err)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
@@ -173,42 +173,40 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
||||
baseRepo,
|
||||
permBase)
|
||||
}
|
||||
headGitRepo.Close()
|
||||
ctx.NotFound("ParseCompareInfo", nil)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
|
||||
// user should have permission to read headrepo's codes
|
||||
permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
|
||||
if err != nil {
|
||||
headGitRepo.Close()
|
||||
ctx.ServerError("GetUserRepoPermission", err)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
if !permHead.CanRead(models.UnitTypeCode) {
|
||||
if log.IsTrace() {
|
||||
log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
|
||||
ctx.User,
|
||||
headRepo,
|
||||
permHead)
|
||||
if !isSameRepo {
|
||||
// user should have permission to read headrepo's codes
|
||||
permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserRepoPermission", err)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
if !permHead.CanRead(models.UnitTypeCode) {
|
||||
if log.IsTrace() {
|
||||
log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
|
||||
ctx.User,
|
||||
headRepo,
|
||||
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.
|
||||
headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch)
|
||||
headIsCommit := headGitRepo.IsCommitExist(headBranch)
|
||||
headIsBranch := headGitRepo.IsBranchExist(headBranch)
|
||||
headIsTag := headGitRepo.IsTagExist(headBranch)
|
||||
if !headIsCommit && !headIsBranch && !headIsTag {
|
||||
// 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()
|
||||
ctx.Data["HeadBranch"] = headBranch
|
||||
headIsCommit = true
|
||||
} else {
|
||||
headGitRepo.Close()
|
||||
ctx.NotFound("IsRefExist", nil)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
@@ -229,14 +227,12 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *
|
||||
baseRepo,
|
||||
permBase)
|
||||
}
|
||||
headGitRepo.Close()
|
||||
ctx.NotFound("ParseCompareInfo", 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 {
|
||||
headGitRepo.Close()
|
||||
ctx.ServerError("GetCompareInfo", err)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
@@ -385,7 +381,8 @@ func CompareDiff(ctx *context.Context) {
|
||||
}
|
||||
defer headGitRepo.Close()
|
||||
|
||||
if err := parseBaseRepoInfo(ctx, headRepo); err != nil {
|
||||
var err error
|
||||
if err = parseBaseRepoInfo(ctx, headRepo); err != nil {
|
||||
ctx.ServerError("parseBaseRepoInfo", err)
|
||||
return
|
||||
}
|
||||
@@ -418,7 +415,7 @@ func CompareDiff(ctx *context.Context) {
|
||||
|
||||
if !nothingToCompare {
|
||||
// Setup information for new form.
|
||||
RetrieveRepoMetas(ctx, ctx.Repo.Repository)
|
||||
RetrieveRepoMetas(ctx, ctx.Repo.Repository, true)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -427,6 +424,11 @@ func CompareDiff(ctx *context.Context) {
|
||||
beforeCommitID := ctx.Data["BeforeCommitID"].(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["IsRepoToolbarCommits"] = true
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user