mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-10 12:31:52 +02:00
Compare commits
17 Commits
v1.11.0-rc
...
v1.1.2
Author | SHA1 | Date | |
---|---|---|---|
|
bbe6aa349f | ||
|
4fd55d8796 | ||
|
daaabaa1d9 | ||
|
fa059debca | ||
|
2854c8aa47 | ||
|
506c98df5b | ||
|
f9859a2991 | ||
|
473df53533 | ||
|
2482c67e2b | ||
|
d9bdf7a65d | ||
|
11ad296347 | ||
|
5fad54248f | ||
|
2b5e4b4d96 | ||
|
65eea82c3e | ||
|
fac75b8086 | ||
|
e4706127f9 | ||
|
c9baf9d14b |
@@ -1,44 +0,0 @@
|
||||
repo: go-gitea/gitea
|
||||
groups:
|
||||
-
|
||||
name: BREAKING
|
||||
labels:
|
||||
- kind/breaking
|
||||
-
|
||||
name: FEATURE
|
||||
labels:
|
||||
- kind/feature
|
||||
-
|
||||
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
|
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
||||
*
|
||||
!gitea
|
||||
!docker
|
||||
!public
|
||||
!templates
|
898
.drone.yml
898
.drone.yml
@@ -1,773 +1,145 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: testing
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
base: /srv/app
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
pipeline:
|
||||
clone:
|
||||
image: plugins/git
|
||||
tags: true
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- apk -U add openssh-client
|
||||
- make clean
|
||||
- make generate
|
||||
- make vet
|
||||
- make lint
|
||||
- make test
|
||||
- make build
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
test-mysql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-mysql
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
test-pgsql:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test-pgsql
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
static:
|
||||
image: karalabe/xgo-latest:latest
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
coverage:
|
||||
image: plugins/coverage
|
||||
server: https://coverage.gitea.io
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
tags: [ '${DRONE_TAG##v}' ]
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
tags: [ '${DRONE_BRANCH##release/v}' ]
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ release/* ]
|
||||
|
||||
docker:
|
||||
image: plugins/docker
|
||||
repo: gitea/gitea
|
||||
tags: [ 'latest' ]
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/${DRONE_TAG##v}
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/${DRONE_BRANCH##release/v}
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ release/* ]
|
||||
|
||||
release:
|
||||
image: plugins/s3
|
||||
path_style: true
|
||||
strip_prefix: dist/release/
|
||||
source: dist/release/*
|
||||
target: /gitea/master
|
||||
when:
|
||||
event: [ push ]
|
||||
branch: [ master ]
|
||||
|
||||
github:
|
||||
image: plugins/github-release
|
||||
files:
|
||||
- dist/release/*
|
||||
when:
|
||||
event: [ tag ]
|
||||
branch: [ refs/tags/* ]
|
||||
|
||||
gitter:
|
||||
image: plugins/gitter
|
||||
|
||||
services:
|
||||
- name: mysql
|
||||
pull: default
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: test
|
||||
- MYSQL_DATABASE=test
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: mysql8
|
||||
pull: default
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: testgitea
|
||||
|
||||
- name: pgsql
|
||||
pull: default
|
||||
pgsql:
|
||||
image: postgres:9.5
|
||||
environment:
|
||||
POSTGRES_DB: test
|
||||
|
||||
- name: mssql
|
||||
pull: default
|
||||
image: microsoft/mssql-server-linux:latest
|
||||
environment:
|
||||
ACCEPT_EULA: Y
|
||||
MSSQL_PID: Standard
|
||||
SA_PASSWORD: MwantsaSecurePassword1
|
||||
|
||||
- name: ldap
|
||||
pull: default
|
||||
image: gitea/test-openldap:latest
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
- POSTGRES_DB=test
|
||||
when:
|
||||
event:
|
||||
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: unit-test
|
||||
pull: always
|
||||
image: golang:1.13
|
||||
commands:
|
||||
- make unit-test-coverage
|
||||
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
|
||||
|
||||
- name: 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
|
||||
- make test-mysql-migration
|
||||
- make integration-test-coverage
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata
|
||||
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
|
||||
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-mysql8-migration
|
||||
- timeout -s ABRT 20m make test-mysql8
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata
|
||||
TEST_LDAP: 1
|
||||
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
|
||||
commands:
|
||||
- "curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash"
|
||||
- apt-get install -y git-lfs
|
||||
- make test-mssql-migration
|
||||
- make test-mssql
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata
|
||||
TEST_LDAP: 1
|
||||
depends_on:
|
||||
- build
|
||||
|
||||
- name: generate-coverage
|
||||
pull: always
|
||||
image: golang:1.13
|
||||
commands:
|
||||
- make coverage
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata
|
||||
depends_on:
|
||||
- unit-test
|
||||
- test-mysql
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
- name: coverage
|
||||
pull: always
|
||||
image: robertstettner/drone-codecov
|
||||
settings:
|
||||
files:
|
||||
- coverage.all
|
||||
environment:
|
||||
CODECOV_TOKEN:
|
||||
from_secret: codecov_token
|
||||
depends_on:
|
||||
- generate-coverage
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: translations
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
|
||||
steps:
|
||||
- name: download
|
||||
pull: always
|
||||
image: jonasfranz/crowdin
|
||||
settings:
|
||||
download: true
|
||||
export_dir: options/locale/
|
||||
ignore_branch: true
|
||||
project_identifier: gitea
|
||||
environment:
|
||||
CROWDIN_KEY:
|
||||
from_secret: crowdin_key
|
||||
|
||||
- name: update
|
||||
pull: default
|
||||
image: alpine:3.11
|
||||
commands:
|
||||
- mv ./options/locale/locale_en-US.ini ./options/
|
||||
- "sed -i -e 's/=\"/=/g' -e 's/\"$$//g' ./options/locale/*.ini"
|
||||
- "sed -i -e 's/\\\\\\\\\"/\"/g' ./options/locale/*.ini"
|
||||
- mv ./options/locale_en-US.ini ./options/locale/
|
||||
|
||||
- name: push
|
||||
pull: always
|
||||
image: appleboy/drone-git-push
|
||||
settings:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
commit: true
|
||||
commit_message: "[skip ci] Updated translations via Crowdin"
|
||||
remote: "git@github.com:go-gitea/gitea.git"
|
||||
environment:
|
||||
GIT_PUSH_SSH_KEY:
|
||||
from_secret: git_push_ssh_key
|
||||
|
||||
- name: upload_translations
|
||||
pull: always
|
||||
image: jonasfranz/crowdin
|
||||
settings:
|
||||
files:
|
||||
locale_en-US.ini: options/locale/locale_en-US.ini
|
||||
ignore_branch: true
|
||||
project_identifier: gitea
|
||||
environment:
|
||||
CROWDIN_KEY:
|
||||
from_secret: crowdin_key
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: release-master
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
- "release/*"
|
||||
event:
|
||||
- push
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- translations
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: static
|
||||
pull: always
|
||||
image: techknowlogick/xgo:latest
|
||||
commands:
|
||||
- apt update && apt -y install curl
|
||||
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
|
||||
- name: gpg-sign
|
||||
pull: always
|
||||
image: plugins/gpgsign:1
|
||||
settings:
|
||||
detach_sign: true
|
||||
excludes:
|
||||
- "dist/release/*.sha256"
|
||||
files:
|
||||
- "dist/release/*"
|
||||
environment:
|
||||
GPGSIGN_KEY:
|
||||
from_secret: gpgsign_key
|
||||
GPGSIGN_PASSPHRASE:
|
||||
from_secret: gpgsign_passphrase
|
||||
|
||||
- name: release-branch-release
|
||||
pull: always
|
||||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
strip_prefix: dist/release/
|
||||
target: "/gitea/${DRONE_BRANCH##release/v}"
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: aws_access_key_id
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
from_secret: aws_secret_access_key
|
||||
when:
|
||||
branch:
|
||||
- "release/*"
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: release
|
||||
pull: always
|
||||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
strip_prefix: dist/release/
|
||||
target: /gitea/master
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: aws_access_key_id
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
from_secret: aws_secret_access_key
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: release-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: static
|
||||
pull: always
|
||||
image: techknowlogick/xgo:latest
|
||||
commands:
|
||||
- apt update && apt -y install curl
|
||||
- curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt -y install nodejs
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
environment:
|
||||
GOPROXY: off
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
|
||||
- name: gpg-sign
|
||||
pull: always
|
||||
image: plugins/gpgsign:1
|
||||
settings:
|
||||
detach_sign: true
|
||||
excludes:
|
||||
- "dist/release/*.sha256"
|
||||
files:
|
||||
- "dist/release/*"
|
||||
environment:
|
||||
GPGSIGN_KEY:
|
||||
from_secret: gpgsign_key
|
||||
GPGSIGN_PASSPHRASE:
|
||||
from_secret: gpgsign_passphrase
|
||||
|
||||
- name: release
|
||||
pull: always
|
||||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
strip_prefix: dist/release/
|
||||
target: "/gitea/${DRONE_TAG##v}"
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: aws_access_key_id
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
from_secret: aws_secret_access_key
|
||||
|
||||
- name: github
|
||||
pull: always
|
||||
image: plugins/github-release:1
|
||||
settings:
|
||||
files:
|
||||
- "dist/release/*"
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: github_token
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docs
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
steps:
|
||||
- name: build-docs
|
||||
pull: always
|
||||
image: webhippie/hugo:latest
|
||||
commands:
|
||||
- cd docs
|
||||
- make trans-copy
|
||||
- make clean
|
||||
- make build
|
||||
|
||||
- name: publish-docs
|
||||
pull: always
|
||||
image: lucap/drone-netlify:latest
|
||||
settings:
|
||||
path: docs/public/
|
||||
site_id: d2260bae-7861-4c02-8646-8f6440b12672
|
||||
environment:
|
||||
NETLIFY_TOKEN:
|
||||
from_secret: netlify_token
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-linux-amd64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
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-amd64
|
||||
settings:
|
||||
dry_run: true
|
||||
repo: gitea/gitea
|
||||
tags: linux-amd64
|
||||
build_args:
|
||||
- GOPROXY=off
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: publish
|
||||
pull: always
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=off
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-linux-arm64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
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
|
||||
settings:
|
||||
dry_run: true
|
||||
repo: gitea/gitea
|
||||
tags: linux-arm64
|
||||
build_args:
|
||||
- GOPROXY=off
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: publish
|
||||
pull: always
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=off
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-manifest
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: manifest
|
||||
pull: always
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
spec: docker/manifest.tmpl
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
|
||||
depends_on:
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: notify
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
when:
|
||||
status:
|
||||
- success
|
||||
- failure
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- translations
|
||||
- release-version
|
||||
- release-master
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
- docker-manifest
|
||||
- docs
|
||||
|
||||
steps:
|
||||
- name: discord
|
||||
pull: always
|
||||
image: appleboy/drone-discord:1.0.0
|
||||
environment:
|
||||
DISCORD_WEBHOOK_ID:
|
||||
from_secret: discord_webhook_id
|
||||
DISCORD_WEBHOOK_TOKEN:
|
||||
from_secret: discord_webhook_token
|
||||
event: [ push, tag, pull_request ]
|
||||
|
1
.drone.yml.sig
Normal file
1
.drone.yml.sig
Normal file
@@ -0,0 +1 @@
|
||||
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9zcnYvYXBwCiAgcGF0aDogc3JjL2NvZGUuZ2l0ZWEuaW8vZ2l0ZWEKCnBpcGVsaW5lOgogIGNsb25lOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0CiAgICB0YWdzOiB0cnVlCgogIHRlc3Q6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgVEFHUzogYmluZGF0YSBzcWxpdGUKICAgICAgR09QQVRIOiAvc3J2L2FwcAogICAgY29tbWFuZHM6CiAgICAgIC0gYXBrIC1VIGFkZCBvcGVuc3NoLWNsaWVudAogICAgICAtIG1ha2UgY2xlYW4KICAgICAgLSBtYWtlIGdlbmVyYXRlCiAgICAgIC0gbWFrZSB2ZXQKICAgICAgLSBtYWtlIGxpbnQKICAgICAgLSBtYWtlIHRlc3QKICAgICAgLSBtYWtlIGJ1aWxkCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIHRlc3QtbXlzcWw6CiAgICBpbWFnZTogd2ViaGlwcGllL2dvbGFuZzplZGdlCiAgICBwdWxsOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgVEFHUzogYmluZGF0YQogICAgICBHT1BBVEg6IC9zcnYvYXBwCiAgICBjb21tYW5kczoKICAgICAgLSBtYWtlIHRlc3QtbXlzcWwKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2gsIHRhZywgcHVsbF9yZXF1ZXN0IF0KCiAgdGVzdC1wZ3NxbDoKICAgIGltYWdlOiB3ZWJoaXBwaWUvZ29sYW5nOmVkZ2UKICAgIHB1bGw6IHRydWUKICAgIGVudmlyb25tZW50OgogICAgICBUQUdTOiBiaW5kYXRhCiAgICAgIEdPUEFUSDogL3Nydi9hcHAKICAgIGNvbW1hbmRzOgogICAgICAtIG1ha2UgdGVzdC1wZ3NxbAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCwgdGFnLCBwdWxsX3JlcXVlc3QgXQoKICBzdGF0aWM6CiAgICBpbWFnZToga2FyYWxhYmUveGdvLWxhdGVzdDpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGVudmlyb25tZW50OgogICAgICBUQUdTOiBiaW5kYXRhIHNxbGl0ZQogICAgICBHT1BBVEg6IC9zcnYvYXBwCiAgICBjb21tYW5kczoKICAgICAgLSBtYWtlIHJlbGVhc2UKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2gsIHRhZywgcHVsbF9yZXF1ZXN0IF0KCiAgY292ZXJhZ2U6CiAgICBpbWFnZTogcGx1Z2lucy9jb3ZlcmFnZQogICAgc2VydmVyOiBodHRwczovL2NvdmVyYWdlLmdpdGVhLmlvCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCgogIGRvY2tlcjoKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZ2l0ZWEvZ2l0ZWEKICAgIHRhZ3M6IFsgJyR7RFJPTkVfVEFHIyN2fScgXQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiBnaXRlYS9naXRlYQogICAgdGFnczogWyAnJHtEUk9ORV9CUkFOQ0gjI3JlbGVhc2Uvdn0nIF0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2ggXQogICAgICBicmFuY2g6IFsgcmVsZWFzZS8qIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiBnaXRlYS9naXRlYQogICAgdGFnczogWyAnbGF0ZXN0JyBdCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8ke0RST05FX1RBRyMjdn0KICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHRhZyBdCiAgICAgIGJyYW5jaDogWyByZWZzL3RhZ3MvKiBdCgogIHJlbGVhc2U6CiAgICBpbWFnZTogcGx1Z2lucy9zMwogICAgcGF0aF9zdHlsZTogdHJ1ZQogICAgc3RyaXBfcHJlZml4OiBkaXN0L3JlbGVhc2UvCiAgICBzb3VyY2U6IGRpc3QvcmVsZWFzZS8qCiAgICB0YXJnZXQ6IC9naXRlYS8ke0RST05FX0JSQU5DSCMjcmVsZWFzZS92fQogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgcHVzaCBdCiAgICAgIGJyYW5jaDogWyByZWxlYXNlLyogXQoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvczMKICAgIHBhdGhfc3R5bGU6IHRydWUKICAgIHN0cmlwX3ByZWZpeDogZGlzdC9yZWxlYXNlLwogICAgc291cmNlOiBkaXN0L3JlbGVhc2UvKgogICAgdGFyZ2V0OiAvZ2l0ZWEvbWFzdGVyCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoIF0KICAgICAgYnJhbmNoOiBbIG1hc3RlciBdCgogIGdpdGh1YjoKICAgIGltYWdlOiBwbHVnaW5zL2dpdGh1Yi1yZWxlYXNlCiAgICBmaWxlczoKICAgICAgLSBkaXN0L3JlbGVhc2UvKgogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnIF0KICAgICAgYnJhbmNoOiBbIHJlZnMvdGFncy8qIF0KCiAgZ2l0dGVyOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0dGVyCgpzZXJ2aWNlczoKICBteXNxbDoKICAgIGltYWdlOiBteXNxbDo1LjcKICAgIGVudmlyb25tZW50OgogICAgICAtIE1ZU1FMX0RBVEFCQVNFPXRlc3QKICAgICAgLSBNWVNRTF9BTExPV19FTVBUWV9QQVNTV09SRD15ZXMKICAgIHdoZW46CiAgICAgIGV2ZW50OiBbIHB1c2gsIHRhZywgcHVsbF9yZXF1ZXN0IF0KCiAgcGdzcWw6CiAgICBpbWFnZTogcG9zdGdyZXM6OS41CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBQT1NUR1JFU19EQj10ZXN0CiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIHB1bGxfcmVxdWVzdCBdCg.hp6IsxbFIQOaxJdmGv32Vf34-Nra3KqVIWzH52W687I
|
@@ -1,11 +1,11 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = lf
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
@@ -15,17 +15,13 @@ indent_size = 8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.less]
|
||||
[*.{less,yml}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml,json}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
indent_size = 4
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
@@ -1 +0,0 @@
|
||||
/web_src/js/semanticDropdown.js
|
53
.eslintrc
53
.eslintrc
@@ -1,53 +0,0 @@
|
||||
root: true
|
||||
|
||||
extends:
|
||||
- eslint-config-airbnb-base
|
||||
- eslint:recommended
|
||||
|
||||
parserOptions:
|
||||
ecmaVersion: 2020
|
||||
|
||||
env:
|
||||
browser: true
|
||||
es6: true
|
||||
jquery: true
|
||||
node: true
|
||||
|
||||
globals:
|
||||
__webpack_public_path__: true
|
||||
Clipboard: false
|
||||
CodeMirror: false
|
||||
Dropzone: false
|
||||
emojify: false
|
||||
hljs: false
|
||||
SimpleMDE: false
|
||||
u2fApi: false
|
||||
Vue: false
|
||||
|
||||
rules:
|
||||
arrow-body-style: [0]
|
||||
camelcase: [0]
|
||||
comma-dangle: [2, only-multiline]
|
||||
consistent-return: [0]
|
||||
default-case: [0]
|
||||
func-names: [0]
|
||||
import/extensions: [0]
|
||||
max-len: [0]
|
||||
newline-per-chained-call: [0]
|
||||
no-alert: [0]
|
||||
no-continue: [0]
|
||||
no-mixed-operators: [0]
|
||||
no-multi-assign: [0]
|
||||
no-new: [0]
|
||||
no-param-reassign: [0]
|
||||
no-plusplus: [0]
|
||||
no-restricted-syntax: [0]
|
||||
no-shadow: [0]
|
||||
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}]
|
||||
no-use-before-define: [0]
|
||||
no-var: [2]
|
||||
one-var-declaration-per-line: [0]
|
||||
one-var: [0]
|
||||
prefer-const: [2, {destructuring: all}]
|
||||
prefer-destructuring: [0]
|
||||
radix: [2, as-needed]
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,7 +1,6 @@
|
||||
* text=auto eol=lf
|
||||
conf/* linguist-vendored
|
||||
docker/* linguist-vendored
|
||||
options/* linguist-vendored
|
||||
public/* linguist-vendored
|
||||
scripts/* linguist-vendored
|
||||
templates/* linguist-vendored
|
||||
templates/* linguist-vendored
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
||||
open_collective: gitea
|
17
.github/issue_template.md
vendored
17
.github/issue_template.md
vendored
@@ -1,13 +1,9 @@
|
||||
<!-- NOTE: If your issue is a security concern, please send an email to security@gitea.io instead of opening a public issue -->
|
||||
1. Please speak English, this is the language all of us can speak and write.
|
||||
2. Please ask questions or configuration/deploy problems on our Gitter channel: https://gitter.im/go-gitea/gitea
|
||||
3. Please take a moment to search check that your issue doesn't already exist.
|
||||
4. Please give all relevant information below for bug reports, because incomplete details will be handled as an invalid report.
|
||||
|
||||
<!--
|
||||
1. Please speak English, this is the language all maintainers can speak and write.
|
||||
2. Please ask questions or configuration/deploy problems on our Discord
|
||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
||||
3. Please take a moment to check that your issue doesn't already exist.
|
||||
4. Please give all relevant information below for bug reports, because
|
||||
incomplete details will be handled as an invalid report.
|
||||
-->
|
||||
**You MUST delete the content above including this line before posting, otherwise your issue will be invalid.**
|
||||
|
||||
- Gitea version (or commit ref):
|
||||
- Git version:
|
||||
@@ -15,7 +11,6 @@
|
||||
- Database (use `[x]`):
|
||||
- [ ] PostgreSQL
|
||||
- [ ] MySQL
|
||||
- [ ] MSSQL
|
||||
- [ ] SQLite
|
||||
- Can you reproduce the bug at https://try.gitea.io:
|
||||
- [ ] Yes (provide example URL)
|
||||
@@ -30,4 +25,4 @@
|
||||
|
||||
## Screenshots
|
||||
|
||||
<!-- **If this issue involves the Web Interface, please include a screenshot** -->
|
||||
**If this issue involves the Web Interface, please include a screenshot**
|
||||
|
53
.github/stale.yml
vendored
53
.github/stale.yml
vendored
@@ -1,53 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- status/blocked
|
||||
- kind/security
|
||||
- lgtm/done
|
||||
- reviewed/confirmed
|
||||
- priority/critical
|
||||
- kind/proposal
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs during the next 2 weeks. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
This issue has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 1
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
pulls:
|
||||
daysUntilStale: 60
|
||||
daysUntilClose: 60
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs during the next 2 months. Thank you
|
||||
for your contributions.
|
||||
closeComment: >
|
||||
This pull request has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
|
37
.gitignore
vendored
37
.gitignore
vendored
@@ -10,10 +10,6 @@ _test
|
||||
# IntelliJ
|
||||
.idea
|
||||
|
||||
# MS VSCode
|
||||
.vscode
|
||||
__debug_bin
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
@@ -30,8 +26,7 @@ _testmain.go
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
*coverage.out
|
||||
coverage.all
|
||||
coverage.out
|
||||
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
@@ -41,8 +36,6 @@ coverage.all
|
||||
*.log
|
||||
|
||||
/gitea
|
||||
/debug
|
||||
/integrations.test
|
||||
|
||||
/bin
|
||||
/dist
|
||||
@@ -51,31 +44,3 @@ coverage.all
|
||||
/indexers
|
||||
/log
|
||||
/public/img/avatar
|
||||
/integrations/gitea-integration-mysql
|
||||
/integrations/gitea-integration-mysql8
|
||||
/integrations/gitea-integration-pgsql
|
||||
/integrations/gitea-integration-sqlite
|
||||
/integrations/gitea-integration-mssql
|
||||
/integrations/indexers-mysql
|
||||
/integrations/indexers-mysql8
|
||||
/integrations/indexers-pgsql
|
||||
/integrations/indexers-sqlite
|
||||
/integrations/indexers-mssql
|
||||
/integrations/mysql.ini
|
||||
/integrations/mysql8.ini
|
||||
/integrations/pgsql.ini
|
||||
/integrations/mssql.ini
|
||||
/node_modules
|
||||
/yarn.lock
|
||||
/public/js
|
||||
/public/css
|
||||
|
||||
# Snapcraft
|
||||
snap/.snapcraft/
|
||||
parts/
|
||||
stage/
|
||||
prime/
|
||||
*.snap
|
||||
*.snap-build
|
||||
*_source.tar.bz2
|
||||
.DS_Store
|
||||
|
@@ -1,97 +0,0 @@
|
||||
linters:
|
||||
enable:
|
||||
- gosimple
|
||||
- deadcode
|
||||
- typecheck
|
||||
- govet
|
||||
- errcheck
|
||||
- staticcheck
|
||||
- unused
|
||||
- structcheck
|
||||
- varcheck
|
||||
- golint
|
||||
- dupl
|
||||
#- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||
- gofmt
|
||||
- misspell
|
||||
- gocritic
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
fast: false
|
||||
|
||||
run:
|
||||
timeout: 3m
|
||||
|
||||
linters-settings:
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- singleCaseSwitch # Every time this occured in the code, there was no other way.
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- unparam
|
||||
- staticcheck
|
||||
- path: models/migrations/v
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- linters:
|
||||
- dupl
|
||||
text: "webhook"
|
||||
- linters:
|
||||
- gocritic
|
||||
text: "`ID' should not be capitalized"
|
||||
- path: modules/templates/helper.go
|
||||
linters:
|
||||
- gocritic
|
||||
- linters:
|
||||
- unused
|
||||
- deadcode
|
||||
text: "swagger"
|
||||
- path: contrib/pr/checkout.go
|
||||
linters:
|
||||
- errcheck
|
||||
- path: models/issue.go
|
||||
linters:
|
||||
- errcheck
|
||||
- path: models/migrations/
|
||||
linters:
|
||||
- errcheck
|
||||
- path: modules/log/
|
||||
linters:
|
||||
- errcheck
|
||||
- path: routers/routes/routes.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: routers/api/v1/repo/issue_subscription.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: routers/repo/view.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: models/migrations/
|
||||
linters:
|
||||
- unused
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "argument x is overwritten before first use"
|
||||
- path: modules/httplib/httplib.go
|
||||
linters:
|
||||
- staticcheck
|
||||
# Enabling this would require refactoring the methods and how they are called.
|
||||
- path: models/issue_comment_list.go
|
||||
linters:
|
||||
- dupl
|
||||
- linters:
|
||||
- misspell
|
||||
text: '`Unknwon` is a misspelling of `Unknown`'
|
5
.ignore
5
.ignore
@@ -1,5 +0,0 @@
|
||||
/vendor
|
||||
/public/vendor
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
3
.lgtm
3
.lgtm
@@ -1,3 +1,2 @@
|
||||
pattern = "(?)LGTM"
|
||||
self_approval_off = true
|
||||
self_approval_off = false
|
||||
ignore_maintainers_file = true
|
||||
|
25
.revive.toml
25
.revive.toml
@@ -1,25 +0,0 @@
|
||||
ignoreGeneratedHeader = false
|
||||
severity = "warning"
|
||||
confidence = 0.8
|
||||
errorCode = 1
|
||||
warningCode = 1
|
||||
|
||||
[rule.blank-imports]
|
||||
[rule.context-as-argument]
|
||||
[rule.context-keys-type]
|
||||
[rule.dot-imports]
|
||||
[rule.error-return]
|
||||
[rule.error-strings]
|
||||
[rule.error-naming]
|
||||
[rule.exported]
|
||||
[rule.if-return]
|
||||
[rule.increment-decrement]
|
||||
[rule.var-naming]
|
||||
[rule.var-declaration]
|
||||
[rule.package-comments]
|
||||
[rule.range]
|
||||
[rule.receiver-naming]
|
||||
[rule.time-naming]
|
||||
[rule.unexported-return]
|
||||
[rule.indent-error-flow]
|
||||
[rule.errorf]
|
11
.stylelintrc
11
.stylelintrc
@@ -1,11 +0,0 @@
|
||||
extends: stylelint-config-standard
|
||||
|
||||
rules:
|
||||
block-closing-brace-empty-line-before: null
|
||||
color-hex-length: null
|
||||
comment-empty-line-before: null
|
||||
declaration-empty-line-before: null
|
||||
indentation: 4
|
||||
no-descending-specificity: null
|
||||
rule-empty-line-before: null
|
||||
selector-pseudo-element-colon-notation: null
|
51
BSDmakefile
51
BSDmakefile
@@ -1,51 +0,0 @@
|
||||
# GNU makefile proxy script for BSD make
|
||||
# Written and maintained by Mahmoud Al-Qudsi <mqudsi@neosmart.net>
|
||||
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2018
|
||||
# Obtain updates from <https://github.com/neosmart/gmake-proxy>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
JARG =
|
||||
GMAKE = "gmake"
|
||||
#When gmake is called from another make instance, -w is automatically added
|
||||
#which causes extraneous messages about directory changes to be emitted.
|
||||
#--no-print-directory silences these messages.
|
||||
GARGS = "--no-print-directory"
|
||||
|
||||
.if "$(.MAKE.JOBS)" != ""
|
||||
JARG = -j$(.MAKE.JOBS)
|
||||
.endif
|
||||
|
||||
#by default bmake will cd into ./obj first
|
||||
.OBJDIR: ./
|
||||
|
||||
.PHONY: FRC
|
||||
$(.TARGETS): FRC
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.DONE .DEFAULT: .SILENT
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.ERROR: .SILENT
|
||||
if ! which $(GMAKE) > /dev/null; then \
|
||||
echo "GNU Make is required!"; \
|
||||
fi
|
2933
CHANGELOG.md
2933
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
309
CONTRIBUTING.md
309
CONTRIBUTING.md
@@ -1,148 +1,48 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Contribution Guidelines](#contribution-guidelines)
|
||||
- [Introduction](#introduction)
|
||||
- [Bug reports](#bug-reports)
|
||||
- [Discuss your design](#discuss-your-design)
|
||||
- [Testing redux](#testing-redux)
|
||||
- [Vendoring](#vendoring)
|
||||
- [Translation](#translation)
|
||||
- [Code review](#code-review)
|
||||
- [Styleguide](#styleguide)
|
||||
- [Design guideline](#design-guideline)
|
||||
- [API v1](#api-v1)
|
||||
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
|
||||
- [Release Cycle](#release-cycle)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Owners](#owners)
|
||||
- [Versions](#versions)
|
||||
- [Releasing Gitea](#releasing-gitea)
|
||||
- [Copyright](#copyright)
|
||||
|
||||
## Introduction
|
||||
|
||||
This document explains how to contribute changes to the Gitea project.
|
||||
It assumes you have followed the
|
||||
[installation instructions](https://docs.gitea.io/en-us/).
|
||||
Sensitive security-related issues should be reported to
|
||||
[security@gitea.io](mailto:security@gitea.io).
|
||||
|
||||
For configuring IDE or code editor to develop Gitea see [IDE and code editor configuration](contrib/ide/)
|
||||
This document explains how to contribute changes to the Gitea project. It assumes you have followed the [installation instructions](https://docs.gitea.io/en-us/). Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
|
||||
|
||||
## Bug reports
|
||||
|
||||
Please search the issues on the issue tracker with a variety of keywords
|
||||
to ensure your bug is not already reported.
|
||||
Please search the issues on the issue tracker with a variety of keywords to ensure your bug is not already reported.
|
||||
|
||||
If unique, [open an issue](https://github.com/go-gitea/gitea/issues/new)
|
||||
and answer the questions so we can understand and reproduce the
|
||||
problematic behavior.
|
||||
If unique, [open an issue](https://github.com/go-gitea/gitea/issues/new) and answer the questions so we can understand and reproduce the problematic behavior.
|
||||
|
||||
To show us that the issue you are having is in Gitea itself, please
|
||||
write clear, concise instructions so we can reproduce the behavior—
|
||||
even if it seems obvious. The more detailed and specific you are,
|
||||
the faster we can fix the issue. Check out [How to Report Bugs
|
||||
Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html).
|
||||
To show us that the issue you are having is in Gitea itself, please write clear, concise instructions so we can reproduce the behavior (even if it seems obvious). The more detailed and specific you are, the faster we can fix the issue. Check out [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html).
|
||||
|
||||
Please be kind, remember that Gitea comes at no cost to you, and you're
|
||||
getting free help.
|
||||
Please be kind, remember that Gitea comes at no cost to you, and you're getting free help.
|
||||
|
||||
## Discuss your design
|
||||
|
||||
The project welcomes submissions. If you want to change or add something,
|
||||
please let everyone know what you're working on—[file an issue](https://github.com/go-gitea/gitea/issues/new)!
|
||||
Significant changes must go through the change proposal process
|
||||
before they can be accepted. To create a proposal, file an issue with
|
||||
your proposed changes documented, and make sure to note in the title
|
||||
of the issue that it is a proposal.
|
||||
The project welcomes submissions but please let everyone know what you're working on if you want to change or add something to the Gitea repositories.
|
||||
|
||||
This process gives everyone a chance to validate the design, helps
|
||||
prevent duplication of effort, and ensures that the idea fits inside
|
||||
the goals for the project and tools. It also checks that the design is
|
||||
sound before code is written; the code review tool is not the place for
|
||||
high-level discussions.
|
||||
Before starting to write something new for the Gitea project, please [file an issue](https://github.com/go-gitea/gitea/issues/new). Significant changes must go through the [change proposal process](https://github.com/go-gitea/proposals) before they can be accepted.
|
||||
|
||||
This process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside the goals for the project and tools. It also checks that the design is sound before code is written; the code review tool is not the place for high-level discussions.
|
||||
|
||||
## Testing redux
|
||||
|
||||
Before submitting a pull request, run all the tests for the whole tree
|
||||
to make sure your changes don't cause regression elsewhere.
|
||||
|
||||
Here's how to run the test suite:
|
||||
|
||||
- Install the correct version of the drone-cli package. As of this
|
||||
writing, the correct drone-cli version is
|
||||
[1.2.0](https://docs.drone.io/cli/install/).
|
||||
- Ensure you have enough free disk space. You will need at least
|
||||
15-20 Gb of free disk space to hold all of the containers drone
|
||||
creates (a default AWS or GCE disk size won't work -- see
|
||||
[#6243](https://github.com/go-gitea/gitea/issues/6243)).
|
||||
- Change into the base directory of your copy of the gitea repository,
|
||||
and run `drone exec --event pull_request`.
|
||||
- At the moment `drone exec` doesn't support the Docker Toolbox on Windows 10
|
||||
(see [drone-cli#135](https://github.com/drone/drone-cli/issues/135))
|
||||
|
||||
The drone version, command line, and disk requirements do change over
|
||||
time (see [#4053](https://github.com/go-gitea/gitea/issues/4053) and
|
||||
[#6243](https://github.com/go-gitea/gitea/issues/6243)); if you
|
||||
discover any issues, please feel free to send us a pull request to
|
||||
update these instructions.
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. To make sure you are running the test suite exactly like we do, you should install the CLI for [Drone CI](https://github.com/drone/drone), as we are using the server for continous testing, following [these instructions](http://readme.drone.io/usage/getting-started-cli). After that you can simply call `drone exec` within your working directory and it will try to run the test suite locally.
|
||||
|
||||
## Vendoring
|
||||
|
||||
We keep a cached copy of dependencies within the `vendor/` directory,
|
||||
managing updates via [Modules](https://golang.org/cmd/go/#hdr-Module_maintenance).
|
||||
We keep a cached copy of dependencies within the `vendor/` directory, managing updates via [govendor](http://github.com/kardianos/govendor).
|
||||
|
||||
Pull requests should only include `vendor/` updates if they are part of
|
||||
the same change, be it a bugfix or a feature addition.
|
||||
Pull requests should only include `vendor/` updates if they are part of the same change, be it a bugfix or a feature addition.
|
||||
|
||||
The `vendor/` update needs to be justified as part of the PR description,
|
||||
and must be verified by the reviewers and/or merger to always reference
|
||||
an existing upstream commit.
|
||||
|
||||
You can find more information on how to get started with it on the [Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
||||
|
||||
## Translation
|
||||
|
||||
We do all translation work inside [Crowdin](https://crowdin.com/project/gitea).
|
||||
The only translation that is maintained in this git repository is
|
||||
[`en_US.ini`](https://github.com/go-gitea/gitea/blob/master/options/locale/locale_en-US.ini)
|
||||
and is synced regularly to Crowdin. Once a translation has reached
|
||||
A SATISFACTORY PERCENTAGE it will be synced back into this repo and
|
||||
included in the next released version.
|
||||
|
||||
## Building Gitea
|
||||
|
||||
Generally, the go build tools are installed as-needed in the `Makefile`.
|
||||
An exception are the tools to build the CSS, JS and images.
|
||||
|
||||
- To build CSS and JS: Install [Node.js](https://nodejs.org/en/download/package-manager) at version 10.0 or above
|
||||
with `npm` and then run `npm install`, `make css` and `make js`.
|
||||
- To build Images: ImageMagick, inkscape and zopflipng binaries must be
|
||||
available in your `PATH` to run `make generate-images`.
|
||||
|
||||
For more details on how to generate files, build and test Gitea, see the [hacking instructions](https://docs.gitea.io/en-us/hacking-on-gitea/)
|
||||
The `vendor/` update needs to be justified as part of the PR description, and must be verified by the reviewers and/or merger to always reference an existing upstream commit.
|
||||
|
||||
## Code review
|
||||
|
||||
Changes to Gitea must be reviewed before they are accepted—no matter who
|
||||
makes the change, even if they are an owner or a maintainer. We use GitHub's
|
||||
pull request workflow to do that. And, we also use [LGTM](http://lgtm.co)
|
||||
to ensure every PR is reviewed by at least 2 maintainers.
|
||||
Changes to Gitea must be reviewed before they are accepted, no matter who makes the change even if it is an owner or a maintainer. We use GitHub's pull request workflow to do that and we also use [LGTM](http://lgtm.co) to ensure every PR is reviewed by at least 2 maintainers.
|
||||
|
||||
Please try to make your pull request easy to review for us. And, please read
|
||||
the *[How to get faster PR reviews](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews)* guide;
|
||||
it has lots of useful tips for any project you may want to contribute.
|
||||
Some of the key points:
|
||||
Please try to make your pull request easy to review for us. Please read the "[How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/devel/faster_reviews.md)" guide, it has lots of useful tips for any project you may want to contribute. Some of the key points:
|
||||
|
||||
* Make small pull requests. The smaller, the faster to review and the
|
||||
more likely it will be merged soon.
|
||||
* Don't make changes unrelated to your PR. Maybe there are typos on
|
||||
some comments, maybe refactoring would be welcome on a function... but
|
||||
if that is not related to your PR, please make *another* PR for that.
|
||||
* Split big pull requests into multiple small ones. An incremental change
|
||||
will be faster to review than a huge PR.
|
||||
* Make small pull requests. The smaller, the faster to review and the more likely it will be merged soon.
|
||||
* Don't make changes unrelated to your PR. Maybe there are typos on some comments, maybe refactoring would be welcome on a function... but if that is not related to your PR, please make *another* PR for that.
|
||||
* Split big pull requests into multiple small ones. An incremental change will be faster to review than a huge PR.
|
||||
|
||||
## Styleguide
|
||||
|
||||
@@ -163,202 +63,57 @@ import (
|
||||
)
|
||||
```
|
||||
|
||||
## Design guideline
|
||||
## Sign your work
|
||||
|
||||
To maintain understandable code and avoid circular dependencies it is important to have a good structure of the code. The gitea code is divided into the following parts:
|
||||
|
||||
- **integration:** Integrations tests
|
||||
- **models:** Contains the data structures used by xorm to construct database tables. It also contains supporting functions to query and update the database. Dependecies to other code in Gitea should be avoided although some modules might be needed (for example for logging).
|
||||
- **models/fixtures:** Sample model data used in integration tests.
|
||||
- **models/migrations:** Handling of database migrations between versions. PRs that changes a database structure shall also have a migration step.
|
||||
- **modules:** Different modules to handle specific functionality in Gitea.
|
||||
- **public:** Frontend files (javascript, images, css, etc.)
|
||||
- **routers:** Handling of server requests. As it uses other Gitea packages to serve the request, other packages (models, modules or services) shall not depend on routers
|
||||
- **services:** Support functions for common routing operations. Uses models and modules to handle the request.
|
||||
- **templates:** Golang templates for generating the html output.
|
||||
- **vendor:** External code that Gitea depends on.
|
||||
|
||||
## API v1
|
||||
|
||||
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [GitHub API v3](https://developer.github.com/v3/).
|
||||
Thus, Gitea´s API should use the same endpoints and fields as GitHub´s API as far as possible, unless there are good reasons to deviate.
|
||||
If Gitea provides functionality that GitHub does not, a new endpoint can be created.
|
||||
If information is provided by Gitea that is not provided by the GitHub API, a new field can be used that doesn't collide with any GitHub fields.
|
||||
|
||||
Updating an existing API should not remove existing fields unless there is a really good reason to do so.
|
||||
The same applies to status responses. If you notice a problem, feel free to leave a comment in the code for future refactoring to APIv2 (which is currently not planned).
|
||||
|
||||
All expected results (errors, success, fail messages) should be documented
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L319-L327)).
|
||||
|
||||
All JSON input types must be defined as a struct in `models/structs/`
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91))
|
||||
and referenced in
|
||||
[routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go).
|
||||
They can then be used like the following:
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318)).
|
||||
|
||||
All JSON responses must be defined as a struct in `models/structs/`
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L36-L68))
|
||||
and referenced in its category in `routers/api/v1/swagger/`
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16))
|
||||
They can be used like the following:
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279))
|
||||
|
||||
In general, HTTP methods are chosen as follows:
|
||||
* **GET** endpoints return requested object and status **OK (200)**
|
||||
* **DELETE** endpoints return status **No Content (204)**
|
||||
* **POST** endpoints return status **Created (201)**, used to **create** new objects (e.g. a User)
|
||||
* **PUT** endpoints return status **No Content (204)**, used to **add/assign** existing Obejcts (e.g. User) to something (e.g. Org-Team)
|
||||
* **PATCH** endpoints return changed object and status **OK (200)**, used to **edit/change** an existing object
|
||||
|
||||
|
||||
An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
|
||||
|
||||
|
||||
## Developer Certificate of Origin (DCO)
|
||||
|
||||
We consider the act of contributing to the code by submitting a Pull
|
||||
Request as the "Sign off" or agreement to the certifications and terms
|
||||
of the [DCO](DCO) and [MIT license](LICENSE). No further action is required.
|
||||
Additionally you could add a line at the end of your commit message.
|
||||
The sign-off is a simple line at the end of the explanation for the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: If you can certify [DCO](DCO), then you just add a line to every git commit message:
|
||||
|
||||
```
|
||||
Signed-off-by: Joe Smith <joe.smith@email.com>
|
||||
```
|
||||
|
||||
If you set your `user.name` and `user.email` git configs, you can add the
|
||||
line to the end of your commit automatically with `git commit -s`.
|
||||
|
||||
We assume in good faith that the information you provide is legally binding.
|
||||
Please use your real name, we really dislike pseudonyms or anonymous contributions. We are in the open-source world without secrets. If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit -s`.
|
||||
|
||||
## Release Cycle
|
||||
|
||||
We adopted a release schedule to streamline the process of working
|
||||
on, finishing, and issuing releases. The overall goal is to make a
|
||||
minor release every two months, which breaks down into one month of
|
||||
general development followed by one month of testing and polishing
|
||||
known as the release freeze. All the feature pull requests should be
|
||||
merged in the first month of one release period. And, during the frozen
|
||||
period, a corresponding release branch is open for fixes backported from
|
||||
master. Release candidates are made during this period for user testing to
|
||||
obtain a final version that is maintained in this branch. A release is
|
||||
maintained by issuing patch releases to only correct critical problems
|
||||
such as crashes or security issues.
|
||||
We adopted a release schedule to streamline the process of working on, finishing, and issuing releases. The overall goal is to make a major release every two months, which breaks down into one month of general development followed by one month of testing and polishing known as the release freeze. A release is maintained by issuing minor releases to only correct critical problems such as crashes or security issues. All the feature pull requests should be merged in the first month of one release period.
|
||||
|
||||
Major release cycles are bimonthly. They always begin on the 25th and end on
|
||||
the 24th (i.e., the 25th of December to February 24th).
|
||||
|
||||
During a development cycle, we may also publish any necessary minor releases
|
||||
for the previous version. For example, if the latest, published release is
|
||||
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
|
||||
still possible.
|
||||
The current release cycle is aligned to start on December 25 to February 24, next is February 25 to April 24, and etc. On this cycle, we also maybe publish the previous release minor version. For example, the current release version is v1.1, but we maybe also publish v1.0.2. When we publish v1.2, then we will stop publish v1.0.3.
|
||||
|
||||
## Maintainers
|
||||
|
||||
To make sure every PR is checked, we have [team
|
||||
maintainers](MAINTAINERS). Every PR **MUST** be reviewed by at least
|
||||
two maintainers (or owners) before it can get merged. A maintainer
|
||||
should be a contributor of Gitea (or Gogs) and contributed at least
|
||||
4 accepted PRs. A contributor should apply as a maintainer in the
|
||||
[Discord](https://discord.gg/NsatcWJ) #develop channel. The owners
|
||||
or the team maintainers may invite the contributor. A maintainer
|
||||
should spend some time on code reviews. If a maintainer has no
|
||||
time to do that, they should apply to leave the maintainers team
|
||||
and we will give them the honor of being a member of the [advisors
|
||||
team](https://github.com/orgs/go-gitea/teams/advisors). Of course, if
|
||||
an advisor has time to code review, we will gladly welcome them back
|
||||
to the maintainers team. If a maintainer is inactive for more than 3
|
||||
months and forgets to leave the maintainers team, the owners may move
|
||||
him or her from the maintainers team to the advisors team.
|
||||
For security reasons, Maintainers should use 2FA for their accounts and
|
||||
if possible provide gpg signed commits.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
https://help.github.com/articles/signing-commits-with-gpg/
|
||||
To make sure every PR is checked, we have [team maintainers](https://github.com/orgs/go-gitea/teams/maintainers). Every PR **MUST** be reviewed by at least two maintainers (or owners) before it can get merged. A maintainer should be a contributor of Gitea (or Gogs) and contributed at least 4 accepted PRs. A contributor should apply as a maintainer in the [Gitter develop channel](https://gitter.im/go-gitea/develop). The owners or the team maintainers may invite the contributor. A maintainer should spend some time on code reviews. If a maintainer has no time to do that, they should apply to leave the maintainers team and we will give them the honor of being a member of the [advisors team](https://github.com/orgs/go-gitea/teams/advisors). Of course, if an advisor has time to code review, we will gladly welcome them back to the maintainers team. If a maintainer is inactive for more than 3 months and forgets to leave the maintainers team, the owners may move him or her from the maintainers team to the advisors team.
|
||||
|
||||
## Owners
|
||||
|
||||
Since Gitea is a pure community organization without any company support,
|
||||
to keep the development healthy we will elect three owners every year. All
|
||||
contributors may vote to elect up to three candidates, one of which will
|
||||
be the main owner, and the other two the assistant owners. When the new
|
||||
owners have been elected, the old owners will give up ownership to the
|
||||
newly elected owners. If an owner is unable to do so, the other owners
|
||||
will assist in ceding ownership to the newly elected owners.
|
||||
For security reasons, Owners or any account with write access (like a bot)
|
||||
must use 2FA.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
Since Gitea is a pure community organization without any company support, to keep the development healthy we will elect three owners every year. All contributors may vote to elect up to three candidates, one of which will be the main owner, and the other two the assistant owners. When the new owners have been elected, the old owners will give up ownership to the newly elected owners. If an owner is unable to do so, the other owners will assist in ceding ownership to the newly elected owners.
|
||||
|
||||
After the election, the new owners should proactively agree
|
||||
with our [CONTRIBUTING](CONTRIBUTING.md) requirements in the
|
||||
[Discord](https://discord.gg/NsatcWJ) #general channel. Below are the
|
||||
words to speak:
|
||||
After the election, the new owners should proactively agree with our [CONTRIBUTING](CONTRIBUTING.md) requirements on the [Gitter main channel](https://gitter.im/go-gitea/gitea). Below are the words to speak:
|
||||
|
||||
```
|
||||
I'm honored to having been elected an owner of Gitea, I agree with
|
||||
[CONTRIBUTING](CONTRIBUTING.md). I will spend part of my time on Gitea
|
||||
and lead the development of Gitea.
|
||||
I'm honored to having been elected an owner of Gitea, I agree with [CONTRIBUTING](CONTRIBUTING.md). I will spend part of my time on Gitea and lead the development of Gitea.
|
||||
```
|
||||
|
||||
To honor the past owners, here's the history of the owners and the time
|
||||
they served:
|
||||
To honor the past owners, here's the history of the owners and the time they served:
|
||||
|
||||
* 2016-11-04 ~ 2017-12-31
|
||||
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
* [Thomas Boerger](https://github.com/tboerger) <thomas@webhippie.de>
|
||||
* [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||
|
||||
* 2018-01-01 ~ 2018-12-31
|
||||
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
* [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||
|
||||
* 2019-01-01 ~ 2019-12-31
|
||||
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
* [Matti Ranta](https://github.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
|
||||
* 2020-01-01 ~ 2020-12-31
|
||||
* [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
* [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
|
||||
* [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
|
||||
## Versions
|
||||
|
||||
Gitea has the `master` branch as a tip branch and has version branches
|
||||
such as `release/v0.9`. `release/v0.9` is a release branch and we will
|
||||
tag `v0.9.0` for binary download. If `v0.9.0` has bugs, we will accept
|
||||
pull requests on the `release/v0.9` branch and publish a `v0.9.1` tag,
|
||||
after bringing the bug fix also to the master branch.
|
||||
Gitea has the `master` branch as a tip branch and has version branches such as `v0.9`. `v0.9` is a release branch and we will tag `v0.9.0` for binary download. If `v0.9.0` has bugs, we will accept pull requests on the `v0.9` branch and publish a `v0.9.1` tag, after bringing the bug fix also to the master branch.
|
||||
|
||||
Since the `master` branch is a tip version, if you wish to use Gitea
|
||||
in production, please download the latest release tag version. All the
|
||||
branches will be protected via GitHub, all the PRs to every branch must
|
||||
be reviewed by two maintainers and must pass the automatic tests.
|
||||
|
||||
## Releasing Gitea
|
||||
|
||||
* Let $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin will be kept the same as milestones on github or gitea in future.
|
||||
* Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody against in about serval hours.
|
||||
* If this is a big version first you have to create PR for changelog on branch `master` with PRs with label `changelog` and after it has been merged do following steps:
|
||||
* Create `-dev` tag as `git tag -s -F release.notes v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
|
||||
* When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
|
||||
* If it is bugfix version create PR for changelog on branch `release/v$vmaj.$vmin` and wait till it is reviewed and merged.
|
||||
* Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
|
||||
* And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically created a release and upload all the compiled binary. (But currently it didn't add the release notes automatically. Maybe we should fix that.)
|
||||
* If needed send PR for changelog on branch `master`.
|
||||
* Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
|
||||
Since the `master` branch is a tip version, if you wish to use Gitea in production, please download the latest release tag version. All the branches will be protected via GitHub, all the PRs to every branch must be reviewed by two maintainers and must pass the automatic tests.
|
||||
|
||||
## Copyright
|
||||
|
||||
Code that you contribute should use the standard copyright header:
|
||||
|
||||
```
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2017 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.
|
||||
```
|
||||
|
||||
Files in the repository contain copyright from the year they are added
|
||||
to the year they are last changed. If the copyright author is changed,
|
||||
just paste the header below the old one.
|
||||
Files in the repository contain copyright from the year they are added to the year they are last changed. If the copyright author is changed, just paste the header below the old one.
|
||||
|
56
Dockerfile
56
Dockerfile
@@ -1,45 +1,23 @@
|
||||
|
||||
###################################
|
||||
#Build stage
|
||||
FROM golang:1.13-alpine3.11 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
|
||||
ARG GITEA_VERSION
|
||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||
ENV TAGS "bindata $TAGS"
|
||||
|
||||
#Build deps
|
||||
RUN apk --no-cache add build-base git nodejs npm
|
||||
|
||||
#Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
|
||||
#Checkout version if set
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean build
|
||||
|
||||
FROM alpine:3.11
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
FROM alpine:3.4
|
||||
MAINTAINER Thomas Boerger <thomas@webhippie.de>
|
||||
|
||||
EXPOSE 22 3000
|
||||
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
RUN apk update && \
|
||||
apk add \
|
||||
su-exec \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gettext \
|
||||
sqlite \
|
||||
bash \
|
||||
git \
|
||||
linux-pam \
|
||||
openssh \
|
||||
s6 \
|
||||
sqlite \
|
||||
su-exec \
|
||||
tzdata
|
||||
|
||||
RUN addgroup \
|
||||
curl \
|
||||
openssh \
|
||||
tzdata && \
|
||||
rm -rf \
|
||||
/var/cache/apk/* && \
|
||||
addgroup \
|
||||
-S -g 1000 \
|
||||
git && \
|
||||
adduser \
|
||||
@@ -49,16 +27,16 @@ RUN addgroup \
|
||||
-u 1000 \
|
||||
-G git \
|
||||
git && \
|
||||
echo "git:$(dd if=/dev/urandom bs=24 count=1 status=none | base64)" | chpasswd
|
||||
echo "git:$(date +%s | sha256sum | base64 | head -c 32)" | chpasswd
|
||||
|
||||
ENV USER git
|
||||
ENV GITEA_CUSTOM /data/gitea
|
||||
ENV GODEBUG=netdns=go
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker/root /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
RUN ln -s /app/gitea/gitea /usr/local/bin/gitea
|
||||
COPY docker /
|
||||
COPY gitea /app/gitea/gitea
|
||||
|
42
Dockerfile.rpi
Normal file
42
Dockerfile.rpi
Normal file
@@ -0,0 +1,42 @@
|
||||
FROM hypriot/rpi-alpine-scratch:v3.4
|
||||
MAINTAINER Thomas Boerger <thomas@webhippie.de>
|
||||
|
||||
EXPOSE 22 3000
|
||||
|
||||
RUN apk update && \
|
||||
apk add \
|
||||
su-exec \
|
||||
ca-certificates \
|
||||
sqlite \
|
||||
bash \
|
||||
git \
|
||||
linux-pam \
|
||||
s6 \
|
||||
curl \
|
||||
openssh \
|
||||
tzdata && \
|
||||
rm -rf \
|
||||
/var/cache/apk/* && \
|
||||
addgroup \
|
||||
-S -g 1000 \
|
||||
git && \
|
||||
adduser \
|
||||
-S -H -D \
|
||||
-h /data/git \
|
||||
-s /bin/bash \
|
||||
-u 1000 \
|
||||
-G git \
|
||||
git && \
|
||||
echo "git:$(date +%s | sha256sum | base64 | head -c 32)" | chpasswd
|
||||
|
||||
ENV USER git
|
||||
ENV GITEA_CUSTOM /data/gitea
|
||||
ENV GODEBUG=netdns=go
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker /
|
||||
COPY gitea /app/gitea/gitea
|
24
MAINTAINERS
24
MAINTAINERS
@@ -7,32 +7,8 @@ Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
||||
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||
Matthias Loibl <mail@matthiasloibl.com> (@metalmatze)
|
||||
Morgan Bazalgette <the@howl.moe> (@thehowl)
|
||||
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
||||
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
||||
Sandro Santilli <strk@kbt.io> (@strk)
|
||||
Thibault Meyer <meyer.thibault@gmail.com> (@0xbaadf00d)
|
||||
Thomas Boerger <thomas@webhippie.de> (@tboerger)
|
||||
Patrick G <geek1011@outlook.com> (@geek1011)
|
||||
Antoine Girard <sapk@sapk.fr> (@sapk)
|
||||
Lauris Bukšis-Haberkorns <lauris@nix.lv> (@lafriks)
|
||||
Jonas Östanbäck <jonas.ostanback@gmail.com> (@cez81)
|
||||
David Schneiderbauer <dschneiderbauer@gmail.com> (@daviian)
|
||||
Peter Žeby <morlinest@gmail.com> (@morlinest)
|
||||
Matti Ranta <techknowlogick@gitea.io> (@techknowlogick)
|
||||
Jonas Franz <info@jonasfranz.software> (@jonasfranz)
|
||||
Alexey Terentyev <axifnx@gmail.com> (@axifive)
|
||||
Lanre Adelowo <yo@lanre.wtf> (@adelowo)
|
||||
Konrad Langenberg <k@knt.li> (@kolaente)
|
||||
He-Long Zhang <outman99@hotmail.com> (@BetaCat0)
|
||||
Andrew Thornton <art27@cantab.net> (@zeripath)
|
||||
John Olheiser <john.olheiser@gmail.com> (@jolheiser)
|
||||
Richard Mahn <rich.mahn@unfoldingword.org> (@richmahn)
|
||||
Mrsdizzie <info@mrsdizzie.com> (@mrsdizzie)
|
||||
silverwind <me@silverwind.io> (@silverwind)
|
||||
Gary Kim <gary@garykim.dev> (@gary-kim)
|
||||
Guillermo Prandi <gitea.maint@mailfilter.com.ar> (@guillep2k)
|
||||
Mura Li <typeless@ctli.io> (@typeless)
|
||||
6543 <6543@obermui.de> (@6543)
|
||||
jaqra <jaqra@hotmail.com> (@jaqra)
|
||||
David Svantesson <davidsvantesson@gmail.com> (@davidsvantesson)
|
||||
|
528
Makefile
528
Makefile
@@ -1,419 +1,107 @@
|
||||
DIST := dist
|
||||
IMPORT := code.gitea.io/gitea
|
||||
export GO111MODULE=off
|
||||
|
||||
GO ?= go
|
||||
SED_INPLACE := sed -i
|
||||
SHASUM ?= shasum -a 256
|
||||
|
||||
export PATH := $($(GO) env GOPATH)/bin:$(PATH)
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
EXECUTABLE ?= gitea.exe
|
||||
EXECUTABLE := gitea.exe
|
||||
else
|
||||
EXECUTABLE ?= gitea
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
SED_INPLACE := sed -i ''
|
||||
endif
|
||||
ifeq ($(UNAME_S),FreeBSD)
|
||||
SED_INPLACE := sed -i ''
|
||||
endif
|
||||
EXECUTABLE := gitea
|
||||
endif
|
||||
|
||||
GOFILES := $(shell find . -name "*.go" -type f ! -path "./vendor/*" ! -path "*/bindata.go")
|
||||
GOFMT ?= gofmt -s
|
||||
BINDATA := modules/{options,public,templates}/bindata.go
|
||||
STYLESHEETS := $(wildcard public/less/index.less public/less/_*.less)
|
||||
JAVASCRIPTS :=
|
||||
|
||||
GOFLAGS := -v
|
||||
EXTRA_GOFLAGS ?=
|
||||
LDFLAGS := -X "main.Version=$(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')" -X "main.Tags=$(TAGS)"
|
||||
|
||||
MAKE_VERSION := $(shell $(MAKE) -v | head -n 1)
|
||||
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations,$(shell go list ./... | grep -v /vendor/))
|
||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
|
||||
TAGS ?=
|
||||
|
||||
ifneq ($(DRONE_TAG),)
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
GITEA_VERSION ?= $(VERSION)
|
||||
else
|
||||
ifneq ($(DRONE_BRANCH),)
|
||||
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||
else
|
||||
VERSION ?= master
|
||||
endif
|
||||
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||
endif
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||
|
||||
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell GO111MODULE=on $(GO) list -mod=vendor ./... | grep -v /vendor/)))
|
||||
|
||||
GO_SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
JS_SOURCES ?= $(shell find web_src/js web_src/css -type f)
|
||||
CSS_SOURCES ?= $(shell find web_src/less -type f)
|
||||
|
||||
JS_DEST := public/js/index.js
|
||||
CSS_DEST := public/css/index.css
|
||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||
|
||||
JS_DEST_DIR := public/js
|
||||
CSS_DEST_DIR := public/css
|
||||
|
||||
TAGS ?=
|
||||
|
||||
TMPDIR := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'gitea-temp')
|
||||
|
||||
#To update swagger use: GO111MODULE=on go get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1
|
||||
SWAGGER := GO111MODULE=on $(GO) run -mod=vendor github.com/go-swagger/go-swagger/cmd/swagger
|
||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl}}/api/v1"|g
|
||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl}}/api/v1"|"basePath": "/api/v1"|g
|
||||
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
||||
|
||||
TEST_MYSQL_HOST ?= mysql:3306
|
||||
TEST_MYSQL_DBNAME ?= testgitea
|
||||
TEST_MYSQL_USERNAME ?= root
|
||||
TEST_MYSQL_PASSWORD ?=
|
||||
TEST_MYSQL8_HOST ?= mysql8:3306
|
||||
TEST_MYSQL8_DBNAME ?= testgitea
|
||||
TEST_MYSQL8_USERNAME ?= root
|
||||
TEST_MYSQL8_PASSWORD ?=
|
||||
TEST_PGSQL_HOST ?= pgsql:5432
|
||||
TEST_PGSQL_DBNAME ?= testgitea
|
||||
TEST_PGSQL_USERNAME ?= postgres
|
||||
TEST_PGSQL_PASSWORD ?= postgres
|
||||
TEST_MSSQL_HOST ?= mssql:1433
|
||||
TEST_MSSQL_DBNAME ?= gitea
|
||||
TEST_MSSQL_USERNAME ?= sa
|
||||
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||
|
||||
# $(call strip-suffix,filename)
|
||||
strip-suffix = $(firstword $(subst ., ,$(1)))
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
include docker/Makefile
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Make Routines:"
|
||||
@echo " - \"\" equivalent to \"build\""
|
||||
@echo " - build creates the entire project"
|
||||
@echo " - clean delete integration files and build files but not css and js files"
|
||||
@echo " - clean-all delete all generated files (integration test, build, css and js files)"
|
||||
@echo " - css rebuild only css files"
|
||||
@echo " - js rebuild only js files"
|
||||
@echo " - generate run \"make css js\" and \"go generate\""
|
||||
@echo " - fmt format the code"
|
||||
@echo " - generate-swagger generate the swagger spec from code comments"
|
||||
@echo " - swagger-validate check if the swagger spec is valide"
|
||||
@echo " - revive run code linter revive"
|
||||
@echo " - misspell check if a word is written wrong"
|
||||
@echo " - vet examines Go source code and reports suspicious constructs"
|
||||
@echo " - test run unit test"
|
||||
@echo " - test-sqlite run integration test for sqlite"
|
||||
|
||||
.PHONY: go-check
|
||||
go-check:
|
||||
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell go version | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?\s' | tr '.' ' ');))
|
||||
@if [ "$(GO_VERSION)" -lt "001011000" ]; then \
|
||||
echo "Gitea requires Go 1.11.0 or greater to build. You can get it at https://golang.org/dl/"; \
|
||||
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 '.' ' ');))
|
||||
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
|
||||
@if [ "$(NODE_VERSION)" -lt "010000000" -o "$(NPM_MISSING)" = "1" ]; then \
|
||||
echo "Gitea requires Node.js 10.0.0 or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: clean-all
|
||||
clean-all: clean
|
||||
rm -rf $(JS_DEST_DIR) $(CSS_DEST_DIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(GO) clean -i ./...
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \
|
||||
integrations*.test \
|
||||
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-mysql8/ integrations/gitea-integration-sqlite/ \
|
||||
integrations/gitea-integration-mssql/ integrations/indexers-mysql/ integrations/indexers-mysql8/ integrations/indexers-pgsql integrations/indexers-sqlite \
|
||||
integrations/indexers-mssql integrations/mysql.ini integrations/mysql8.ini integrations/pgsql.ini integrations/mssql.ini
|
||||
go clean -i ./...
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA)
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
$(GOFMT) -w $(GOFILES)
|
||||
find . -name "*.go" -type f -not -path "./vendor/*" | xargs gofmt -s -w
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
$(GO) vet $(PACKAGES)
|
||||
go vet $(PACKAGES)
|
||||
|
||||
.PHONY: generate
|
||||
generate: js css
|
||||
GO111MODULE=on $(GO) generate -mod=vendor $(PACKAGES)
|
||||
|
||||
.PHONY: generate-swagger
|
||||
generate-swagger:
|
||||
$(SWAGGER) generate spec -o './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: swagger-check
|
||||
swagger-check: generate-swagger
|
||||
@diff=$$(git diff '$(SWAGGER_SPEC)'); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make generate-swagger' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
exit 1; \
|
||||
fi;
|
||||
|
||||
.PHONY: swagger-validate
|
||||
swagger-validate:
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
|
||||
$(SWAGGER) validate './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
generate:
|
||||
@hash go-bindata > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get -u github.com/jteeuwen/go-bindata/...; \
|
||||
fi
|
||||
go generate $(PACKAGES)
|
||||
|
||||
.PHONY: errcheck
|
||||
errcheck:
|
||||
@hash errcheck > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/kisielk/errcheck; \
|
||||
go get -u github.com/kisielk/errcheck; \
|
||||
fi
|
||||
errcheck $(PACKAGES)
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@echo 'make lint is depricated. Use "make revive" if you want to use the old lint tool, or "make golangci-lint" to run a complete code check.'
|
||||
|
||||
.PHONY: revive
|
||||
revive:
|
||||
@hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/mgechev/revive; \
|
||||
@hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get -u github.com/golang/lint/golint; \
|
||||
fi
|
||||
revive -config .revive.toml -exclude=./vendor/... ./... || exit 1
|
||||
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
|
||||
|
||||
.PHONY: misspell-check
|
||||
misspell-check:
|
||||
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
|
||||
fi
|
||||
misspell -error -i unknwon,destory $(GOFILES)
|
||||
|
||||
.PHONY: misspell
|
||||
misspell:
|
||||
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
|
||||
fi
|
||||
misspell -w -i unknwon $(GOFILES)
|
||||
|
||||
.PHONY: fmt-check
|
||||
fmt-check:
|
||||
# get all go files and run go fmt on them
|
||||
@diff=$$($(GOFMT) -d $(GOFILES)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make fmt' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
exit 1; \
|
||||
fi;
|
||||
.PHONY: integrations
|
||||
integrations: TAGS=bindata sqlite
|
||||
integrations: build
|
||||
go test code.gitea.io/gitea/integrations
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
GO111MODULE=on $(GO) test -mod=vendor -tags='sqlite sqlite_unlock_notify' $(PACKAGES)
|
||||
|
||||
.PHONY: test\#%
|
||||
test\#%:
|
||||
GO111MODULE=on $(GO) test -mod=vendor -tags='sqlite sqlite_unlock_notify' -run $* $(PACKAGES)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@hash gocovmerge > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/wadey/gocovmerge; \
|
||||
fi
|
||||
gocovmerge integration.coverage.out $(shell find . -type f -name "coverage.out") > coverage.all;\
|
||||
|
||||
.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
|
||||
|
||||
.PHONY: vendor
|
||||
vendor:
|
||||
GO111MODULE=on $(GO) mod tidy && GO111MODULE=on $(GO) mod vendor
|
||||
|
||||
.PHONY: test-vendor
|
||||
test-vendor: vendor
|
||||
@diff=$$(git diff vendor/); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make vendor' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
exit 1; \
|
||||
fi;
|
||||
|
||||
.PHONY: test-sqlite
|
||||
test-sqlite: integrations.sqlite.test
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test
|
||||
|
||||
.PHONY: test-sqlite\#%
|
||||
test-sqlite\#%: integrations.sqlite.test
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.run $*
|
||||
|
||||
.PHONY: test-sqlite-migration
|
||||
test-sqlite-migration: migrations.sqlite.test
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./migrations.sqlite.test
|
||||
|
||||
generate-ini-mysql:
|
||||
sed -e 's|{{TEST_MYSQL_HOST}}|${TEST_MYSQL_HOST}|g' \
|
||||
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL_USERNAME}}|${TEST_MYSQL_USERNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL_PASSWORD}}|${TEST_MYSQL_PASSWORD}|g' \
|
||||
integrations/mysql.ini.tmpl > integrations/mysql.ini
|
||||
for PKG in $(PACKAGES); do go test -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
|
||||
.PHONY: test-mysql
|
||||
test-mysql: integrations.mysql.test generate-ini-mysql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test
|
||||
|
||||
.PHONY: test-mysql\#%
|
||||
test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.run $*
|
||||
|
||||
.PHONY: test-mysql-migration
|
||||
test-mysql-migration: migrations.mysql.test generate-ini-mysql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./migrations.mysql.test
|
||||
|
||||
|
||||
generate-ini-mysql8:
|
||||
sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \
|
||||
-e 's|{{TEST_MYSQL8_DBNAME}}|${TEST_MYSQL8_DBNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL8_USERNAME}}|${TEST_MYSQL8_USERNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL8_PASSWORD}}|${TEST_MYSQL8_PASSWORD}|g' \
|
||||
integrations/mysql8.ini.tmpl > integrations/mysql8.ini
|
||||
|
||||
.PHONY: test-mysql8
|
||||
test-mysql8: integrations.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test
|
||||
|
||||
.PHONY: test-mysql8\#%
|
||||
test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test -test.run $*
|
||||
|
||||
.PHONY: test-mysql8-migration
|
||||
test-mysql8-migration: migrations.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql8.ini ./migrations.mysql8.test
|
||||
|
||||
|
||||
generate-ini-pgsql:
|
||||
sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \
|
||||
-e 's|{{TEST_PGSQL_DBNAME}}|${TEST_PGSQL_DBNAME}|g' \
|
||||
-e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \
|
||||
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
|
||||
integrations/pgsql.ini.tmpl > integrations/pgsql.ini
|
||||
test-mysql:
|
||||
@echo "Not integrated yet!"
|
||||
|
||||
.PHONY: test-pgsql
|
||||
test-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test
|
||||
|
||||
.PHONY: test-pgsql\#%
|
||||
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.run $*
|
||||
|
||||
.PHONY: test-pgsql-migration
|
||||
test-pgsql-migration: migrations.pgsql.test generate-ini-pgsql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./migrations.pgsql.test
|
||||
|
||||
|
||||
generate-ini-mssql:
|
||||
sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
|
||||
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
|
||||
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
|
||||
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
|
||||
integrations/mssql.ini.tmpl > integrations/mssql.ini
|
||||
|
||||
.PHONY: test-mssql
|
||||
test-mssql: integrations.mssql.test generate-ini-mssql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test
|
||||
|
||||
.PHONY: test-mssql\#%
|
||||
test-mssql\#%: integrations.mssql.test generate-ini-mssql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.run $*
|
||||
|
||||
.PHONY: test-mssql-migration
|
||||
test-mssql-migration: migrations.mssql.test generate-ini-mssql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./migrations.mssql.test
|
||||
|
||||
|
||||
.PHONY: bench-sqlite
|
||||
bench-sqlite: integrations.sqlite.test
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
|
||||
.PHONY: bench-mysql
|
||||
bench-mysql: integrations.mysql.test generate-ini-mysql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
|
||||
.PHONY: bench-mssql
|
||||
bench-mssql: integrations.mssql.test generate-ini-mssql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
|
||||
.PHONY: bench-pgsql
|
||||
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
|
||||
|
||||
.PHONY: integration-test-coverage
|
||||
integration-test-coverage: integrations.cover.test generate-ini-mysql
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
|
||||
|
||||
integrations.mysql.test: $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.mysql.test
|
||||
|
||||
integrations.mysql8.test: $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.mysql8.test
|
||||
|
||||
integrations.pgsql.test: $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.pgsql.test
|
||||
|
||||
integrations.mssql.test: $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.mssql.test
|
||||
|
||||
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)
|
||||
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
|
||||
migrations.mysql.test: $(GO_SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql.test
|
||||
|
||||
.PHONY: migrations.mysql8.test
|
||||
migrations.mysql8.test: $(GO_SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql8.test
|
||||
|
||||
.PHONY: migrations.pgsql.test
|
||||
migrations.pgsql.test: $(GO_SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.pgsql.test
|
||||
|
||||
.PHONY: migrations.mssql.test
|
||||
migrations.mssql.test: $(GO_SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.mssql.test
|
||||
|
||||
.PHONY: migrations.sqlite.test
|
||||
migrations.sqlite.test: $(GO_SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
|
||||
test-pgsql:
|
||||
@echo "Not integrated yet!"
|
||||
|
||||
.PHONY: check
|
||||
check: test
|
||||
|
||||
.PHONY: install
|
||||
install: $(wildcard *.go)
|
||||
$(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||
go install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||
|
||||
.PHONY: build
|
||||
build: go-check generate $(EXECUTABLE)
|
||||
build: $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
$(EXECUTABLE): $(SOURCES)
|
||||
go build -i -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" webhippie/golang:edge make clean generate build
|
||||
docker build -t gitea/gitea:latest .
|
||||
|
||||
.PHONY: release
|
||||
release: generate release-dirs release-windows release-linux release-darwin release-copy release-compress release-check
|
||||
release: release-dirs release-windows release-linux release-darwin release-copy release-check
|
||||
|
||||
.PHONY: release-dirs
|
||||
release-dirs:
|
||||
@@ -422,142 +110,54 @@ release-dirs:
|
||||
.PHONY: release-windows
|
||||
release-windows:
|
||||
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u src.techknowlogick.com/xgo; \
|
||||
go get -u github.com/karalabe/xgo; \
|
||||
fi
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
||||
ifeq ($(CI),drone)
|
||||
cp /build/* $(DIST)/binaries
|
||||
mv /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-linux
|
||||
release-linux:
|
||||
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u src.techknowlogick.com/xgo; \
|
||||
go get -u github.com/karalabe/xgo; \
|
||||
fi
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/*' -out gitea-$(VERSION) .
|
||||
ifeq ($(CI),drone)
|
||||
cp /build/* $(DIST)/binaries
|
||||
mv /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-darwin
|
||||
release-darwin:
|
||||
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u src.techknowlogick.com/xgo; \
|
||||
go get -u github.com/karalabe/xgo; \
|
||||
fi
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
|
||||
ifeq ($(CI),drone)
|
||||
cp /build/* $(DIST)/binaries
|
||||
mv /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-copy
|
||||
release-copy:
|
||||
cd $(DIST); for file in `find /build -type f -name "*"`; do cp $${file} ./release/; done;
|
||||
$(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
|
||||
|
||||
.PHONY: release-check
|
||||
release-check:
|
||||
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done;
|
||||
|
||||
.PHONY: release-compress
|
||||
release-compress:
|
||||
@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \
|
||||
fi
|
||||
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done;
|
||||
|
||||
node_modules: package-lock.json
|
||||
npm install --no-save
|
||||
|
||||
.PHONY: npm-update
|
||||
npm-update: node-check node_modules
|
||||
npx updates -cu
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install --package-lock
|
||||
|
||||
.PHONY: js
|
||||
js: node-check $(JS_DEST)
|
||||
|
||||
$(JS_DEST): node_modules $(JS_SOURCES)
|
||||
npx eslint web_src/js webpack.config.js
|
||||
npx webpack
|
||||
|
||||
.PHONY: css
|
||||
css: node-check $(CSS_DEST)
|
||||
|
||||
$(CSS_DEST): node_modules $(CSS_SOURCES)
|
||||
npx stylelint web_src/less
|
||||
npx lessc web_src/less/index.less public/css/index.css
|
||||
$(foreach file, $(filter-out web_src/less/themes/_base.less, $(wildcard web_src/less/themes/*)),npx lessc web_src/less/themes/$(notdir $(file)) > public/css/theme-$(notdir $(call strip-suffix,$(file))).css;)
|
||||
npx postcss --use autoprefixer --use cssnano --no-map --replace public/css/*
|
||||
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
|
||||
|
||||
.PHONY: javascripts
|
||||
javascripts:
|
||||
echo "'make javascripts' is deprecated, please use 'make js'"
|
||||
$(MAKE) js
|
||||
javascripts: public/js/index.js
|
||||
|
||||
.PHONY: stylesheets-check
|
||||
stylesheets-check:
|
||||
echo "'make stylesheets-check' is deprecated, please use 'make css'"
|
||||
$(MAKE) css
|
||||
.IGNORE: public/js/index.js
|
||||
public/js/index.js: $(JAVASCRIPTS)
|
||||
cat $< >| $@
|
||||
|
||||
.PHONY: generate-stylesheets
|
||||
generate-stylesheets:
|
||||
echo "'make generate-stylesheets' is deprecated, please use 'make css'"
|
||||
$(MAKE) css
|
||||
.PHONY: stylesheets
|
||||
stylesheets: public/css/index.css
|
||||
|
||||
.PHONY: swagger-ui
|
||||
swagger-ui:
|
||||
rm -Rf public/vendor/assets/swagger-ui
|
||||
git clone --depth=10 -b v3.13.4 --single-branch https://github.com/swagger-api/swagger-ui.git $(TMPDIR)/swagger-ui
|
||||
mv $(TMPDIR)/swagger-ui/dist public/vendor/assets/swagger-ui
|
||||
rm -Rf $(TMPDIR)/swagger-ui
|
||||
$(SED_INPLACE) "s;http://petstore.swagger.io/v2/swagger.json;../../../swagger.v1.json;g" public/vendor/assets/swagger-ui/index.html
|
||||
.IGNORE: public/css/index.css
|
||||
public/css/index.css: $(STYLESHEETS)
|
||||
lessc $< $@
|
||||
|
||||
.PHONY: update-translations
|
||||
update-translations:
|
||||
mkdir -p ./translations
|
||||
cd ./translations && curl -L https://crowdin.com/download/project/gitea.zip > gitea.zip && unzip gitea.zip
|
||||
rm ./translations/gitea.zip
|
||||
$(SED_INPLACE) -e 's/="/=/g' -e 's/"$$//g' ./translations/*.ini
|
||||
$(SED_INPLACE) -e 's/\\"/"/g' ./translations/*.ini
|
||||
mv ./translations/*.ini ./options/locale/
|
||||
rmdir ./translations
|
||||
|
||||
.PHONY: generate-images
|
||||
generate-images:
|
||||
mkdir -p $(TMPDIR)/images
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 880 -h 880 -e $(PWD)/public/img/gitea-lg.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 512 -h 512 -e $(PWD)/public/img/gitea-512.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 192 -h 192 -e $(PWD)/public/img/gitea-192.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer1 -e $(TMPDIR)/images/sm-1.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer2 -e $(TMPDIR)/images/sm-2.png
|
||||
composite -compose atop $(TMPDIR)/images/sm-2.png $(TMPDIR)/images/sm-1.png $(PWD)/public/img/gitea-sm.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 200 -h 200 -e $(PWD)/public/img/avatar_default.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 180 -h 180 -e $(PWD)/public/img/favicon.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 128 -h 128 -e $(TMPDIR)/images/128-raw.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 64 -h 64 -e $(TMPDIR)/images/64-raw.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 32 -h 32 -jC -i layer1 -e $(TMPDIR)/images/32-1.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 32 -h 32 -jC -i layer2 -e $(TMPDIR)/images/32-2.png
|
||||
composite -compose atop $(TMPDIR)/images/32-2.png $(TMPDIR)/images/32-1.png $(TMPDIR)/images/32-raw.png
|
||||
inkscape -f $(PWD)/assets/logo.svg -w 16 -h 16 -jC -i layer1 -e $(TMPDIR)/images/16-raw.png
|
||||
zopflipng -m -y $(TMPDIR)/images/128-raw.png $(TMPDIR)/images/128.png
|
||||
zopflipng -m -y $(TMPDIR)/images/64-raw.png $(TMPDIR)/images/64.png
|
||||
zopflipng -m -y $(TMPDIR)/images/32-raw.png $(TMPDIR)/images/32.png
|
||||
zopflipng -m -y $(TMPDIR)/images/16-raw.png $(TMPDIR)/images/16.png
|
||||
rm -f $(TMPDIR)/images/*-*.png
|
||||
convert $(TMPDIR)/images/16.png $(TMPDIR)/images/32.png \
|
||||
$(TMPDIR)/images/64.png $(TMPDIR)/images/128.png \
|
||||
$(PWD)/public/img/favicon.ico
|
||||
rm -rf $(TMPDIR)/images
|
||||
$(foreach file, $(shell find public/img -type f -name '*.png'),zopflipng -m -y $(file) $(file);)
|
||||
|
||||
.PHONY: pr
|
||||
pr:
|
||||
$(GO) run contrib/pr/checkout.go $(PR)
|
||||
|
||||
.PHONY: golangci-lint
|
||||
golangci-lint:
|
||||
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
export BINARY="golangci-lint"; \
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.20.0; \
|
||||
fi
|
||||
golangci-lint run --timeout 5m
|
||||
.PHONY: assets
|
||||
assets: javascripts stylesheets
|
||||
|
108
README.md
108
README.md
@@ -1,63 +1,39 @@
|
||||
[简体中文](README_ZH.md)
|
||||
[简体中文](https://github.com/go-gitea/gitea/blob/master/README_ZH.md)
|
||||
|
||||
<h1> <img src="https://raw.githubusercontent.com/go-gitea/gitea/master/public/img/gitea-192.png" alt="logo" width="30" height="30"> Gitea - Git with a cup of tea</h1>
|
||||
# Gitea - Git with a cup of tea
|
||||
|
||||
[](https://drone.gitea.io/go-gitea/gitea)
|
||||
[](https://discord.gg/NsatcWJ)
|
||||
[](https://gitter.im/go-gitea/gitea?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://microbadger.com/images/gitea/gitea "Get your own image badge on microbadger.com")
|
||||
[](https://codecov.io/gh/go-gitea/gitea)
|
||||
[](https://coverage.gitea.io/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://www.codetriage.com/go-gitea/gitea)
|
||||
[](https://opencollective.com/gitea)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://crowdin.com/project/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
|
||||
||||
|
||||
|:-------------:|:-------:|:-------:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
||||
## Purpose
|
||||
|
||||
The goal of this project is to make the easiest, fastest, and most
|
||||
painless way of setting up a self-hosted Git service.
|
||||
Using Go, this can be done with an independent binary distribution across
|
||||
**all platforms** which Go supports, including Linux, macOS, and Windows
|
||||
on x86, amd64, ARM and PowerPC architectures.
|
||||
Want to try it before doing anything else?
|
||||
Do it [with the online demo](https://try.gitea.io/)!
|
||||
This project has been
|
||||
[forked](https://blog.gitea.io/2016/12/welcome-to-gitea/) from
|
||||
[Gogs](https://gogs.io) since 2016.11 but changed a lot.
|
||||
The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. Using Go, this can be done with an independent binary distribution across **all platforms** which Go supports, including Linux, macOS, and Windows on x86, amd64, ARM and PowerPC architectures. Want to try it before doing anything else? Do it [with the online demo](https://try.gitea.io/)! This project has been [forked](https://blog.gitea.io/2016/12/welcome-to-gitea/) from [Gogs](https://gogs.io).
|
||||
|
||||
## Building
|
||||
## Notes
|
||||
|
||||
From the root of the source tree, run:
|
||||
1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||
2. If you found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||
3. If you're interested in using our APIs, we have experimental support with [documentation](https://godoc.org/code.gitea.io/sdk/gitea).
|
||||
|
||||
TAGS="bindata" make build
|
||||
## Docs
|
||||
|
||||
More info: https://docs.gitea.io/en-us/install-from-source/
|
||||
|
||||
## Using
|
||||
|
||||
./gitea web
|
||||
|
||||
NOTE: If you're interested in using our APIs, we have experimental
|
||||
support with [documentation](https://try.gitea.io/api/swagger).
|
||||
For more information and instructions about how to install Gitea please look at our [documentation](https://docs.gitea.io/en-us/). If you cannot find some specific information, then head over to our [Gitter](https://gitter.im/go-gitea/gitea) channel to chat with us.
|
||||
|
||||
## Contributing
|
||||
|
||||
Expected workflow is: Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
NOTES:
|
||||
|
||||
1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||
2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||
|
||||
## Further information
|
||||
|
||||
For more information and instructions about how to install Gitea, please look
|
||||
at our [documentation](https://docs.gitea.io/en-us/). If you have questions
|
||||
that are not covered by the documentation, you can get in contact with us on
|
||||
our [Discord server](https://discord.gg/NsatcWJ),
|
||||
or [forum](https://discourse.gitea.io/)!
|
||||
Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## Authors
|
||||
|
||||
@@ -65,48 +41,6 @@ or [forum](https://discourse.gitea.io/)!
|
||||
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
* [Translators](options/locale/TRANSLATORS)
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/gitea#backer)]
|
||||
|
||||
<a href="https://opencollective.com/gitea#backers" target="_blank"><img src="https://opencollective.com/gitea/backers.svg?width=890"></a>
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/gitea#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/gitea/sponsor/0/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/1/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/2/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/3/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/4/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/5/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/6/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/7/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/8/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/9/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/9/avatar.svg"></a>
|
||||
|
||||
## FAQ
|
||||
|
||||
**How do you pronounce Gitea?**
|
||||
|
||||
Gitea is pronounced [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY) as in "gi-tea" with a hard g.
|
||||
|
||||
**Why is this not hosted on a Gitea instance?**
|
||||
|
||||
We're [working on it](https://github.com/go-gitea/gitea/issues/1029).
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
See the [LICENSE](https://github.com/go-gitea/gitea/blob/master/LICENSE) file
|
||||
for the full license text.
|
||||
|
||||
## Screenshots
|
||||
Looking for an overview of the interface? Check it out!
|
||||
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
This project is licensed under the MIT License. See the [LICENSE](https://github.com/go-gitea/gitea/blob/master/LICENSE) file for the full license text.
|
||||
|
33
README_ZH.md
33
README_ZH.md
@@ -1,22 +1,25 @@
|
||||
[English](README.md)
|
||||
[English](https://github.com/go-gitea/gitea/blob/master/README.md)
|
||||
|
||||
<h1> <img src="https://raw.githubusercontent.com/go-gitea/gitea/master/public/img/gitea-192.png" alt="logo" width="30" height="30"> Gitea - Git with a cup of tea</h1>
|
||||
# Gitea - Git with a cup of tea
|
||||
|
||||
[](https://drone.gitea.io/go-gitea/gitea)
|
||||
[](https://discord.gg/NsatcWJ)
|
||||
[](https://gitter.im/go-gitea/gitea?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://microbadger.com/images/gitea/gitea "Get your own image badge on microbadger.com")
|
||||
[](https://codecov.io/gh/go-gitea/gitea)
|
||||
[](https://coverage.gitea.io/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://www.codetriage.com/go-gitea/gitea)
|
||||
[](https://opencollective.com/gitea)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://crowdin.com/project/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
|
||||
||||
|
||||
|:-------------:|:-------:|:-------:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
||||
## 目标
|
||||
|
||||
Gitea 的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用 Go 作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了 x86,amd64,还包括 ARM 和 PowerPC。
|
||||
Gitea的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了x86,amd64,还包括 ARM 和 PowerPC。
|
||||
|
||||
如果您想试用一下,请访问 [在线Demo](https://try.gitea.io/)!
|
||||
|
||||
@@ -28,7 +31,7 @@ Gitea 的首要目标是创建一个极易安装,运行非常快速,安装
|
||||
|
||||
## 文档
|
||||
|
||||
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/gitea) 和 QQ群 328432459 来和我们交流。
|
||||
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Gitter - 英文](https://gitter.im/go-gitea/gitea) 和 QQ群 328432459 来和我们交流。
|
||||
|
||||
## 贡献流程
|
||||
|
||||
@@ -43,11 +46,3 @@ Fork -> Patch -> Push -> Pull Request
|
||||
## 授权许可
|
||||
|
||||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/go-gitea/gitea/blob/master/LICENSE) 文件中。
|
||||
|
||||
## 截图
|
||||
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
|
160
assets/logo.svg
160
assets/logo.svg
@@ -1,160 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 135.46667 135.46667"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
inkscape:export-filename=""
|
||||
inkscape:export-xdpi="48.000004"
|
||||
inkscape:export-ydpi="48.000004">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.70710678"
|
||||
inkscape:cx="418.13805"
|
||||
inkscape:cy="177.57445"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
width="256px"
|
||||
showguides="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1137"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:measure-start="283.373,243.952"
|
||||
inkscape:measure-end="290.267,236.527">
|
||||
<sodipodi:guide
|
||||
position="0,0"
|
||||
orientation="0,512"
|
||||
id="guide3699"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="135.46667,0"
|
||||
orientation="-512,0"
|
||||
id="guide3701"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="135.46667,135.46667"
|
||||
orientation="0,-512"
|
||||
id="guide3703"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="0,135.46667"
|
||||
orientation="512,0"
|
||||
id="guide3705"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-161.53334)"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#609926;fill-opacity:1;stroke:#428f29;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 27.709937,195.15095 c -9.546573,-0.0272 -22.3392732,6.79805 -21.6317552,23.90397 1.105534,26.72889 25.4565952,29.20839 35.1916502,29.42301 1.068023,5.01357 12.521798,22.30563 21.001818,23.21667 h 37.15277 c 22.27763,-1.66785 38.9607,-75.75671 26.59321,-76.03825 -46.781583,2.47691 -49.995146,2.13838 -88.599758,0 -2.495053,-0.0266 -5.972321,-0.49474 -9.707935,-0.5054 z m 2.491319,9.45886 c 1.351378,13.69267 3.555849,21.70359 8.018216,33.94345 -11.382872,-1.50473 -21.069822,-5.22443 -22.851515,-19.10984 -0.950962,-7.4112 2.390428,-15.16769 14.833299,-14.83361 z"
|
||||
id="path3722"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sscccccsccsc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.24757317;stroke-opacity:1"
|
||||
id="rect4599"
|
||||
width="34.762054"
|
||||
height="34.762054"
|
||||
x="87.508659"
|
||||
y="18.291576"
|
||||
transform="rotate(25.914715)"
|
||||
ry="5.4825778" />
|
||||
<path
|
||||
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26644793px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 79.804947,57.359056 3.241146,1.609954 V 35.255731 h -3.262698 z"
|
||||
id="path4525"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Layer 3"
|
||||
style="display:inline">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4539">
|
||||
<circle
|
||||
transform="rotate(-19.796137)"
|
||||
r="3.4745038"
|
||||
cy="90.077766"
|
||||
cx="49.064713"
|
||||
id="path4606"
|
||||
style="fill:#609926;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" />
|
||||
<circle
|
||||
transform="rotate(-19.796137)"
|
||||
r="3.4745038"
|
||||
cy="102.1049"
|
||||
cx="36.810425"
|
||||
id="path4606-3"
|
||||
style="fill:#609926;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" />
|
||||
<circle
|
||||
transform="rotate(-19.796137)"
|
||||
r="3.4745038"
|
||||
cy="111.43928"
|
||||
cx="46.484283"
|
||||
id="path4606-1"
|
||||
style="fill:#609926;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="rotate(26.024158)"
|
||||
y="18.061695"
|
||||
x="97.333458"
|
||||
height="27.261492"
|
||||
width="2.6726954"
|
||||
id="rect4629-8"
|
||||
style="fill:#609926;fill-opacity:1;stroke:none;stroke-width:0.27444693;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4514"
|
||||
d="m 76.558096,68.116343 c 12.97589,6.395378 13.012989,4.101862 4.890858,20.907244"
|
||||
style="fill:none;stroke:#609926;stroke-width:2.68000007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.6 KiB |
534
cmd/admin.go
534
cmd/admin.go
@@ -6,33 +6,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth/oauth2"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
pwd "code.gitea.io/gitea/modules/password"
|
||||
"code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
// CmdAdmin represents the available admin sub-command.
|
||||
CmdAdmin = cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Command line interface to perform common administrative operations",
|
||||
Usage: "Perform admin operations on command line",
|
||||
Description: `Allow using internal logic of Gitea without hacking into the source code
|
||||
to make automatic initialization process more smoothly`,
|
||||
Subcommands: []cli.Command{
|
||||
subcmdCreateUser,
|
||||
subcmdChangePassword,
|
||||
subcmdRepoSyncReleases,
|
||||
subcmdRegenerate,
|
||||
subcmdAuth,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -43,519 +33,63 @@ var (
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Username. DEPRECATED: use username instead",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username",
|
||||
Value: "",
|
||||
Usage: "Username",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "password",
|
||||
Value: "",
|
||||
Usage: "User password",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "email",
|
||||
Value: "",
|
||||
Usage: "User email address",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "admin",
|
||||
Usage: "User is an admin",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "random-password",
|
||||
Usage: "Generate a random password for the user",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "random-password-length",
|
||||
Usage: "Length of the random password to be generated",
|
||||
Value: 12,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "access-token",
|
||||
Usage: "Generate access token for the user",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
subcmdChangePassword = cli.Command{
|
||||
Name: "change-password",
|
||||
Usage: "Change a user's password",
|
||||
Action: runChangePassword,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "username,u",
|
||||
Value: "",
|
||||
Usage: "The user to change password for",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "password,p",
|
||||
Value: "",
|
||||
Usage: "New password to set for user",
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
subcmdRepoSyncReleases = cli.Command{
|
||||
Name: "repo-sync-releases",
|
||||
Usage: "Synchronize repository releases with tags",
|
||||
Action: runRepoSyncReleases,
|
||||
}
|
||||
|
||||
subcmdRegenerate = cli.Command{
|
||||
Name: "regenerate",
|
||||
Usage: "Regenerate specific files",
|
||||
Subcommands: []cli.Command{
|
||||
microcmdRegenHooks,
|
||||
microcmdRegenKeys,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdRegenHooks = cli.Command{
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
}
|
||||
|
||||
microcmdRegenKeys = cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
}
|
||||
|
||||
subcmdAuth = cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Modify external auth providers",
|
||||
Subcommands: []cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
cmdAuthAddLdapBindDn,
|
||||
cmdAuthUpdateLdapBindDn,
|
||||
cmdAuthAddLdapSimpleAuth,
|
||||
cmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthList,
|
||||
microcmdAuthDelete,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthList = cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
}
|
||||
|
||||
idFlag = cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}
|
||||
|
||||
microcmdAuthDelete = cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
)
|
||||
|
||||
func runChangePassword(c *cli.Context) error {
|
||||
if err := argsSet(c, "username", "password"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !pwd.IsComplexEnough(c.String("password")) {
|
||||
return errors.New("Password does not meet complexity requirements")
|
||||
}
|
||||
uname := c.String("username")
|
||||
user, err := models.GetUserByName(uname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user.Salt, err = models.GetUserSalt(); err != nil {
|
||||
return err
|
||||
}
|
||||
user.HashPassword(c.String("password"))
|
||||
|
||||
if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCreateUser(c *cli.Context) error {
|
||||
if err := argsSet(c, "email"); err != nil {
|
||||
return err
|
||||
if !c.IsSet("name") {
|
||||
return fmt.Errorf("Username is not specified")
|
||||
} else if !c.IsSet("password") {
|
||||
return fmt.Errorf("Password is not specified")
|
||||
} else if !c.IsSet("email") {
|
||||
return fmt.Errorf("Email is not specified")
|
||||
}
|
||||
|
||||
if c.IsSet("name") && c.IsSet("username") {
|
||||
return errors.New("Cannot set both --name and --username flags")
|
||||
}
|
||||
if !c.IsSet("name") && !c.IsSet("username") {
|
||||
return errors.New("One of --name or --username flags must be set")
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if c.IsSet("password") && c.IsSet("random-password") {
|
||||
return errors.New("cannot set both -random-password and -password flags")
|
||||
setting.NewContext()
|
||||
models.LoadConfigs()
|
||||
|
||||
setting.NewXORMLogService(false)
|
||||
if err := models.SetEngine(); err != nil {
|
||||
return fmt.Errorf("models.SetEngine: %v", err)
|
||||
}
|
||||
|
||||
var username string
|
||||
if c.IsSet("username") {
|
||||
username = c.String("username")
|
||||
} else {
|
||||
username = c.String("name")
|
||||
fmt.Fprintf(os.Stderr, "--name flag is deprecated. Use --username instead.\n")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var password string
|
||||
if c.IsSet("password") {
|
||||
password = c.String("password")
|
||||
} else if c.IsSet("random-password") {
|
||||
var err error
|
||||
password, err = pwd.Generate(c.Int("random-password-length"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("generated random password is '%s'\n", password)
|
||||
} else {
|
||||
return errors.New("must set either password or random-password flag")
|
||||
}
|
||||
|
||||
// always default to true
|
||||
var changePassword = true
|
||||
|
||||
// If this is the first user being created.
|
||||
// Take it as the admin and don't force a password update.
|
||||
if n := models.CountUsers(); n == 0 {
|
||||
changePassword = false
|
||||
}
|
||||
|
||||
if c.IsSet("must-change-password") {
|
||||
changePassword = c.Bool("must-change-password")
|
||||
}
|
||||
|
||||
u := &models.User{
|
||||
Name: username,
|
||||
Email: c.String("email"),
|
||||
Passwd: password,
|
||||
IsActive: true,
|
||||
IsAdmin: c.Bool("admin"),
|
||||
MustChangePassword: changePassword,
|
||||
Theme: setting.UI.DefaultTheme,
|
||||
}
|
||||
|
||||
if err := models.CreateUser(u); err != nil {
|
||||
if err := models.CreateUser(&models.User{
|
||||
Name: c.String("name"),
|
||||
Email: c.String("email"),
|
||||
Passwd: c.String("password"),
|
||||
IsActive: true,
|
||||
IsAdmin: c.Bool("admin"),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("CreateUser: %v", err)
|
||||
}
|
||||
|
||||
if c.Bool("access-token") {
|
||||
t := &models.AccessToken{
|
||||
Name: "gitea-admin",
|
||||
UID: u.ID,
|
||||
}
|
||||
|
||||
if err := models.NewAccessToken(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Access token was successfully created... %s\n", t.Token)
|
||||
}
|
||||
|
||||
fmt.Printf("New user '%s' has been successfully created!\n", username)
|
||||
fmt.Printf("New user '%s' has been successfully created!\n", c.String("name"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func runRepoSyncReleases(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("Synchronizing repository releases (this may take a while)")
|
||||
for page := 1; ; page++ {
|
||||
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Page: page,
|
||||
PageSize: models.RepositoryListDefaultPageSize,
|
||||
Private: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("SearchRepositoryByName: %v", err)
|
||||
}
|
||||
if len(repos) == 0 {
|
||||
break
|
||||
}
|
||||
log.Trace("Processing next %d repos of %d", len(repos), count)
|
||||
for _, repo := range repos {
|
||||
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Warn("OpenRepository: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
oldnum, err := getReleaseCount(repo.ID)
|
||||
if err != nil {
|
||||
log.Warn(" GetReleaseCountByRepoID: %v", err)
|
||||
}
|
||||
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
||||
|
||||
if err = repository.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||
log.Warn(" SyncReleasesWithTags: %v", err)
|
||||
gitRepo.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
count, err = getReleaseCount(repo.ID)
|
||||
if err != nil {
|
||||
log.Warn(" GetReleaseCountByRepoID: %v", err)
|
||||
gitRepo.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
log.Trace(" repo %s releases synchronized to tags: from %d to %d",
|
||||
repo.FullName(), oldnum, count)
|
||||
gitRepo.Close()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getReleaseCount(id int64) (int64, error) {
|
||||
return models.GetReleaseCountByRepoID(
|
||||
id,
|
||||
models.FindReleasesOptions{
|
||||
IncludeTags: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func runRegenerateHooks(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
return models.SyncRepositoryHooks()
|
||||
}
|
||||
|
||||
func runRegenerateKeys(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
return models.RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *models.OAuth2Config {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &models.OAuth2Config{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return models.CreateLoginSource(&models.LoginSource{
|
||||
Type: models.LoginOAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActived: true,
|
||||
Cfg: parseOAuth2Config(c),
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := models.GetLoginSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.OAuth2()
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
var customURLMapping = &oauth2.CustomURLMapping{}
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return models.UpdateSource(source)
|
||||
}
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSources, err := models.LoginSources()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
for _, source := range loginSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", source.ID, source.Name, models.LoginNames[source.Type], source.IsActived)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := models.GetLoginSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return models.DeleteSource(source)
|
||||
}
|
||||
|
@@ -1,359 +0,0 @@
|
||||
// Copyright 2019 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth/ldap"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
type (
|
||||
authService struct {
|
||||
initDB func() error
|
||||
createLoginSource func(loginSource *models.LoginSource) error
|
||||
updateLoginSource func(loginSource *models.LoginSource) error
|
||||
getLoginSourceByID func(id int64) (*models.LoginSource, error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
commonLdapCLIFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Authentication name.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "not-active",
|
||||
Usage: "Deactivate the authentication source.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "security-protocol",
|
||||
Usage: "Security protocol name.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "skip-tls-verify",
|
||||
Usage: "Disable TLS verification.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "host",
|
||||
Usage: "The address where the LDAP server can be reached.",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "The port to use when connecting to the LDAP server.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user-search-base",
|
||||
Usage: "The LDAP base at which user accounts will be searched for.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user-filter",
|
||||
Usage: "An LDAP filter declaring how to find the user record that is attempting to authenticate.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "admin-filter",
|
||||
Usage: "An LDAP filter specifying if a user should be given administrator privileges.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "firstname-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user’s first name.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "surname-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user’s surname.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "email-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user’s email address.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "public-ssh-key-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
|
||||
},
|
||||
}
|
||||
|
||||
ldapBindDnCLIFlags = append(commonLdapCLIFlags,
|
||||
cli.StringFlag{
|
||||
Name: "bind-dn",
|
||||
Usage: "The DN to bind to the LDAP server with when searching for the user.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "bind-password",
|
||||
Usage: "The password for the Bind DN, if any.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "attributes-in-bind",
|
||||
Usage: "Fetch attributes in bind DN context.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "synchronize-users",
|
||||
Usage: "Enable user synchronization.",
|
||||
},
|
||||
cli.UintFlag{
|
||||
Name: "page-size",
|
||||
Usage: "Search page size.",
|
||||
})
|
||||
|
||||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
||||
cli.StringFlag{
|
||||
Name: "user-dn",
|
||||
Usage: "The user’s DN.",
|
||||
})
|
||||
|
||||
cmdAuthAddLdapBindDn = cli.Command{
|
||||
Name: "add-ldap",
|
||||
Usage: "Add new LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().addLdapBindDn(c)
|
||||
},
|
||||
Flags: ldapBindDnCLIFlags,
|
||||
}
|
||||
|
||||
cmdAuthUpdateLdapBindDn = cli.Command{
|
||||
Name: "update-ldap",
|
||||
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().updateLdapBindDn(c)
|
||||
},
|
||||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
||||
}
|
||||
|
||||
cmdAuthAddLdapSimpleAuth = cli.Command{
|
||||
Name: "add-ldap-simple",
|
||||
Usage: "Add new LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().addLdapSimpleAuth(c)
|
||||
},
|
||||
Flags: ldapSimpleAuthCLIFlags,
|
||||
}
|
||||
|
||||
cmdAuthUpdateLdapSimpleAuth = cli.Command{
|
||||
Name: "update-ldap-simple",
|
||||
Usage: "Update existing LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().updateLdapSimpleAuth(c)
|
||||
},
|
||||
Flags: append([]cli.Flag{idFlag}, ldapSimpleAuthCLIFlags...),
|
||||
}
|
||||
)
|
||||
|
||||
// newAuthService creates a service with default functions.
|
||||
func newAuthService() *authService {
|
||||
return &authService{
|
||||
initDB: initDB,
|
||||
createLoginSource: models.CreateLoginSource,
|
||||
updateLoginSource: models.UpdateSource,
|
||||
getLoginSourceByID: models.GetLoginSourceByID,
|
||||
}
|
||||
}
|
||||
|
||||
// parseLoginSource assigns values on loginSource according to command line flags.
|
||||
func parseLoginSource(c *cli.Context, loginSource *models.LoginSource) {
|
||||
if c.IsSet("name") {
|
||||
loginSource.Name = c.String("name")
|
||||
}
|
||||
if c.IsSet("not-active") {
|
||||
loginSource.IsActived = !c.Bool("not-active")
|
||||
}
|
||||
if c.IsSet("synchronize-users") {
|
||||
loginSource.IsSyncEnabled = c.Bool("synchronize-users")
|
||||
}
|
||||
}
|
||||
|
||||
// parseLdapConfig assigns values on config according to command line flags.
|
||||
func parseLdapConfig(c *cli.Context, config *models.LDAPConfig) error {
|
||||
if c.IsSet("name") {
|
||||
config.Source.Name = c.String("name")
|
||||
}
|
||||
if c.IsSet("host") {
|
||||
config.Source.Host = c.String("host")
|
||||
}
|
||||
if c.IsSet("port") {
|
||||
config.Source.Port = c.Int("port")
|
||||
}
|
||||
if c.IsSet("security-protocol") {
|
||||
p, ok := findLdapSecurityProtocolByName(c.String("security-protocol"))
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown security protocol name: %s", c.String("security-protocol"))
|
||||
}
|
||||
config.Source.SecurityProtocol = p
|
||||
}
|
||||
if c.IsSet("skip-tls-verify") {
|
||||
config.Source.SkipVerify = c.Bool("skip-tls-verify")
|
||||
}
|
||||
if c.IsSet("bind-dn") {
|
||||
config.Source.BindDN = c.String("bind-dn")
|
||||
}
|
||||
if c.IsSet("user-dn") {
|
||||
config.Source.UserDN = c.String("user-dn")
|
||||
}
|
||||
if c.IsSet("bind-password") {
|
||||
config.Source.BindPassword = c.String("bind-password")
|
||||
}
|
||||
if c.IsSet("user-search-base") {
|
||||
config.Source.UserBase = c.String("user-search-base")
|
||||
}
|
||||
if c.IsSet("username-attribute") {
|
||||
config.Source.AttributeUsername = c.String("username-attribute")
|
||||
}
|
||||
if c.IsSet("firstname-attribute") {
|
||||
config.Source.AttributeName = c.String("firstname-attribute")
|
||||
}
|
||||
if c.IsSet("surname-attribute") {
|
||||
config.Source.AttributeSurname = c.String("surname-attribute")
|
||||
}
|
||||
if c.IsSet("email-attribute") {
|
||||
config.Source.AttributeMail = c.String("email-attribute")
|
||||
}
|
||||
if c.IsSet("attributes-in-bind") {
|
||||
config.Source.AttributesInBind = c.Bool("attributes-in-bind")
|
||||
}
|
||||
if c.IsSet("public-ssh-key-attribute") {
|
||||
config.Source.AttributeSSHPublicKey = c.String("public-ssh-key-attribute")
|
||||
}
|
||||
if c.IsSet("page-size") {
|
||||
config.Source.SearchPageSize = uint32(c.Uint("page-size"))
|
||||
}
|
||||
if c.IsSet("user-filter") {
|
||||
config.Source.Filter = c.String("user-filter")
|
||||
}
|
||||
if c.IsSet("admin-filter") {
|
||||
config.Source.AdminFilter = c.String("admin-filter")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// findLdapSecurityProtocolByName finds security protocol by its name ignoring case.
|
||||
// It returns the value of the security protocol and if it was found.
|
||||
func findLdapSecurityProtocolByName(name string) (ldap.SecurityProtocol, bool) {
|
||||
for i, n := range models.SecurityProtocolNames {
|
||||
if strings.EqualFold(name, n) {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// getLoginSource gets the login source by its id defined in the command line flags.
|
||||
// It returns an error if the id is not set, does not match any source or if the source is not of expected type.
|
||||
func (a *authService) getLoginSource(c *cli.Context, loginType models.LoginType) (*models.LoginSource, error) {
|
||||
if err := argsSet(c, "id"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loginSource, err := a.getLoginSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if loginSource.Type != loginType {
|
||||
return nil, fmt.Errorf("Invalid authentication type. expected: %s, actual: %s", models.LoginNames[loginType], models.LoginNames[loginSource.Type])
|
||||
}
|
||||
|
||||
return loginSource, nil
|
||||
}
|
||||
|
||||
// addLdapBindDn adds a new LDAP via Bind DN authentication source.
|
||||
func (a *authService) addLdapBindDn(c *cli.Context) error {
|
||||
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-search-base", "user-filter", "email-attribute"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := a.initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSource := &models.LoginSource{
|
||||
Type: models.LoginLDAP,
|
||||
IsActived: true, // active by default
|
||||
Cfg: &models.LDAPConfig{
|
||||
Source: &ldap.Source{
|
||||
Enabled: true, // always true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
parseLoginSource(c, loginSource)
|
||||
if err := parseLdapConfig(c, loginSource.LDAP()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.createLoginSource(loginSource)
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP via Bind DN authentication source.
|
||||
func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
if err := a.initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSource, err := a.getLoginSource(c, models.LoginLDAP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parseLoginSource(c, loginSource)
|
||||
if err := parseLdapConfig(c, loginSource.LDAP()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.updateLoginSource(loginSource)
|
||||
}
|
||||
|
||||
// addLdapSimpleAuth adds a new LDAP (simple auth) authentication source.
|
||||
func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-dn", "user-filter", "email-attribute"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := a.initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSource := &models.LoginSource{
|
||||
Type: models.LoginDLDAP,
|
||||
IsActived: true, // active by default
|
||||
Cfg: &models.LDAPConfig{
|
||||
Source: &ldap.Source{
|
||||
Enabled: true, // always true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
parseLoginSource(c, loginSource)
|
||||
if err := parseLdapConfig(c, loginSource.LDAP()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.createLoginSource(loginSource)
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
|
||||
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
if err := a.initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loginSource, err := a.getLoginSource(c, models.LoginDLDAP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parseLoginSource(c, loginSource)
|
||||
if err := parseLdapConfig(c, loginSource.LDAP()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.updateLoginSource(loginSource)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
47
cmd/cert.go
47
cmd/cert.go
@@ -90,16 +90,16 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
||||
}
|
||||
}
|
||||
|
||||
func runCert(c *cli.Context) error {
|
||||
if err := argsSet(c, "host"); err != nil {
|
||||
return err
|
||||
func runCert(ctx *cli.Context) error {
|
||||
if len(ctx.String("host")) == 0 {
|
||||
log.Fatal("Missing required --host parameter")
|
||||
}
|
||||
|
||||
var priv interface{}
|
||||
var err error
|
||||
switch c.String("ecdsa-curve") {
|
||||
switch ctx.String("ecdsa-curve") {
|
||||
case "":
|
||||
priv, err = rsa.GenerateKey(rand.Reader, c.Int("rsa-bits"))
|
||||
priv, err = rsa.GenerateKey(rand.Reader, ctx.Int("rsa-bits"))
|
||||
case "P224":
|
||||
priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
|
||||
case "P256":
|
||||
@@ -109,23 +109,23 @@ func runCert(c *cli.Context) error {
|
||||
case "P521":
|
||||
priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
||||
default:
|
||||
log.Fatalf("Unrecognized elliptic curve: %q", c.String("ecdsa-curve"))
|
||||
log.Fatalf("Unrecognized elliptic curve: %q", ctx.String("ecdsa-curve"))
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate private key: %v", err)
|
||||
}
|
||||
|
||||
var notBefore time.Time
|
||||
if startDate := c.String("start-date"); startDate != "" {
|
||||
notBefore, err = time.Parse("Jan 2 15:04:05 2006", startDate)
|
||||
if len(ctx.String("start-date")) == 0 {
|
||||
notBefore = time.Now()
|
||||
} else {
|
||||
notBefore, err = time.Parse("Jan 2 15:04:05 2006", ctx.String("start-date"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse creation date: %v", err)
|
||||
}
|
||||
} else {
|
||||
notBefore = time.Now()
|
||||
}
|
||||
|
||||
notAfter := notBefore.Add(c.Duration("duration"))
|
||||
notAfter := notBefore.Add(ctx.Duration("duration"))
|
||||
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
@@ -147,7 +147,7 @@ func runCert(c *cli.Context) error {
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
hosts := strings.Split(c.String("host"), ",")
|
||||
hosts := strings.Split(ctx.String("host"), ",")
|
||||
for _, h := range hosts {
|
||||
if ip := net.ParseIP(h); ip != nil {
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
@@ -156,7 +156,7 @@ func runCert(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if c.Bool("ca") {
|
||||
if ctx.Bool("ca") {
|
||||
template.IsCA = true
|
||||
template.KeyUsage |= x509.KeyUsageCertSign
|
||||
}
|
||||
@@ -170,28 +170,17 @@ func runCert(c *cli.Context) error {
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open cert.pem for writing: %v", err)
|
||||
}
|
||||
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encode certificate: %v", err)
|
||||
}
|
||||
err = certOut.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to write cert: %v", err)
|
||||
}
|
||||
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
certOut.Close()
|
||||
log.Println("Written cert.pem")
|
||||
|
||||
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open key.pem for writing: %v", err)
|
||||
}
|
||||
err = pem.Encode(keyOut, pemBlockForKey(priv))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encode key: %v", err)
|
||||
}
|
||||
err = keyOut.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to write key: %v", err)
|
||||
}
|
||||
pem.Encode(keyOut, pemBlockForKey(priv))
|
||||
keyOut.Close()
|
||||
log.Println("Written key.pem")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
48
cmd/cmd.go
48
cmd/cmd.go
@@ -1,48 +0,0 @@
|
||||
// Copyright 2018 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 cmd provides subcommands to the gitea binary - such as "web" or
|
||||
// "admin".
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// argsSet checks that all the required arguments are set. args is a list of
|
||||
// arguments that must be set in the passed Context.
|
||||
func argsSet(c *cli.Context, args ...string) error {
|
||||
for _, a := range args {
|
||||
if !c.IsSet(a) {
|
||||
return errors.New(a + " is not set")
|
||||
}
|
||||
|
||||
if util.IsEmptyString(a) {
|
||||
return errors.New(a + " is required")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initDB() error {
|
||||
return initDBDisableConsole(false)
|
||||
}
|
||||
|
||||
func initDBDisableConsole(disableConsole bool) error {
|
||||
setting.NewContext()
|
||||
setting.InitDBConfig()
|
||||
|
||||
setting.NewXORMLogService(disableConsole)
|
||||
if err := models.SetEngine(); err != nil {
|
||||
return fmt.Errorf("models.SetEngine: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
// Copyright 2019 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdConvert represents the available convert sub-command.
|
||||
var CmdConvert = cli.Command{
|
||||
Name: "convert",
|
||||
Usage: "Convert the database",
|
||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4",
|
||||
Action: runConvert,
|
||||
}
|
||||
|
||||
func runConvert(ctx *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("AppPath: %s", setting.AppPath)
|
||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||
log.Trace("Custom path: %s", setting.CustomPath)
|
||||
log.Trace("Log path: %s", setting.LogRootPath)
|
||||
setting.InitDBConfig()
|
||||
|
||||
if !setting.Database.UseMySQL {
|
||||
fmt.Println("This command can only be used with a MySQL database")
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := models.ConvertUtf8ToUtf8mb4(); err != nil {
|
||||
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
||||
|
||||
return nil
|
||||
}
|
121
cmd/dump.go
121
cmd/dump.go
@@ -8,17 +8,16 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/unknwon/cae/zip"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@@ -31,12 +30,12 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "file, f",
|
||||
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
||||
Usage: "Name of the dump file which will be created.",
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "verbose, V",
|
||||
Name: "verbose, v",
|
||||
Usage: "Show process details",
|
||||
},
|
||||
cli.StringFlag{
|
||||
@@ -48,21 +47,16 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
Name: "database, d",
|
||||
Usage: "Specify the database SQL syntax",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "skip-repository, R",
|
||||
Usage: "Skip the repository dumping",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func fatal(format string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
log.Fatal(format, args...)
|
||||
}
|
||||
|
||||
func runDump(ctx *cli.Context) error {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
setting.NewContext()
|
||||
setting.NewServices() // cannot access session settings otherwise
|
||||
models.LoadConfigs()
|
||||
|
||||
err := models.SetEngine()
|
||||
if err != nil {
|
||||
@@ -71,105 +65,90 @@ func runDump(ctx *cli.Context) error {
|
||||
|
||||
tmpDir := ctx.String("tempdir")
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
fatal("Path does not exist: %s", tmpDir)
|
||||
log.Fatalf("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
tmpWorkDir, err := ioutil.TempDir(tmpDir, "gitea-dump-")
|
||||
TmpWorkDir, err := ioutil.TempDir(tmpDir, "gitea-dump-")
|
||||
if err != nil {
|
||||
fatal("Failed to create tmp work directory: %v", err)
|
||||
log.Fatalf("Failed to create tmp work directory: %v", err)
|
||||
}
|
||||
log.Info("Creating tmp work dir: %s", tmpWorkDir)
|
||||
log.Printf("Creating tmp work dir: %s", TmpWorkDir)
|
||||
|
||||
// work-around #1103
|
||||
if os.Getenv("TMPDIR") == "" {
|
||||
os.Setenv("TMPDIR", tmpWorkDir)
|
||||
}
|
||||
|
||||
dbDump := path.Join(tmpWorkDir, "gitea-db.sql")
|
||||
|
||||
fileName := ctx.String("file")
|
||||
log.Info("Packing dump files...")
|
||||
z, err := zip.Create(fileName)
|
||||
if err != nil {
|
||||
fatal("Failed to create %s: %v", fileName, err)
|
||||
}
|
||||
reposDump := path.Join(TmpWorkDir, "gitea-repo.zip")
|
||||
dbDump := path.Join(TmpWorkDir, "gitea-db.sql")
|
||||
|
||||
log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
|
||||
zip.Verbose = ctx.Bool("verbose")
|
||||
|
||||
if ctx.IsSet("skip-repository") {
|
||||
log.Info("Skip dumping local repositories")
|
||||
} else {
|
||||
log.Info("Dumping local repositories...%s", setting.RepoRootPath)
|
||||
reposDump := path.Join(tmpWorkDir, "gitea-repo.zip")
|
||||
if err := zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
|
||||
fatal("Failed to dump local repositories: %v", err)
|
||||
}
|
||||
if err := z.AddFile("gitea-repo.zip", reposDump); err != nil {
|
||||
fatal("Failed to include gitea-repo.zip: %v", err)
|
||||
}
|
||||
if err := zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
|
||||
log.Fatalf("Failed to dump local repositories: %v", err)
|
||||
}
|
||||
|
||||
targetDBType := ctx.String("database")
|
||||
if len(targetDBType) > 0 && targetDBType != setting.Database.Type {
|
||||
log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType)
|
||||
if len(targetDBType) > 0 && targetDBType != models.DbCfg.Type {
|
||||
log.Printf("Dumping database %s => %s...", models.DbCfg.Type, targetDBType)
|
||||
} else {
|
||||
log.Info("Dumping database...")
|
||||
log.Printf("Dumping database...")
|
||||
}
|
||||
|
||||
if err := models.DumpDatabase(dbDump, targetDBType); err != nil {
|
||||
fatal("Failed to dump database: %v", err)
|
||||
log.Fatalf("Failed to dump database: %v", err)
|
||||
}
|
||||
|
||||
fileName := fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix())
|
||||
log.Printf("Packing dump files...")
|
||||
z, err := zip.Create(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
if err := z.AddFile("gitea-repo.zip", reposDump); err != nil {
|
||||
log.Fatalf("Failed to include gitea-repo.zip: %v", err)
|
||||
}
|
||||
if err := z.AddFile("gitea-db.sql", dbDump); err != nil {
|
||||
fatal("Failed to include gitea-db.sql: %v", err)
|
||||
log.Fatalf("Failed to include gitea-db.sql: %v", err)
|
||||
}
|
||||
|
||||
if len(setting.CustomConf) > 0 {
|
||||
log.Info("Adding custom configuration file from %s", setting.CustomConf)
|
||||
if err := z.AddFile("app.ini", setting.CustomConf); err != nil {
|
||||
fatal("Failed to include specified app.ini: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
customDir, err := os.Stat(setting.CustomPath)
|
||||
if err == nil && customDir.IsDir() {
|
||||
if err := z.AddDir("custom", setting.CustomPath); err != nil {
|
||||
fatal("Failed to include custom: %v", err)
|
||||
log.Fatalf("Failed to include custom: %v", err)
|
||||
}
|
||||
} else {
|
||||
log.Info("Custom dir %s doesn't exist, skipped", setting.CustomPath)
|
||||
log.Printf("Custom dir %s doesn't exist, skipped", setting.CustomPath)
|
||||
}
|
||||
|
||||
if com.IsExist(setting.AppDataPath) {
|
||||
log.Info("Packing data directory...%s", setting.AppDataPath)
|
||||
log.Printf("Packing data directory...%s", setting.AppDataPath)
|
||||
|
||||
var sessionAbsPath string
|
||||
if setting.SessionConfig.Provider == "file" {
|
||||
sessionAbsPath = setting.SessionConfig.ProviderConfig
|
||||
if len(setting.SessionConfig.ProviderConfig) == 0 {
|
||||
setting.SessionConfig.ProviderConfig = "data/sessions"
|
||||
}
|
||||
sessionAbsPath, _ = filepath.Abs(setting.SessionConfig.ProviderConfig)
|
||||
}
|
||||
if err := zipAddDirectoryExclude(z, "data", setting.AppDataPath, sessionAbsPath); err != nil {
|
||||
fatal("Failed to include data directory: %v", err)
|
||||
log.Fatalf("Failed to include data directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
fatal("Failed to include log: %v", err)
|
||||
log.Fatalf("Failed to include log: %v", err)
|
||||
}
|
||||
|
||||
if err = z.Close(); err != nil {
|
||||
_ = os.Remove(fileName)
|
||||
fatal("Failed to save %s: %v", fileName, err)
|
||||
log.Fatalf("Failed to save %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
if err := os.Chmod(fileName, 0600); err != nil {
|
||||
log.Info("Can't change file access permissions mask to 0600: %v", err)
|
||||
log.Printf("Can't change file access permissions mask to 0600: %v", err)
|
||||
}
|
||||
|
||||
log.Info("Removing tmp work dir: %s", tmpWorkDir)
|
||||
log.Printf("Removing tmp work dir: %s", TmpWorkDir)
|
||||
|
||||
if err := os.RemoveAll(tmpWorkDir); err != nil {
|
||||
fatal("Failed to remove %s: %v", tmpWorkDir, err)
|
||||
if err := os.RemoveAll(TmpWorkDir); err != nil {
|
||||
log.Fatalf("Failed to remove %s: %v", TmpWorkDir, err)
|
||||
}
|
||||
log.Info("Finish dumping in file %s", fileName)
|
||||
log.Printf("Finish dumping in file %s", fileName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,84 +0,0 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2016 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
// CmdGenerate represents the available generate sub-command.
|
||||
CmdGenerate = cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "Command line interface for running generators",
|
||||
Subcommands: []cli.Command{
|
||||
subcmdSecret,
|
||||
},
|
||||
}
|
||||
|
||||
subcmdSecret = cli.Command{
|
||||
Name: "secret",
|
||||
Usage: "Generate a secret token",
|
||||
Subcommands: []cli.Command{
|
||||
microcmdGenerateInternalToken,
|
||||
microcmdGenerateLfsJwtSecret,
|
||||
microcmdGenerateSecretKey,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdGenerateInternalToken = cli.Command{
|
||||
Name: "INTERNAL_TOKEN",
|
||||
Usage: "Generate a new INTERNAL_TOKEN",
|
||||
Action: runGenerateInternalToken,
|
||||
}
|
||||
|
||||
microcmdGenerateLfsJwtSecret = cli.Command{
|
||||
Name: "JWT_SECRET",
|
||||
Aliases: []string{"LFS_JWT_SECRET"},
|
||||
Usage: "Generate a new JWT_SECRET",
|
||||
Action: runGenerateLfsJwtSecret,
|
||||
}
|
||||
|
||||
microcmdGenerateSecretKey = cli.Command{
|
||||
Name: "SECRET_KEY",
|
||||
Usage: "Generate a new SECRET_KEY",
|
||||
Action: runGenerateSecretKey,
|
||||
}
|
||||
)
|
||||
|
||||
func runGenerateInternalToken(c *cli.Context) error {
|
||||
internalToken, err := generate.NewInternalToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", internalToken)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
JWTSecretBase64, err := generate.NewJwtSecret()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", JWTSecretBase64)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGenerateSecretKey(c *cli.Context) error {
|
||||
secretKey, err := generate.NewSecretKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", secretKey)
|
||||
return nil
|
||||
}
|
392
cmd/hook.go
392
cmd/hook.go
@@ -7,33 +7,39 @@ package cmd
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/httplib"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
hookBatchSize = 30
|
||||
)
|
||||
|
||||
var (
|
||||
// CmdHook represents the available hooks sub-command.
|
||||
CmdHook = cli.Command{
|
||||
Name: "hook",
|
||||
Usage: "Delegate commands to corresponding Git hooks",
|
||||
Description: "This should only be called by Git",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
Subcommands: []cli.Command{
|
||||
subcmdHookPreReceive,
|
||||
subcmdHookUpdate,
|
||||
subcmdHookUpadte,
|
||||
subcmdHookPostReceive,
|
||||
},
|
||||
}
|
||||
@@ -44,7 +50,7 @@ var (
|
||||
Description: "This command should only be called by Git",
|
||||
Action: runHookPreReceive,
|
||||
}
|
||||
subcmdHookUpdate = cli.Command{
|
||||
subcmdHookUpadte = cli.Command{
|
||||
Name: "update",
|
||||
Usage: "Delegate update Git hook",
|
||||
Description: "This command should only be called by Git",
|
||||
@@ -59,49 +65,126 @@ var (
|
||||
)
|
||||
|
||||
func runHookPreReceive(c *cli.Context) error {
|
||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
setup("hooks/pre-receive.log", false)
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
fail(`Rejecting changes as Gitea environment not set.
|
||||
If you are pushing over SSH you must push with a key managed by
|
||||
Gitea or set your environment appropriately.`, "")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
if err := setup("hooks/pre-receive.log"); err != nil {
|
||||
fail("Hook pre-receive init failed", fmt.Sprintf("setup: %v", err))
|
||||
}
|
||||
|
||||
// the environment setted on serv command
|
||||
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
|
||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||
username := os.Getenv(models.EnvRepoUsername)
|
||||
reponame := os.Getenv(models.EnvRepoName)
|
||||
userID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
|
||||
prID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchPRID), 10, 64)
|
||||
isDeployKey, _ := strconv.ParseBool(os.Getenv(models.EnvIsDeployKey))
|
||||
//username := os.Getenv(models.EnvRepoUsername)
|
||||
//reponame := os.Getenv(models.EnvRepoName)
|
||||
//repoPath := models.RepoPath(username, reponame)
|
||||
|
||||
hookOptions := private.HookOptions{
|
||||
UserID: userID,
|
||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||
ProtectedBranchID: prID,
|
||||
IsDeployKey: isDeployKey,
|
||||
buf := bytes.NewBuffer(nil)
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
buf.Write(scanner.Bytes())
|
||||
buf.WriteByte('\n')
|
||||
|
||||
// TODO: support news feeds for wiki
|
||||
if isWiki {
|
||||
continue
|
||||
}
|
||||
|
||||
fields := bytes.Fields(scanner.Bytes())
|
||||
if len(fields) != 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
//oldCommitID := string(fields[0])
|
||||
newCommitID := string(fields[1])
|
||||
refFullName := string(fields[2])
|
||||
|
||||
// FIXME: when we add feature to protected branch to deny force push, then uncomment below
|
||||
/*var isForce bool
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect force push: %v", err)
|
||||
} else if len(output) > 0 {
|
||||
isForce = true
|
||||
}
|
||||
}*/
|
||||
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
protectBranch, err := models.GetProtectedBranchBy(repoID, branchName)
|
||||
if err != nil {
|
||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
||||
}
|
||||
|
||||
if protectBranch != nil {
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
} else {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
//fail(fmt.Sprintf("branch %s is protected from force push", branchName), "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
if err := setup("hooks/update.log"); err != nil {
|
||||
fail("Hook update init failed", fmt.Sprintf("setup: %v", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookPostReceive(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
if err := setup("hooks/post-receive.log"); err != nil {
|
||||
fail("Hook post-receive init failed", fmt.Sprintf("setup: %v", err))
|
||||
}
|
||||
|
||||
// the environment setted on serv command
|
||||
repoUser := os.Getenv(models.EnvRepoUsername)
|
||||
repoUserSalt := os.Getenv(models.EnvRepoUserSalt)
|
||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||
repoName := os.Getenv(models.EnvRepoName)
|
||||
pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
|
||||
pusherName := os.Getenv(models.EnvPusherName)
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
oldCommitIDs := make([]string, hookBatchSize)
|
||||
newCommitIDs := make([]string, hookBatchSize)
|
||||
refFullNames := make([]string, hookBatchSize)
|
||||
count := 0
|
||||
total := 0
|
||||
lastline := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
buf.Write(scanner.Bytes())
|
||||
buf.WriteByte('\n')
|
||||
|
||||
// TODO: support news feeds for wiki
|
||||
if isWiki {
|
||||
continue
|
||||
@@ -115,221 +198,36 @@ Gitea or set your environment appropriately.`, "")
|
||||
oldCommitID := string(fields[0])
|
||||
newCommitID := string(fields[1])
|
||||
refFullName := string(fields[2])
|
||||
total++
|
||||
lastline++
|
||||
|
||||
// If the ref is a branch, check if it's protected
|
||||
if strings.HasPrefix(refFullName, git.BranchPrefix) {
|
||||
oldCommitIDs[count] = oldCommitID
|
||||
newCommitIDs[count] = newCommitID
|
||||
refFullNames[count] = refFullName
|
||||
count++
|
||||
fmt.Fprintf(os.Stdout, "*")
|
||||
os.Stdout.Sync()
|
||||
if err := models.PushUpdate(models.PushUpdateOptions{
|
||||
RefFullName: refFullName,
|
||||
OldCommitID: oldCommitID,
|
||||
NewCommitID: newCommitID,
|
||||
PusherID: pusherID,
|
||||
PusherName: pusherName,
|
||||
RepoUserName: repoUser,
|
||||
RepoName: repoName,
|
||||
}); err != nil {
|
||||
log.GitLogger.Error(2, "Update: %v", err)
|
||||
}
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
||||
os.Stdout.Sync()
|
||||
// Ask for running deliver hook and test pull request tasks.
|
||||
reqURL := setting.LocalURL + repoUser + "/" + repoName + "/tasks/trigger?branch=" +
|
||||
strings.TrimPrefix(refFullName, git.BranchPrefix) + "&secret=" + base.EncodeMD5(repoUserSalt) + "&pusher=" + com.ToStr(pusherID)
|
||||
log.GitLogger.Trace("Trigger task: %s", reqURL)
|
||||
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
|
||||
switch statusCode {
|
||||
case http.StatusOK:
|
||||
// no-op
|
||||
case http.StatusInternalServerError:
|
||||
fail("Internal Server Error", msg)
|
||||
default:
|
||||
fail(msg, "")
|
||||
}
|
||||
count = 0
|
||||
lastline = 0
|
||||
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}).Response()
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode/100 != 2 {
|
||||
log.GitLogger.Error(2, "Failed to trigger task: not 2xx response code")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stdout, ".")
|
||||
os.Stdout.Sync()
|
||||
}
|
||||
if lastline >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
os.Stdout.Sync()
|
||||
lastline = 0
|
||||
log.GitLogger.Error(2, "Failed to trigger task: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
|
||||
os.Stdout.Sync()
|
||||
|
||||
statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
fail("Internal Server Error", msg)
|
||||
case http.StatusForbidden:
|
||||
fail(msg, "")
|
||||
}
|
||||
} else if lastline > 0 {
|
||||
fmt.Fprintf(os.Stdout, "\n")
|
||||
os.Stdout.Sync()
|
||||
lastline = 0
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, "Checked %d references in total\n", total)
|
||||
os.Stdout.Sync()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
// Update is empty and is kept only for backwards compatibility
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookPostReceive(c *cli.Context) error {
|
||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||
return nil
|
||||
}
|
||||
|
||||
setup("hooks/post-receive.log", false)
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
fail(`Rejecting changes as Gitea environment not set.
|
||||
If you are pushing over SSH you must push with a key managed by
|
||||
Gitea or set your environment appropriately.`, "")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// the environment setted on serv command
|
||||
repoUser := os.Getenv(models.EnvRepoUsername)
|
||||
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
|
||||
repoName := os.Getenv(models.EnvRepoName)
|
||||
pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
|
||||
pusherName := os.Getenv(models.EnvPusherName)
|
||||
|
||||
hookOptions := private.HookOptions{
|
||||
UserName: pusherName,
|
||||
UserID: pusherID,
|
||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||
}
|
||||
oldCommitIDs := make([]string, hookBatchSize)
|
||||
newCommitIDs := make([]string, hookBatchSize)
|
||||
refFullNames := make([]string, hookBatchSize)
|
||||
count := 0
|
||||
total := 0
|
||||
wasEmpty := false
|
||||
masterPushed := false
|
||||
results := make([]private.HookPostReceiveBranchResult, 0)
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
// TODO: support news feeds for wiki
|
||||
if isWiki {
|
||||
continue
|
||||
}
|
||||
|
||||
fields := bytes.Fields(scanner.Bytes())
|
||||
if len(fields) != 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, ".")
|
||||
oldCommitIDs[count] = string(fields[0])
|
||||
newCommitIDs[count] = string(fields[1])
|
||||
refFullNames[count] = string(fields[2])
|
||||
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
|
||||
masterPushed = true
|
||||
}
|
||||
count++
|
||||
total++
|
||||
os.Stdout.Sync()
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
||||
os.Stdout.Sync()
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
hookPrintResults(results)
|
||||
fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
if wasEmpty && masterPushed {
|
||||
// We need to tell the repo to reset the default branch to master
|
||||
err := private.SetDefaultBranch(repoUser, repoName, "master")
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
|
||||
os.Stdout.Sync()
|
||||
|
||||
hookPrintResults(results)
|
||||
return nil
|
||||
}
|
||||
|
||||
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
|
||||
os.Stdout.Sync()
|
||||
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
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()
|
||||
|
||||
if wasEmpty && masterPushed {
|
||||
// We need to tell the repo to reset the default branch to master
|
||||
err := private.SetDefaultBranch(repoUser, repoName, "master")
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
hookPrintResults(results)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func hookPrintResults(results []private.HookPostReceiveBranchResult) {
|
||||
for _, res := range results {
|
||||
if !res.Message {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if res.Create {
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res.Branch)
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
}
|
||||
|
73
cmd/keys.go
73
cmd/keys.go
@@ -1,73 +0,0 @@
|
||||
// Copyright 2018 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 cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdKeys represents the available keys sub-command
|
||||
var CmdKeys = cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Action: runKeys,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "expected, e",
|
||||
Value: "git",
|
||||
Usage: "Expected user for whom provide key commands",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username, u",
|
||||
Value: "",
|
||||
Usage: "Username trying to log in by SSH",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "type, t",
|
||||
Value: "",
|
||||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "content, k",
|
||||
Value: "",
|
||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runKeys(c *cli.Context) error {
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("No username provided")
|
||||
}
|
||||
// Check username matches the expected username
|
||||
if strings.TrimSpace(c.String("username")) != strings.TrimSpace(c.String("expected")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
content := ""
|
||||
|
||||
if c.IsSet("type") && c.IsSet("content") {
|
||||
content = fmt.Sprintf("%s %s", strings.TrimSpace(c.String("type")), strings.TrimSpace(c.String("content")))
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
return errors.New("No key type and content provided")
|
||||
}
|
||||
|
||||
setup("keys.log", false)
|
||||
|
||||
authorizedString, err := private.AuthorizedPublicKeyByContent(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(strings.TrimSpace(authorizedString))
|
||||
return nil
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
// Copyright 2018 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 cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdMigrate represents the available migrate sub-command.
|
||||
var CmdMigrate = cli.Command{
|
||||
Name: "migrate",
|
||||
Usage: "Migrate the database",
|
||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
||||
Action: runMigrate,
|
||||
}
|
||||
|
||||
func runMigrate(ctx *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("AppPath: %s", setting.AppPath)
|
||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||
log.Trace("Custom path: %s", setting.CustomPath)
|
||||
log.Trace("Log path: %s", setting.LogRootPath)
|
||||
setting.InitDBConfig()
|
||||
|
||||
if err := models.NewEngine(context.Background(), migrations.Migrate); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
231
cmd/serv.go
231
cmd/serv.go
@@ -8,26 +8,22 @@ package cmd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/pprof"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
accessDenied = "Repository does not exist or you do not have access"
|
||||
lfsAuthenticateVerb = "git-lfs-authenticate"
|
||||
)
|
||||
|
||||
@@ -38,23 +34,28 @@ var CmdServ = cli.Command{
|
||||
Description: `Serv provide access auth for repositories`,
|
||||
Action: runServ,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "enable-pprof",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func setup(logPath string, debug bool) {
|
||||
if !debug {
|
||||
_ = log.DelLogger("console")
|
||||
}
|
||||
func setup(logPath string) error {
|
||||
setting.NewContext()
|
||||
if debug {
|
||||
setting.ProdMode = false
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
models.LoadConfigs()
|
||||
|
||||
if setting.UseSQLite3 || setting.UseTiDB {
|
||||
workDir, _ := setting.WorkDir()
|
||||
if err := os.Chdir(workDir); err != nil {
|
||||
log.GitLogger.Fatal(4, "Failed to change directory %s: %v", workDir, err)
|
||||
}
|
||||
}
|
||||
|
||||
setting.NewXORMLogService(true)
|
||||
return models.SetEngine()
|
||||
}
|
||||
|
||||
func parseCmd(cmd string) (string, string) {
|
||||
@@ -81,14 +82,22 @@ func fail(userMessage, logMessage string, args ...interface{}) {
|
||||
if !setting.ProdMode {
|
||||
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
||||
}
|
||||
log.GitLogger.Fatal(3, logMessage, args...)
|
||||
return
|
||||
}
|
||||
|
||||
log.GitLogger.Close()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func runServ(c *cli.Context) error {
|
||||
// FIXME: This needs to internationalised
|
||||
setup("serv.log", c.Bool("debug"))
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := setup("serv.log"); err != nil {
|
||||
fail("System init failed", fmt.Sprintf("setup: %v", err))
|
||||
}
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
println("Gitea: SSH has been disabled")
|
||||
@@ -96,29 +105,12 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(c.Args()) < 1 {
|
||||
if err := cli.ShowSubcommandHelp(c); err != nil {
|
||||
fmt.Printf("error showing subcommand help: %v\n", err)
|
||||
}
|
||||
return nil
|
||||
fail("Not enough arguments", "Not enough arguments")
|
||||
}
|
||||
|
||||
keys := strings.Split(c.Args()[0], "-")
|
||||
if len(keys) != 2 || keys[0] != "key" {
|
||||
fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
}
|
||||
keyID := com.StrTo(keys[1]).MustInt64()
|
||||
|
||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||
if len(cmd) == 0 {
|
||||
key, user, err := private.ServNoCommand(keyID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Failed to check provided key: %v", err)
|
||||
}
|
||||
if key.Type == models.KeyTypeDeploy {
|
||||
println("Hi there! You've successfully authenticated with the deploy key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||
} else {
|
||||
println("Hi there, " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||
}
|
||||
println("Hi there, You've successfully authenticated, but Gitea does not provide shell access.")
|
||||
println("If this is unexpected, please log in with password and setup Gitea under another user.")
|
||||
return nil
|
||||
}
|
||||
@@ -131,8 +123,8 @@ func runServ(c *cli.Context) error {
|
||||
fail("Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
|
||||
}
|
||||
|
||||
argsSplit := strings.Split(args, " ")
|
||||
if len(argsSplit) >= 2 {
|
||||
if strings.Contains(args, " ") {
|
||||
argsSplit := strings.SplitN(args, " ", 2)
|
||||
args = strings.TrimSpace(argsSplit[0])
|
||||
lfsVerb = strings.TrimSpace(argsSplit[1])
|
||||
}
|
||||
@@ -147,22 +139,36 @@ func runServ(c *cli.Context) error {
|
||||
username := strings.ToLower(rr[0])
|
||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||
|
||||
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)
|
||||
}
|
||||
isWiki := false
|
||||
if strings.HasSuffix(reponame, ".wiki") {
|
||||
isWiki = true
|
||||
reponame = reponame[:len(reponame)-5]
|
||||
}
|
||||
|
||||
stopCPUProfiler, err := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "Unable to start CPU profile: %v", err)
|
||||
os.Setenv(models.EnvRepoUsername, username)
|
||||
if isWiki {
|
||||
os.Setenv(models.EnvRepoIsWiki, "true")
|
||||
} else {
|
||||
os.Setenv(models.EnvRepoIsWiki, "false")
|
||||
}
|
||||
os.Setenv(models.EnvRepoName, reponame)
|
||||
|
||||
repoUser, err := models.GetUserByName(username)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
fail("Repository owner does not exist", "Unregistered owner: %s", username)
|
||||
}
|
||||
defer func() {
|
||||
stopCPUProfiler()
|
||||
err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "Unable to dump Mem Profile: %v", err)
|
||||
}
|
||||
}()
|
||||
fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
|
||||
}
|
||||
|
||||
os.Setenv(models.EnvRepoUserSalt, repoUser.Salt)
|
||||
|
||||
repo, err := models.GetRepositoryByName(repoUser.ID, reponame)
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
fail(accessDenied, "Repository does not exist: %s/%s", repoUser.Name, reponame)
|
||||
}
|
||||
fail("Internal error", "Failed to get repository: %v", err)
|
||||
}
|
||||
|
||||
requestedMode, has := allowedCommands[verb]
|
||||
@@ -173,48 +179,88 @@ func runServ(c *cli.Context) error {
|
||||
if verb == lfsAuthenticateVerb {
|
||||
if lfsVerb == "upload" {
|
||||
requestedMode = models.AccessModeWrite
|
||||
} else if lfsVerb == "download" {
|
||||
requestedMode = models.AccessModeRead
|
||||
} else {
|
||||
fail("Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
||||
requestedMode = models.AccessModeRead
|
||||
}
|
||||
}
|
||||
|
||||
results, err := private.ServCommand(keyID, username, reponame, requestedMode, verb, lfsVerb)
|
||||
if err != nil {
|
||||
if private.IsErrServCommand(err) {
|
||||
errServCommand := err.(private.ErrServCommand)
|
||||
if errServCommand.StatusCode != http.StatusInternalServerError {
|
||||
fail("Unauthorized", "%s", errServCommand.Error())
|
||||
} else {
|
||||
fail("Internal Server Error", "%s", errServCommand.Error())
|
||||
}
|
||||
}
|
||||
fail("Internal Server Error", "%s", err.Error())
|
||||
// Prohibit push to mirror repositories.
|
||||
if requestedMode > models.AccessModeRead && repo.IsMirror {
|
||||
fail("mirror repository is read-only", "")
|
||||
}
|
||||
|
||||
// Allow anonymous clone for public repositories.
|
||||
var (
|
||||
keyID int64
|
||||
user *models.User
|
||||
)
|
||||
if requestedMode == models.AccessModeWrite || repo.IsPrivate {
|
||||
keys := strings.Split(c.Args()[0], "-")
|
||||
if len(keys) != 2 {
|
||||
fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
}
|
||||
|
||||
key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
|
||||
if err != nil {
|
||||
fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
|
||||
}
|
||||
keyID = key.ID
|
||||
|
||||
// Check deploy key or user key.
|
||||
if key.Type == models.KeyTypeDeploy {
|
||||
if key.Mode < requestedMode {
|
||||
fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
|
||||
}
|
||||
// Check if this deploy key belongs to current repository.
|
||||
if !models.HasDeployKey(key.ID, repo.ID) {
|
||||
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
// Update deploy key activity.
|
||||
deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
|
||||
if err != nil {
|
||||
fail("Internal error", "GetDeployKey: %v", err)
|
||||
}
|
||||
|
||||
deployKey.Updated = time.Now()
|
||||
if err = models.UpdateDeployKey(deployKey); err != nil {
|
||||
fail("Internal error", "UpdateDeployKey: %v", err)
|
||||
}
|
||||
} else {
|
||||
user, err = models.GetUserByKeyID(key.ID)
|
||||
if err != nil {
|
||||
fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
|
||||
}
|
||||
|
||||
mode, err := models.AccessLevel(user, repo)
|
||||
if err != nil {
|
||||
fail("Internal error", "Failed to check access: %v", err)
|
||||
} else if mode < requestedMode {
|
||||
clientMessage := accessDenied
|
||||
if mode >= models.AccessModeRead {
|
||||
clientMessage = "You do not have sufficient authorization for this action"
|
||||
}
|
||||
fail(clientMessage,
|
||||
"User %s does not have level %v access to repository %s",
|
||||
user.Name, requestedMode, repoPath)
|
||||
}
|
||||
|
||||
os.Setenv(models.EnvPusherName, user.Name)
|
||||
os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
|
||||
}
|
||||
}
|
||||
os.Setenv(models.EnvRepoIsWiki, strconv.FormatBool(results.IsWiki))
|
||||
os.Setenv(models.EnvRepoName, results.RepoName)
|
||||
os.Setenv(models.EnvRepoUsername, results.OwnerName)
|
||||
os.Setenv(models.EnvPusherName, results.UserName)
|
||||
os.Setenv(models.EnvPusherID, strconv.FormatInt(results.UserID, 10))
|
||||
os.Setenv(models.ProtectedBranchRepoID, strconv.FormatInt(results.RepoID, 10))
|
||||
os.Setenv(models.ProtectedBranchPRID, fmt.Sprintf("%d", 0))
|
||||
os.Setenv(models.EnvIsDeployKey, fmt.Sprintf("%t", results.IsDeployKey))
|
||||
os.Setenv(models.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
|
||||
|
||||
//LFS token authentication
|
||||
if verb == lfsAuthenticateVerb {
|
||||
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
|
||||
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, repoUser.Name, repo.Name)
|
||||
|
||||
now := time.Now()
|
||||
claims := jwt.MapClaims{
|
||||
"repo": results.RepoID,
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"repo": repo.ID,
|
||||
"op": lfsVerb,
|
||||
"exp": now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
|
||||
"exp": now.Add(5 * time.Minute).Unix(),
|
||||
"nbf": now.Unix(),
|
||||
"user": results.UserID,
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
})
|
||||
|
||||
// Sign and get the complete encoded token as a string using the secret
|
||||
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
|
||||
@@ -233,6 +279,7 @@ func runServ(c *cli.Context) error {
|
||||
if err != nil {
|
||||
fail("Internal error", "Failed to encode LFS json response: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -249,6 +296,8 @@ func runServ(c *cli.Context) error {
|
||||
gitcmd = exec.Command(verb, repoPath)
|
||||
}
|
||||
|
||||
os.Setenv(models.ProtectedBranchRepoID, fmt.Sprintf("%d", repo.ID))
|
||||
|
||||
gitcmd.Dir = setting.RepoRootPath
|
||||
gitcmd.Stdout = os.Stdout
|
||||
gitcmd.Stdin = os.Stdin
|
||||
@@ -258,9 +307,15 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// Update user key activity.
|
||||
if results.KeyID > 0 {
|
||||
if err = private.UpdatePublicKeyInRepo(results.KeyID, results.RepoID); err != nil {
|
||||
fail("Internal error", "UpdatePublicKeyInRepo: %v", err)
|
||||
if keyID > 0 {
|
||||
key, err := models.GetPublicKeyByID(keyID)
|
||||
if err != nil {
|
||||
fail("Internal error", "GetPublicKeyById: %v", err)
|
||||
}
|
||||
|
||||
key.Updated = time.Now()
|
||||
if err = models.UpdatePublicKey(key); err != nil {
|
||||
fail("Internal error", "UpdatePublicKey: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
729
cmd/web.go
729
cmd/web.go
@@ -5,24 +5,43 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/public"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
"code.gitea.io/gitea/routers/admin"
|
||||
apiv1 "code.gitea.io/gitea/routers/api/v1"
|
||||
"code.gitea.io/gitea/routers/dev"
|
||||
"code.gitea.io/gitea/routers/org"
|
||||
"code.gitea.io/gitea/routers/repo"
|
||||
"code.gitea.io/gitea/routers/user"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/go-macaron/cache"
|
||||
"github.com/go-macaron/captcha"
|
||||
"github.com/go-macaron/csrf"
|
||||
"github.com/go-macaron/gzip"
|
||||
"github.com/go-macaron/i18n"
|
||||
"github.com/go-macaron/session"
|
||||
"github.com/go-macaron/toolbox"
|
||||
context2 "github.com/gorilla/context"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
ini "gopkg.in/ini.v1"
|
||||
macaron "gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
// CmdWeb represents the available web sub-command.
|
||||
@@ -38,6 +57,11 @@ and it takes care of all the other things for you`,
|
||||
Value: "3000",
|
||||
Usage: "Temporary port number to prevent conflict",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pid, P",
|
||||
Value: "/var/run/gitea.pid",
|
||||
@@ -46,117 +70,593 @@ and it takes care of all the other things for you`,
|
||||
},
|
||||
}
|
||||
|
||||
func runHTTPRedirector() {
|
||||
source := fmt.Sprintf("%s:%s", setting.HTTPAddr, setting.PortToRedirect)
|
||||
dest := strings.TrimSuffix(setting.AppURL, "/")
|
||||
log.Info("Redirecting: %s to %s", source, dest)
|
||||
// newMacaron initializes Macaron instance.
|
||||
func newMacaron() *macaron.Macaron {
|
||||
m := macaron.New()
|
||||
if !setting.DisableRouterLog {
|
||||
m.Use(macaron.Logger())
|
||||
}
|
||||
m.Use(macaron.Recovery())
|
||||
if setting.EnableGzip {
|
||||
m.Use(gzip.Gziper())
|
||||
}
|
||||
if setting.Protocol == setting.FCGI {
|
||||
m.SetURLPrefix(setting.AppSubURL)
|
||||
}
|
||||
m.Use(public.Custom(
|
||||
&public.Options{
|
||||
SkipLogging: setting.DisableRouterLog,
|
||||
},
|
||||
))
|
||||
m.Use(public.Static(
|
||||
&public.Options{
|
||||
Directory: path.Join(setting.StaticRootPath, "public"),
|
||||
SkipLogging: setting.DisableRouterLog,
|
||||
},
|
||||
))
|
||||
m.Use(macaron.Static(
|
||||
setting.AvatarUploadPath,
|
||||
macaron.StaticOptions{
|
||||
Prefix: "avatars",
|
||||
SkipLogging: setting.DisableRouterLog,
|
||||
ETag: true,
|
||||
},
|
||||
))
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
target := dest + r.URL.Path
|
||||
if len(r.URL.RawQuery) > 0 {
|
||||
target += "?" + r.URL.RawQuery
|
||||
}
|
||||
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
|
||||
})
|
||||
m.Use(templates.Renderer())
|
||||
models.InitMailRender(templates.Mailer())
|
||||
|
||||
var err = runHTTP("tcp", source, context2.ClearHandler(handler))
|
||||
localeNames, err := options.Dir("locale")
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Failed to start port redirection: %v", err)
|
||||
log.Fatal(4, "Failed to list locale files: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) error {
|
||||
certManager := autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
HostPolicy: autocert.HostWhitelist(domain),
|
||||
Cache: autocert.DirCache(directory),
|
||||
Email: email,
|
||||
}
|
||||
go func() {
|
||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||
// all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||
var err = runHTTP("tcp", setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)))
|
||||
localFiles := make(map[string][]byte)
|
||||
|
||||
for _, name := range localeNames {
|
||||
localFiles[name], err = options.Locale(name)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||
log.Fatal(4, "Failed to load %s locale file. %v", name, err)
|
||||
}
|
||||
}()
|
||||
return runHTTPSWithTLSConfig("tcp", listenAddr, certManager.TLSConfig(), context2.ClearHandler(m))
|
||||
}
|
||||
|
||||
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" && r.Method != "HEAD" {
|
||||
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Remove the trailing slash at the end of setting.AppURL, the request
|
||||
// URI always contains a leading slash, which would result in a double
|
||||
// slash
|
||||
target := strings.TrimRight(setting.AppURL, "/") + r.URL.RequestURI()
|
||||
http.Redirect(w, r, target, http.StatusFound)
|
||||
|
||||
m.Use(i18n.I18n(i18n.Options{
|
||||
SubURL: setting.AppSubURL,
|
||||
Files: localFiles,
|
||||
Langs: setting.Langs,
|
||||
Names: setting.Names,
|
||||
DefaultLang: "en-US",
|
||||
Redirect: true,
|
||||
}))
|
||||
m.Use(cache.Cacher(cache.Options{
|
||||
Adapter: setting.CacheAdapter,
|
||||
AdapterConfig: setting.CacheConn,
|
||||
Interval: setting.CacheInterval,
|
||||
}))
|
||||
m.Use(captcha.Captchaer(captcha.Options{
|
||||
SubURL: setting.AppSubURL,
|
||||
}))
|
||||
m.Use(session.Sessioner(setting.SessionConfig))
|
||||
m.Use(csrf.Csrfer(csrf.Options{
|
||||
Secret: setting.SecretKey,
|
||||
Cookie: setting.CSRFCookieName,
|
||||
SetCookie: true,
|
||||
Header: "X-Csrf-Token",
|
||||
CookiePath: setting.AppSubURL,
|
||||
}))
|
||||
m.Use(toolbox.Toolboxer(m, toolbox.Options{
|
||||
HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{
|
||||
{
|
||||
Desc: "Database connection",
|
||||
Func: models.Ping,
|
||||
},
|
||||
},
|
||||
}))
|
||||
m.Use(context.Contexter())
|
||||
return m
|
||||
}
|
||||
|
||||
func runWeb(ctx *cli.Context) error {
|
||||
managerCtx, cancel := context.WithCancel(context.Background())
|
||||
graceful.InitManager(managerCtx)
|
||||
defer cancel()
|
||||
|
||||
if os.Getppid() > 1 && len(os.Getenv("LISTEN_FDS")) > 0 {
|
||||
log.Info("Restarting Gitea on PID: %d from parent PID: %d", os.Getpid(), os.Getppid())
|
||||
} else {
|
||||
log.Info("Starting Gitea on PID: %d", os.Getpid())
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
|
||||
// Set pid file setting
|
||||
if ctx.IsSet("pid") {
|
||||
setting.CustomPID = ctx.String("pid")
|
||||
}
|
||||
|
||||
// Perform global initialization
|
||||
routers.GlobalInit(graceful.GetManager().HammerContext())
|
||||
routers.GlobalInit()
|
||||
|
||||
// Set up Macaron
|
||||
m := routes.NewMacaron()
|
||||
routes.RegisterRoutes(m)
|
||||
m := newMacaron()
|
||||
|
||||
reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true})
|
||||
ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
|
||||
ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
|
||||
reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
|
||||
|
||||
bindIgnErr := binding.BindIgnErr
|
||||
|
||||
m.Use(user.GetNotificationCount)
|
||||
|
||||
// FIXME: not all routes need go through same middlewares.
|
||||
// Especially some AJAX requests, we can reduce middleware number to improve performance.
|
||||
// Routers.
|
||||
m.Get("/", ignSignIn, routers.Home)
|
||||
m.Group("/explore", func() {
|
||||
m.Get("", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL + "/explore/repos")
|
||||
})
|
||||
m.Get("/repos", routers.ExploreRepos)
|
||||
m.Get("/users", routers.ExploreUsers)
|
||||
m.Get("/organizations", routers.ExploreOrganizations)
|
||||
}, ignSignIn)
|
||||
m.Combo("/install", routers.InstallInit).Get(routers.Install).
|
||||
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
|
||||
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
|
||||
|
||||
// ***** START: User *****
|
||||
m.Group("/user", func() {
|
||||
m.Get("/login", user.SignIn)
|
||||
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
|
||||
m.Get("/sign_up", user.SignUp)
|
||||
m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
|
||||
m.Get("/reset_password", user.ResetPasswd)
|
||||
m.Post("/reset_password", user.ResetPasswdPost)
|
||||
m.Group("/oauth2", func() {
|
||||
m.Get("/:provider", user.SignInOAuth)
|
||||
m.Get("/:provider/callback", user.SignInOAuthCallback)
|
||||
})
|
||||
m.Get("/link_account", user.LinkAccount)
|
||||
m.Post("/link_account_signin", bindIgnErr(auth.SignInForm{}), user.LinkAccountPostSignIn)
|
||||
m.Post("/link_account_signup", bindIgnErr(auth.RegisterForm{}), user.LinkAccountPostRegister)
|
||||
m.Group("/two_factor", func() {
|
||||
m.Get("", user.TwoFactor)
|
||||
m.Post("", bindIgnErr(auth.TwoFactorAuthForm{}), user.TwoFactorPost)
|
||||
m.Get("/scratch", user.TwoFactorScratch)
|
||||
m.Post("/scratch", bindIgnErr(auth.TwoFactorScratchAuthForm{}), user.TwoFactorScratchPost)
|
||||
})
|
||||
}, reqSignOut)
|
||||
|
||||
m.Group("/user/settings", func() {
|
||||
m.Get("", user.Settings)
|
||||
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
|
||||
m.Combo("/avatar").Get(user.SettingsAvatar).
|
||||
Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
|
||||
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
|
||||
m.Combo("/email").Get(user.SettingsEmails).
|
||||
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
|
||||
m.Post("/email/delete", user.DeleteEmail)
|
||||
m.Get("/password", user.SettingsPassword)
|
||||
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
|
||||
m.Combo("/ssh").Get(user.SettingsSSHKeys).
|
||||
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
|
||||
m.Post("/ssh/delete", user.DeleteSSHKey)
|
||||
m.Combo("/applications").Get(user.SettingsApplications).
|
||||
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
|
||||
m.Post("/applications/delete", user.SettingsDeleteApplication)
|
||||
m.Route("/delete", "GET,POST", user.SettingsDelete)
|
||||
m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink)
|
||||
m.Group("/two_factor", func() {
|
||||
m.Get("", user.SettingsTwoFactor)
|
||||
m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch)
|
||||
m.Post("/disable", user.SettingsTwoFactorDisable)
|
||||
m.Get("/enroll", user.SettingsTwoFactorEnroll)
|
||||
m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost)
|
||||
})
|
||||
}, reqSignIn, func(ctx *context.Context) {
|
||||
ctx.Data["PageIsUserSettings"] = true
|
||||
})
|
||||
|
||||
m.Group("/user", func() {
|
||||
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
|
||||
m.Any("/activate", user.Activate)
|
||||
m.Any("/activate_email", user.ActivateEmail)
|
||||
m.Get("/email2user", user.Email2User)
|
||||
m.Get("/forget_password", user.ForgotPasswd)
|
||||
m.Post("/forget_password", user.ForgotPasswdPost)
|
||||
m.Get("/logout", user.SignOut)
|
||||
})
|
||||
// ***** END: User *****
|
||||
|
||||
adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true})
|
||||
|
||||
// ***** START: Admin *****
|
||||
m.Group("/admin", func() {
|
||||
m.Get("", adminReq, admin.Dashboard)
|
||||
m.Get("/config", admin.Config)
|
||||
m.Post("/config/test_mail", admin.SendTestMail)
|
||||
m.Get("/monitor", admin.Monitor)
|
||||
|
||||
m.Group("/users", func() {
|
||||
m.Get("", admin.Users)
|
||||
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCreateUserForm{}), admin.NewUserPost)
|
||||
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Post("/:userid/delete", admin.DeleteUser)
|
||||
})
|
||||
|
||||
m.Group("/orgs", func() {
|
||||
m.Get("", admin.Organizations)
|
||||
})
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Get("", admin.Repos)
|
||||
m.Post("/delete", admin.DeleteRepo)
|
||||
})
|
||||
|
||||
m.Group("/auths", func() {
|
||||
m.Get("", admin.Authentications)
|
||||
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
m.Combo("/:authid").Get(admin.EditAuthSource).
|
||||
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||
m.Post("/:authid/delete", admin.DeleteAuthSource)
|
||||
})
|
||||
|
||||
m.Group("/notices", func() {
|
||||
m.Get("", admin.Notices)
|
||||
m.Post("/delete", admin.DeleteNotices)
|
||||
m.Get("/empty", admin.EmptyNotices)
|
||||
})
|
||||
}, adminReq)
|
||||
// ***** END: Admin *****
|
||||
|
||||
m.Group("", func() {
|
||||
m.Group("/:username", func() {
|
||||
m.Get("", user.Profile)
|
||||
m.Get("/followers", user.Followers)
|
||||
m.Get("/following", user.Following)
|
||||
})
|
||||
|
||||
m.Get("/attachments/:uuid", func(ctx *context.Context) {
|
||||
attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid"))
|
||||
if err != nil {
|
||||
if models.IsErrAttachmentNotExist(err) {
|
||||
ctx.Error(404)
|
||||
} else {
|
||||
ctx.Handle(500, "GetAttachmentByUUID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fr, err := os.Open(attach.LocalPath())
|
||||
if err != nil {
|
||||
ctx.Handle(500, "Open", err)
|
||||
return
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
if err = repo.ServeData(ctx, attach.Name, fr); err != nil {
|
||||
ctx.Handle(500, "ServeData", err)
|
||||
return
|
||||
}
|
||||
})
|
||||
m.Post("/attachments", repo.UploadAttachment)
|
||||
}, ignSignIn)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Get("/action/:action", user.Action)
|
||||
}, reqSignIn)
|
||||
|
||||
if macaron.Env == macaron.DEV {
|
||||
m.Get("/template/*", dev.TemplatePreview)
|
||||
}
|
||||
|
||||
reqRepoAdmin := context.RequireRepoAdmin()
|
||||
reqRepoWriter := context.RequireRepoWriter()
|
||||
|
||||
// ***** START: Organization *****
|
||||
m.Group("/org", func() {
|
||||
m.Group("", func() {
|
||||
m.Get("/create", org.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
|
||||
}, func(ctx *context.Context) {
|
||||
if !ctx.User.CanCreateOrganization() {
|
||||
ctx.NotFound()
|
||||
}
|
||||
})
|
||||
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/dashboard", user.Dashboard)
|
||||
m.Get("/^:type(issues|pulls)$", user.Issues)
|
||||
m.Get("/members", org.Members)
|
||||
m.Get("/members/action/:action", org.MembersAction)
|
||||
|
||||
m.Get("/teams", org.Teams)
|
||||
}, context.OrgAssignment(true))
|
||||
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/teams/:team", org.TeamMembers)
|
||||
m.Get("/teams/:team/repositories", org.TeamRepositories)
|
||||
m.Route("/teams/:team/action/:action", "GET,POST", org.TeamsAction)
|
||||
m.Route("/teams/:team/action/repo/:action", "GET,POST", org.TeamsRepoAction)
|
||||
}, context.OrgAssignment(true, false, true))
|
||||
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/teams/new", org.NewTeam)
|
||||
m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
|
||||
m.Get("/teams/:team/edit", org.EditTeam)
|
||||
m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
|
||||
m.Post("/teams/:team/delete", org.DeleteTeam)
|
||||
|
||||
m.Group("/settings", func() {
|
||||
m.Combo("").Get(org.Settings).
|
||||
Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
|
||||
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), org.SettingsAvatar)
|
||||
m.Post("/avatar/delete", org.SettingsDeleteAvatar)
|
||||
|
||||
m.Group("/hooks", func() {
|
||||
m.Get("", org.Webhooks)
|
||||
m.Post("/delete", org.DeleteWebhook)
|
||||
m.Get("/:type/new", repo.WebhooksNew)
|
||||
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Get("/:id", repo.WebHooksEdit)
|
||||
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
})
|
||||
|
||||
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||
})
|
||||
|
||||
m.Route("/invitations/new", "GET,POST", org.Invitation)
|
||||
}, context.OrgAssignment(true, true))
|
||||
}, reqSignIn)
|
||||
// ***** END: Organization *****
|
||||
|
||||
// ***** START: Repository *****
|
||||
m.Group("/repo", func() {
|
||||
m.Get("/create", repo.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||
m.Get("/migrate", repo.Migrate)
|
||||
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||
m.Combo("/fork/:repoid").Get(repo.Fork).
|
||||
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
|
||||
}, reqSignIn)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Group("/settings", func() {
|
||||
m.Combo("").Get(repo.Settings).
|
||||
Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
|
||||
m.Group("/collaboration", func() {
|
||||
m.Combo("").Get(repo.Collaboration).Post(repo.CollaborationPost)
|
||||
m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
|
||||
m.Post("/delete", repo.DeleteCollaboration)
|
||||
})
|
||||
m.Group("/branches", func() {
|
||||
m.Combo("").Get(repo.ProtectedBranch).Post(repo.ProtectedBranchPost)
|
||||
m.Post("/can_push", repo.ChangeProtectedBranch)
|
||||
m.Post("/delete", repo.DeleteProtectedBranch)
|
||||
})
|
||||
|
||||
m.Group("/hooks", func() {
|
||||
m.Get("", repo.Webhooks)
|
||||
m.Post("/delete", repo.DeleteWebhook)
|
||||
m.Get("/:type/new", repo.WebhooksNew)
|
||||
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Get("/:id", repo.WebHooksEdit)
|
||||
m.Post("/:id/test", repo.TestWebhook)
|
||||
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
|
||||
m.Group("/git", func() {
|
||||
m.Get("", repo.GitHooks)
|
||||
m.Combo("/:name").Get(repo.GitHooksEdit).
|
||||
Post(repo.GitHooksEditPost)
|
||||
}, context.GitHookService())
|
||||
})
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").Get(repo.DeployKeys).
|
||||
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.DeployKeysPost)
|
||||
m.Post("/delete", repo.DeleteDeployKey)
|
||||
})
|
||||
|
||||
}, func(ctx *context.Context) {
|
||||
ctx.Data["PageIsSettings"] = true
|
||||
}, context.UnitTypes())
|
||||
}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
|
||||
|
||||
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
|
||||
m.Group("/:username/:reponame", func() {
|
||||
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
|
||||
// So they can apply their own enable/disable logic on routers.
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
|
||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
|
||||
|
||||
m.Group("/:index", func() {
|
||||
m.Post("/label", repo.UpdateIssueLabel)
|
||||
m.Post("/milestone", repo.UpdateIssueMilestone)
|
||||
m.Post("/assignee", repo.UpdateIssueAssignee)
|
||||
}, reqRepoWriter)
|
||||
|
||||
m.Group("/:index", func() {
|
||||
m.Post("/title", repo.UpdateIssueTitle)
|
||||
m.Post("/content", repo.UpdateIssueContent)
|
||||
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
|
||||
})
|
||||
})
|
||||
m.Group("/comments/:id", func() {
|
||||
m.Post("", repo.UpdateCommentContent)
|
||||
m.Post("/delete", repo.DeleteComment)
|
||||
})
|
||||
m.Group("/labels", func() {
|
||||
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||
m.Post("/delete", repo.DeleteLabel)
|
||||
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
m.Group("/milestones", func() {
|
||||
m.Combo("/new").Get(repo.NewMilestone).
|
||||
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||
m.Get("/:id/edit", repo.EditMilestone)
|
||||
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
|
||||
m.Get("/:id/:action", repo.ChangeMilestonStatus)
|
||||
m.Post("/delete", repo.DeleteMilestone)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/new", repo.NewRelease)
|
||||
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||
m.Post("/delete", repo.DeleteRelease)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/edit/*", repo.EditRelease)
|
||||
m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
||||
}, reqRepoWriter, func(ctx *context.Context) {
|
||||
var err error
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
|
||||
if err != nil {
|
||||
ctx.Handle(500, "CommitsCount", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
|
||||
})
|
||||
|
||||
m.Combo("/compare/*", repo.MustAllowPulls, repo.SetEditorconfigIfExists).
|
||||
Get(repo.CompareAndPullRequest).
|
||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_edit/*").Get(repo.EditFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.EditFilePost)
|
||||
m.Combo("/_new/*").Get(repo.NewFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.NewFilePost)
|
||||
m.Post("/_preview/*", bindIgnErr(auth.EditPreviewDiffForm{}), repo.DiffPreviewPost)
|
||||
m.Combo("/_delete/*").Get(repo.DeleteFile).
|
||||
Post(bindIgnErr(auth.DeleteRepoFileForm{}), repo.DeleteFilePost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_upload/*").Get(repo.UploadFile).
|
||||
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
|
||||
m.Post("/upload-file", repo.UploadFileToServer)
|
||||
m.Post("/upload-remove", bindIgnErr(auth.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
|
||||
}, func(ctx *context.Context) {
|
||||
if !setting.Repository.Upload.Enabled {
|
||||
ctx.Handle(404, "", nil)
|
||||
return
|
||||
}
|
||||
})
|
||||
}, reqRepoWriter, context.RepoRef(), func(ctx *context.Context) {
|
||||
if !ctx.Repo.Repository.CanEnableEditor() || ctx.Repo.IsViewCommit {
|
||||
ctx.Handle(404, "", nil)
|
||||
return
|
||||
}
|
||||
})
|
||||
}, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes())
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Group("", func() {
|
||||
m.Get("/releases", repo.Releases)
|
||||
m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues)
|
||||
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue)
|
||||
m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
|
||||
m.Get("/milestones", repo.Milestones)
|
||||
}, context.RepoRef())
|
||||
|
||||
// m.Get("/branches", repo.Branches)
|
||||
m.Post("/branches/:name/delete", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
|
||||
|
||||
m.Group("/wiki", func() {
|
||||
m.Get("/?:page", repo.Wiki)
|
||||
m.Get("/_pages", repo.WikiPages)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_new").Get(repo.NewWiki).
|
||||
Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost)
|
||||
m.Combo("/:page/_edit").Get(repo.EditWiki).
|
||||
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
|
||||
m.Post("/:page/delete", repo.DeleteWikiPagePost)
|
||||
}, reqSignIn, reqRepoWriter)
|
||||
}, repo.MustEnableWiki, context.RepoRef())
|
||||
|
||||
m.Group("/wiki", func() {
|
||||
m.Get("/raw/*", repo.WikiRaw)
|
||||
m.Get("/*", repo.WikiRaw)
|
||||
}, repo.MustEnableWiki)
|
||||
|
||||
m.Get("/archive/*", repo.Download)
|
||||
|
||||
m.Group("/pulls/:index", func() {
|
||||
m.Get("/commits", context.RepoRef(), repo.ViewPullCommits)
|
||||
m.Get("/files", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ViewPullFiles)
|
||||
m.Post("/merge", reqRepoWriter, repo.MergePullRequest)
|
||||
}, repo.MustAllowPulls)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Get("/src/*", repo.SetEditorconfigIfExists, repo.Home)
|
||||
m.Get("/raw/*", repo.SingleDownload)
|
||||
m.Get("/commits/*", repo.RefCommits)
|
||||
m.Get("/graph", repo.Graph)
|
||||
m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff)
|
||||
m.Get("/forks", repo.Forks)
|
||||
}, context.RepoRef())
|
||||
m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff)
|
||||
|
||||
m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.CompareDiff)
|
||||
}, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes())
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Get("/stars", repo.Stars)
|
||||
m.Get("/watchers", repo.Watchers)
|
||||
}, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes())
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Group("/:reponame", func() {
|
||||
m.Get("", repo.SetEditorconfigIfExists, repo.Home)
|
||||
m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home)
|
||||
}, ignSignIn, context.RepoAssignment(true), context.RepoRef(), context.UnitTypes())
|
||||
|
||||
m.Group("/:reponame", func() {
|
||||
m.Group("/info/lfs", func() {
|
||||
m.Post("/objects/batch", lfs.BatchHandler)
|
||||
m.Get("/objects/:oid/:filename", lfs.ObjectOidHandler)
|
||||
m.Any("/objects/:oid", lfs.ObjectOidHandler)
|
||||
m.Post("/objects", lfs.PostHandler)
|
||||
}, ignSignInAndCsrf)
|
||||
m.Any("/*", ignSignInAndCsrf, repo.HTTP)
|
||||
m.Head("/tasks/trigger", repo.TriggerTask)
|
||||
})
|
||||
})
|
||||
// ***** END: Repository *****
|
||||
|
||||
m.Group("/notifications", func() {
|
||||
m.Get("", user.Notifications)
|
||||
m.Post("/status", user.NotificationStatusPost)
|
||||
}, reqSignIn)
|
||||
|
||||
m.Group("/api", func() {
|
||||
apiv1.RegisterRoutes(m)
|
||||
}, ignSignIn)
|
||||
|
||||
// robots.txt
|
||||
m.Get("/robots.txt", func(ctx *context.Context) {
|
||||
if setting.HasRobotsTxt {
|
||||
ctx.ServeFileContent(path.Join(setting.CustomPath, "robots.txt"))
|
||||
} else {
|
||||
ctx.Error(404)
|
||||
}
|
||||
})
|
||||
|
||||
// Not found handler.
|
||||
m.NotFound(routers.NotFound)
|
||||
|
||||
// Flag for port number in case first time run conflict.
|
||||
if ctx.IsSet("port") {
|
||||
setting.AppURL = strings.Replace(setting.AppURL, setting.HTTPPort, ctx.String("port"), 1)
|
||||
setting.HTTPPort = ctx.String("port")
|
||||
|
||||
switch setting.Protocol {
|
||||
case setting.UnixSocket:
|
||||
case setting.FCGI:
|
||||
case setting.FCGIUnix:
|
||||
default:
|
||||
// Save LOCAL_ROOT_URL if port changed
|
||||
cfg := ini.Empty()
|
||||
if com.IsFile(setting.CustomConf) {
|
||||
// Keeps custom settings if there is already something.
|
||||
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||
return fmt.Errorf("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
}
|
||||
|
||||
defaultLocalURL := string(setting.Protocol) + "://"
|
||||
if setting.HTTPAddr == "0.0.0.0" {
|
||||
defaultLocalURL += "localhost"
|
||||
} else {
|
||||
defaultLocalURL += setting.HTTPAddr
|
||||
}
|
||||
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
||||
|
||||
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
|
||||
if err := cfg.SaveTo(setting.CustomConf); err != nil {
|
||||
return fmt.Errorf("Error saving generated JWT Secret to custom config: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listenAddr := setting.HTTPAddr
|
||||
if setting.Protocol != setting.UnixSocket && setting.Protocol != setting.FCGIUnix {
|
||||
listenAddr += ":" + setting.HTTPPort
|
||||
var listenAddr string
|
||||
if setting.Protocol == setting.UnixSocket {
|
||||
listenAddr = fmt.Sprintf("%s", setting.HTTPAddr)
|
||||
} else {
|
||||
listenAddr = fmt.Sprintf("%s:%s", setting.HTTPAddr, setting.HTTPPort)
|
||||
}
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||
|
||||
@@ -166,7 +666,6 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
if setting.EnablePprof {
|
||||
go func() {
|
||||
log.Info("Starting pprof server on localhost:6060")
|
||||
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
|
||||
}()
|
||||
}
|
||||
@@ -174,38 +673,34 @@ func runWeb(ctx *cli.Context) error {
|
||||
var err error
|
||||
switch setting.Protocol {
|
||||
case setting.HTTP:
|
||||
NoHTTPRedirector()
|
||||
err = runHTTP("tcp", listenAddr, context2.ClearHandler(m))
|
||||
err = runHTTP(listenAddr, context2.ClearHandler(m))
|
||||
case setting.HTTPS:
|
||||
if setting.EnableLetsEncrypt {
|
||||
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, context2.ClearHandler(m))
|
||||
break
|
||||
}
|
||||
if setting.RedirectOtherPort {
|
||||
go runHTTPRedirector()
|
||||
} else {
|
||||
NoHTTPRedirector()
|
||||
}
|
||||
err = runHTTPS("tcp", listenAddr, setting.CertFile, setting.KeyFile, context2.ClearHandler(m))
|
||||
err = runHTTPS(listenAddr, setting.CertFile, setting.KeyFile, context2.ClearHandler(m))
|
||||
case setting.FCGI:
|
||||
NoHTTPRedirector()
|
||||
err = runFCGI("tcp", listenAddr, context2.ClearHandler(m))
|
||||
err = fcgi.Serve(nil, context2.ClearHandler(m))
|
||||
case setting.UnixSocket:
|
||||
NoHTTPRedirector()
|
||||
err = runHTTP("unix", listenAddr, context2.ClearHandler(m))
|
||||
case setting.FCGIUnix:
|
||||
NoHTTPRedirector()
|
||||
err = runFCGI("unix", listenAddr, context2.ClearHandler(m))
|
||||
if err := os.Remove(listenAddr); err != nil && !os.IsNotExist(err) {
|
||||
log.Fatal(4, "Failed to remove unix socket directory %s: %v", listenAddr, err)
|
||||
}
|
||||
var listener *net.UnixListener
|
||||
listener, err = net.ListenUnix("unix", &net.UnixAddr{Name: listenAddr, Net: "unix"})
|
||||
if err != nil {
|
||||
break // Handle error after switch
|
||||
}
|
||||
|
||||
// FIXME: add proper implementation of signal capture on all protocols
|
||||
// execute this on SIGTERM or SIGINT: listener.Close()
|
||||
if err = os.Chmod(listenAddr, os.FileMode(setting.UnixSocketPermission)); err != nil {
|
||||
log.Fatal(4, "Failed to set permission of unix socket: %v", err)
|
||||
}
|
||||
err = http.Serve(listener, context2.ClearHandler(m))
|
||||
default:
|
||||
log.Fatal("Invalid protocol: %s", setting.Protocol)
|
||||
log.Fatal(4, "Invalid protocol: %s", setting.Protocol)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Critical("Failed to start server: %v", err)
|
||||
log.Fatal(4, "Failed to start server: %v", err)
|
||||
}
|
||||
log.Info("HTTP Listener: %s Closed", listenAddr)
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
// +build !windows
|
||||
|
||||
// Copyright 2016 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.
|
||||
@@ -6,47 +8,37 @@ package cmd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"github.com/facebookgo/grace/gracehttp"
|
||||
)
|
||||
|
||||
func runHTTP(network, listenAddr string, m http.Handler) error {
|
||||
return graceful.HTTPListenAndServe(network, listenAddr, m)
|
||||
}
|
||||
|
||||
func runHTTPS(network, listenAddr, certFile, keyFile string, m http.Handler) error {
|
||||
return graceful.HTTPListenAndServeTLS(network, listenAddr, certFile, keyFile, m)
|
||||
}
|
||||
|
||||
func runHTTPSWithTLSConfig(network, listenAddr string, tlsConfig *tls.Config, m http.Handler) error {
|
||||
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, tlsConfig, m)
|
||||
}
|
||||
|
||||
// NoHTTPRedirector tells our cleanup routine that we will not be using a fallback http redirector
|
||||
func NoHTTPRedirector() {
|
||||
graceful.GetManager().InformCleanup()
|
||||
}
|
||||
|
||||
// NoMainListener tells our cleanup routine that we will not be using a possibly provided listener
|
||||
// for our main HTTP/HTTPS service
|
||||
func NoMainListener() {
|
||||
graceful.GetManager().InformCleanup()
|
||||
}
|
||||
|
||||
func runFCGI(network, listenAddr string, m http.Handler) error {
|
||||
// This needs to handle stdin as fcgi point
|
||||
fcgiServer := graceful.NewServer(network, listenAddr)
|
||||
|
||||
err := fcgiServer.ListenAndServe(func(listener net.Listener) error {
|
||||
return fcgi.Serve(listener, m)
|
||||
func runHTTP(listenAddr string, m http.Handler) error {
|
||||
return gracehttp.Serve(&http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
})
|
||||
}
|
||||
|
||||
func runHTTPS(listenAddr, certFile, keyFile string, m http.Handler) error {
|
||||
config := &tls.Config{
|
||||
MinVersion: tls.VersionTLS10,
|
||||
}
|
||||
if config.NextProtos == nil {
|
||||
config.NextProtos = []string{"http/1.1"}
|
||||
}
|
||||
|
||||
config.Certificates = make([]tls.Certificate, 1)
|
||||
var err error
|
||||
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to load https cert file %s: %v", listenAddr, err)
|
||||
}
|
||||
|
||||
return gracehttp.Serve(&http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
TLSConfig: config,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal("Failed to start FCGI main server: %v", err)
|
||||
}
|
||||
log.Info("FCGI Listener: %s Closed", listenAddr)
|
||||
return err
|
||||
}
|
||||
|
19
cmd/web_windows.go
Normal file
19
cmd/web_windows.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build windows
|
||||
|
||||
// Copyright 2016 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 cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func runHTTP(listenAddr string, m http.Handler) error {
|
||||
return http.ListenAndServe(listenAddr, m)
|
||||
}
|
||||
|
||||
func runHTTPS(listenAddr, certFile, keyFile string, m http.Handler) error {
|
||||
return http.ListenAndServeTLS(listenAddr, certFile, keyFile, m)
|
||||
}
|
469
conf/app.ini
vendored
Normal file
469
conf/app.ini
vendored
Normal file
@@ -0,0 +1,469 @@
|
||||
; App name that shows on every page title
|
||||
APP_NAME = Gitea: Git with a cup of tea
|
||||
; Change it if you run locally
|
||||
RUN_USER = git
|
||||
; Either "dev", "prod" or "test", default is "dev"
|
||||
RUN_MODE = dev
|
||||
|
||||
[repository]
|
||||
ROOT =
|
||||
SCRIPT_TYPE = bash
|
||||
; Default ANSI charset
|
||||
ANSI_CHARSET =
|
||||
; Force every new repository to be private
|
||||
FORCE_PRIVATE = false
|
||||
; Global maximum creation limit of repository per user, -1 means no limit
|
||||
MAX_CREATION_LIMIT = -1
|
||||
; Mirror sync queue length, increase if mirror syncing starts hanging
|
||||
MIRROR_QUEUE_LENGTH = 1000
|
||||
; Patch test queue length, increase if pull request patch testing starts hanging
|
||||
PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||
; Preferred Licenses to place at the top of the List
|
||||
; Name must match file name in conf/license or custom/conf/license
|
||||
PREFERRED_LICENSES = Apache License 2.0,MIT License
|
||||
; Disable ability to interact with repositories by HTTP protocol
|
||||
DISABLE_HTTP_GIT = false
|
||||
|
||||
[repository.editor]
|
||||
; List of file extensions that should have line wraps in the CodeMirror editor
|
||||
; Separate extensions with a comma. To line wrap files w/o extension, just put a comma
|
||||
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||
; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
|
||||
PREVIEWABLE_FILE_MODES = markdown
|
||||
|
||||
[repository.upload]
|
||||
; Whether repository file uploads are enabled. Defaults to `true`
|
||||
ENABLED = true
|
||||
; Path for uploads. Defaults to `data/tmp/uploads` (tmp gets deleted on gitea restart)
|
||||
TEMP_PATH = data/tmp/uploads
|
||||
; One or more allowed types, e.g. image/jpeg|image/png. Nothing means any file type
|
||||
ALLOWED_TYPES =
|
||||
; Max size of each file in MB. Defaults to 3MB
|
||||
FILE_MAX_SIZE = 3
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[ui]
|
||||
; Number of repositories that are showed in one explore page
|
||||
EXPLORE_PAGING_NUM = 20
|
||||
; Number of issues that are showed in one page
|
||||
ISSUE_PAGING_NUM = 10
|
||||
; Number of maximum commits showed in one activity feed
|
||||
FEED_MAX_COMMIT_NUM = 5
|
||||
; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||
; An invalid color like "none" or "disable" will have the default style
|
||||
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||
THEME_COLOR_META_TAG = `#6cc644`
|
||||
; Max size of files to be displayed (defaults is 8MiB)
|
||||
MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
; Whether show the user email in the Explore Users page
|
||||
SHOW_USER_EMAIL = true
|
||||
|
||||
[ui.admin]
|
||||
; Number of users that are showed in one page
|
||||
USER_PAGING_NUM = 50
|
||||
; Number of repos that are showed in one page
|
||||
REPO_PAGING_NUM = 50
|
||||
; Number of notices that are showed in one page
|
||||
NOTICE_PAGING_NUM = 25
|
||||
; Number of organization that are showed in one page
|
||||
ORG_PAGING_NUM = 50
|
||||
|
||||
[ui.user]
|
||||
; Number of repos that are showed in one page
|
||||
REPO_PAGING_NUM = 15
|
||||
|
||||
[markdown]
|
||||
; Enable hard line break extension
|
||||
ENABLE_HARD_LINE_BREAK = false
|
||||
; List of custom URL-Schemes that are allowed as links when rendering Markdown
|
||||
; for example git,magnet
|
||||
CUSTOM_URL_SCHEMES =
|
||||
; List of file extensions that should be rendered/edited as Markdown
|
||||
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
|
||||
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
|
||||
[server]
|
||||
PROTOCOL = http
|
||||
DOMAIN = localhost
|
||||
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
HTTP_ADDR = 0.0.0.0
|
||||
HTTP_PORT = 3000
|
||||
; Permission for unix socket
|
||||
UNIX_SOCKET_PERMISSION = 666
|
||||
; Local (DMZ) URL for Gitea workers (such as SSH update) accessing web service.
|
||||
; In most cases you do not need to change the default value.
|
||||
; Alter it only if your SSH server node is not the same as HTTP node.
|
||||
LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
||||
; Disable SSH feature when not available
|
||||
DISABLE_SSH = false
|
||||
; Whether use builtin SSH server or not.
|
||||
START_SSH_SERVER = false
|
||||
; Domain name to be exposed in clone URL
|
||||
SSH_DOMAIN = %(DOMAIN)s
|
||||
; Network interface builtin SSH server listens on
|
||||
SSH_LISTEN_HOST =
|
||||
; Port number to be exposed in clone URL
|
||||
SSH_PORT = 22
|
||||
; Port number builtin SSH server listens on
|
||||
SSH_LISTEN_PORT = %(SSH_PORT)s
|
||||
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
||||
SSH_ROOT_PATH =
|
||||
; Directory to create temporary files when test publick key using ssh-keygen,
|
||||
; default is system temporary directory.
|
||||
SSH_KEY_TEST_PATH =
|
||||
; Path to ssh-keygen, default is 'ssh-keygen' and let shell find out which one to call.
|
||||
SSH_KEYGEN_PATH = ssh-keygen
|
||||
; Indicate whether to check minimum key size with corresponding type
|
||||
MINIMUM_KEY_SIZE_CHECK = false
|
||||
; Disable CDN even in "prod" mode
|
||||
OFFLINE_MODE = false
|
||||
DISABLE_ROUTER_LOG = false
|
||||
; Generate steps:
|
||||
; $ ./gitea cert -ca=true -duration=8760h0m0s -host=myhost.example.com
|
||||
;
|
||||
; Or from a .pfx file exported from the Windows certificate store (do
|
||||
; 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
|
||||
; Upper level of template and static file path
|
||||
; default is the path where Gitea is executed
|
||||
STATIC_ROOT_PATH =
|
||||
; Default path for App data
|
||||
APP_DATA_PATH = data
|
||||
; Application level GZIP support
|
||||
ENABLE_GZIP = false
|
||||
; Landing page for non-logged users, can be "home" or "explore"
|
||||
LANDING_PAGE = home
|
||||
|
||||
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
|
||||
[ssh.minimum_key_sizes]
|
||||
ED25519 = 256
|
||||
ECDSA = 256
|
||||
RSA = 2048
|
||||
DSA = 1024
|
||||
|
||||
[database]
|
||||
; Either "mysql", "postgres" or "sqlite3", it's your choice
|
||||
DB_TYPE = mysql
|
||||
HOST = 127.0.0.1:3306
|
||||
NAME = gitea
|
||||
USER = root
|
||||
PASSWD =
|
||||
; For "postgres" only, either "disable", "require" or "verify-full"
|
||||
SSL_MODE = disable
|
||||
; For "sqlite3" and "tidb", use absolute path when you start as service
|
||||
PATH = data/gitea.db
|
||||
|
||||
[indexer]
|
||||
ISSUE_INDEXER_PATH = indexers/issues.bleve
|
||||
UPDATE_BUFFER_LEN = 20
|
||||
|
||||
[admin]
|
||||
; Disable regular (non-admin) users to create organizations
|
||||
DISABLE_REGULAR_ORG_CREATION = false
|
||||
|
||||
[security]
|
||||
; Whether the installer is disabled
|
||||
INSTALL_LOCK = false
|
||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
|
||||
SECRET_KEY = !#@FDEWREWR&*(
|
||||
; Auto-login remember days
|
||||
LOGIN_REMEMBER_DAYS = 7
|
||||
COOKIE_USERNAME = gitea_awesome
|
||||
COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
; Reverse proxy authentication header name of user name
|
||||
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
||||
; Sets the minimum password length for new Users
|
||||
MIN_PASSWORD_LENGTH = 6
|
||||
; True when users are allowed to import local server paths
|
||||
IMPORT_LOCAL_PATHS = false
|
||||
|
||||
[service]
|
||||
ACTIVE_CODE_LIVE_MINUTES = 180
|
||||
RESET_PASSWD_CODE_LIVE_MINUTES = 180
|
||||
; User need to confirm e-mail for registration
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
; Does not allow register and admin create account only
|
||||
DISABLE_REGISTRATION = false
|
||||
; User must sign in to view anything.
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
; Mail notification
|
||||
ENABLE_NOTIFY_MAIL = false
|
||||
; More detail: https://github.com/go-gitea/gitea/issues/165
|
||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
|
||||
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
|
||||
; Enable captcha validation for registration
|
||||
ENABLE_CAPTCHA = true
|
||||
; Default value for KeepEmailPrivate
|
||||
; New user will get the value of this setting copied into their profile
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
; Default value for the domain part of the user's email address in the git log
|
||||
; if he has set KeepEmailPrivate true. The user's email replaced with a
|
||||
; concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
|
||||
[webhook]
|
||||
; Hook task queue length, increase if webhook shooting starts hanging
|
||||
QUEUE_LENGTH = 1000
|
||||
; Deliver timeout in seconds
|
||||
DELIVER_TIMEOUT = 5
|
||||
; Allow insecure certification
|
||||
SKIP_TLS_VERIFY = false
|
||||
; Number of history information in each page
|
||||
PAGING_NUM = 10
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
; Buffer length of channel, keep it as it is if you don't know what it is.
|
||||
SEND_BUFFER_LEN = 100
|
||||
; Name displayed in mail title
|
||||
SUBJECT = %(APP_NAME)s
|
||||
; Mail server
|
||||
; Gmail: smtp.gmail.com:587
|
||||
; QQ: smtp.qq.com:465
|
||||
; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
|
||||
HOST =
|
||||
; Disable HELO operation when hostname are different.
|
||||
DISABLE_HELO =
|
||||
; Custom hostname for HELO operation, default is from system.
|
||||
HELO_HOSTNAME =
|
||||
; Do not verify the certificate of the server. Only use this for self-signed certificates
|
||||
SKIP_VERIFY =
|
||||
; Use client certificate
|
||||
USE_CERTIFICATE = false
|
||||
CERT_FILE = custom/mailer/cert.pem
|
||||
KEY_FILE = custom/mailer/key.pem
|
||||
; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
|
||||
FROM =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
PASSWD =
|
||||
; Use text/html as alternative format of content
|
||||
ENABLE_HTML_ALTERNATIVE = false
|
||||
; Enable sendmail (override SMTP)
|
||||
USE_SENDMAIL = false
|
||||
; Specifiy an alternative sendmail binary
|
||||
SENDMAIL_PATH = sendmail
|
||||
|
||||
[cache]
|
||||
; Either "memory", "redis", or "memcache", default is "memory"
|
||||
ADAPTER = memory
|
||||
; For "memory" only, GC interval in seconds, default is 60
|
||||
INTERVAL = 60
|
||||
; For "redis" and "memcache", connection host address
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; memcache: `127.0.0.1:11211`
|
||||
HOST =
|
||||
|
||||
[session]
|
||||
; Either "memory", "file", or "redis", default is "memory"
|
||||
PROVIDER = memory
|
||||
; Provider config options
|
||||
; memory: not have any config yet
|
||||
; file: session file path, e.g. `data/sessions`
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
PROVIDER_CONFIG = data/sessions
|
||||
; Session cookie name
|
||||
COOKIE_NAME = i_like_gitea
|
||||
; If you use session in https only, default is false
|
||||
COOKIE_SECURE = false
|
||||
; Enable set cookie, default is true
|
||||
ENABLE_SET_COOKIE = true
|
||||
; Session GC time interval, default is 86400
|
||||
GC_INTERVAL_TIME = 86400
|
||||
; Session life time, default is 86400
|
||||
SESSION_LIFE_TIME = 86400
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = data/avatars
|
||||
; Chinese users can choose "duoshuo"
|
||||
; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
GRAVATAR_SOURCE = gravatar
|
||||
; This value will be forced to be true in offline mode.
|
||||
DISABLE_GRAVATAR = false
|
||||
; Federated avatar lookup uses DNS to discover avatar associated
|
||||
; with emails, see https://www.libravatar.org
|
||||
; This value will be forced to be false in offline mode or Gravatar is disbaled.
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[attachment]
|
||||
; Whether attachments are enabled. Defaults to `true`
|
||||
ENABLE = true
|
||||
; Path for attachments. Defaults to `data/attachments`
|
||||
PATH = data/attachments
|
||||
; One or more allowed types, e.g. image/jpeg|image/png
|
||||
ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip
|
||||
; Max size of each file. Defaults to 32MB
|
||||
MAX_SIZE = 4
|
||||
; Max number of files per upload. Defaults to 10
|
||||
MAX_FILES = 5
|
||||
|
||||
[time]
|
||||
; Specifies the format for fully outputed dates. Defaults to RFC1123
|
||||
; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
|
||||
; For more information about the format see http://golang.org/pkg/time/#pkg-constants
|
||||
FORMAT =
|
||||
|
||||
[log]
|
||||
ROOT_PATH =
|
||||
; Either "console", "file", "conn", "smtp" or "database", default is "console"
|
||||
; Use comma to separate multiple modes, e.g. "console, file"
|
||||
MODE = console
|
||||
; Buffer length of channel, keep it as it is if you don't know what it is.
|
||||
BUFFER_LEN = 10000
|
||||
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
|
||||
LEVEL = Trace
|
||||
|
||||
; For "console" mode only
|
||||
[log.console]
|
||||
LEVEL =
|
||||
|
||||
; For "file" mode only
|
||||
[log.file]
|
||||
LEVEL =
|
||||
; This enables automated log rotate(switch of following options), default is true
|
||||
LOG_ROTATE = true
|
||||
; Max line number of single file, default is 1000000
|
||||
MAX_LINES = 1000000
|
||||
; Max size shift of single file, default is 28 means 1 << 28, 256MB
|
||||
MAX_SIZE_SHIFT = 28
|
||||
; Segment log daily, default is true
|
||||
DAILY_ROTATE = true
|
||||
; Expired days of log file(delete after max days), default is 7
|
||||
MAX_DAYS = 7
|
||||
|
||||
; For "conn" mode only
|
||||
[log.conn]
|
||||
LEVEL =
|
||||
; Reconnect host for every single message, default is false
|
||||
RECONNECT_ON_MSG = false
|
||||
; Try to reconnect when connection is lost, default is false
|
||||
RECONNECT = false
|
||||
; Either "tcp", "unix" or "udp", default is "tcp"
|
||||
PROTOCOL = tcp
|
||||
; Host address
|
||||
ADDR =
|
||||
|
||||
; For "smtp" mode only
|
||||
[log.smtp]
|
||||
LEVEL =
|
||||
; Name displayed in mail title, default is "Diagnostic message from server"
|
||||
SUBJECT = Diagnostic message from server
|
||||
; Mail server
|
||||
HOST =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
PASSWD =
|
||||
; Receivers, can be one or more, e.g. 1@example.com,2@example.com
|
||||
RECEIVERS =
|
||||
|
||||
; For "database" mode only
|
||||
[log.database]
|
||||
LEVEL =
|
||||
; Either "mysql" or "postgres"
|
||||
DRIVER =
|
||||
; Based on xorm, e.g.: root:root@localhost/gitea?charset=utf8
|
||||
CONN =
|
||||
|
||||
[cron]
|
||||
; Enable running cron tasks periodically.
|
||||
ENABLED = true
|
||||
; Run cron tasks when Gitea starts.
|
||||
RUN_AT_START = false
|
||||
|
||||
; Update mirrors
|
||||
[cron.update_mirrors]
|
||||
SCHEDULE = @every 10m
|
||||
|
||||
; Repository health check
|
||||
[cron.repo_health_check]
|
||||
SCHEDULE = @every 24h
|
||||
TIMEOUT = 60s
|
||||
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
|
||||
; see more on http://git-scm.com/docs/git-fsck/1.7.5
|
||||
ARGS =
|
||||
|
||||
; Check repository statistics
|
||||
[cron.check_repo_stats]
|
||||
RUN_AT_START = true
|
||||
SCHEDULE = @every 24h
|
||||
|
||||
; Clean up old repository archives
|
||||
[cron.archive_cleanup]
|
||||
RUN_AT_START = true
|
||||
SCHEDULE = @every 24h
|
||||
; Archives created more than OLDER_THAN ago are subject to deletion
|
||||
OLDER_THAN = 24h
|
||||
|
||||
[git]
|
||||
; Disables highlight of added and removed changes
|
||||
DISABLE_DIFF_HIGHLIGHT = false
|
||||
; Max number of lines allowed of a single file in diff view
|
||||
MAX_GIT_DIFF_LINES = 1000
|
||||
; Max number of characters of a line allowed in diff view
|
||||
MAX_GIT_DIFF_LINE_CHARACTERS = 500
|
||||
; Max number of files shown in diff view
|
||||
MAX_GIT_DIFF_FILES = 100
|
||||
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
||||
; see more on http://git-scm.com/docs/git-gc/1.7.5
|
||||
GC_ARGS =
|
||||
|
||||
; Operation timeout in seconds
|
||||
[git.timeout]
|
||||
MIGRATE = 600
|
||||
MIRROR = 300
|
||||
CLONE = 300
|
||||
PULL = 300
|
||||
GC = 60
|
||||
|
||||
[mirror]
|
||||
; Default interval in hours between each check
|
||||
DEFAULT_INTERVAL = 8
|
||||
|
||||
[api]
|
||||
; Max number of items will response in a page
|
||||
MAX_RESPONSE_ITEMS = 50
|
||||
|
||||
[i18n]
|
||||
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
|
||||
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어
|
||||
|
||||
; Used for datetimepicker
|
||||
[i18n.datelang]
|
||||
en-US = en
|
||||
zh-CN = zh
|
||||
zh-HK = zh-TW
|
||||
zh-TW = zh-TW
|
||||
de-DE = de
|
||||
fr-FR = fr
|
||||
nl-NL = nl
|
||||
lv-LV = lv
|
||||
ru-RU = ru
|
||||
ja-JP = ja
|
||||
es-ES = es
|
||||
pt-BR = pt-BR
|
||||
pl-PL = pl
|
||||
bg-BG = bg
|
||||
it-IT = it
|
||||
fi-FI = fi
|
||||
tr-TR = tr
|
||||
cs-CZ = cs-CZ
|
||||
sr-SP = sr
|
||||
sv-SE = sv
|
||||
ko-KR = ko
|
||||
|
||||
; Extension mapping to highlight class
|
||||
; e.g. .toml=ini
|
||||
[highlight.mapping]
|
||||
|
||||
[other]
|
||||
SHOW_FOOTER_BRANDING = false
|
||||
; Show version information about Gitea and Go in the footer
|
||||
SHOW_FOOTER_VERSION = true
|
||||
; Show time of template execution in the footer
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
@@ -1,66 +0,0 @@
|
||||
Environment To Ini
|
||||
==================
|
||||
|
||||
Multiple docker users have requested that the Gitea docker is changed
|
||||
to permit arbitrary configuration via environment variables.
|
||||
|
||||
Gitea needs to use an ini file for configuration because the running
|
||||
environment that starts the docker may not be the same as that used
|
||||
by the hooks. An ini file also gives a good default and means that
|
||||
users do not have to completely provide a full environment.
|
||||
|
||||
With those caveats above, this command provides a generic way of
|
||||
converting suitably structured environment variables into any ini
|
||||
value.
|
||||
|
||||
To use the command is very simple just run it and the default gitea
|
||||
app.ini will be rewritten to take account of the variables provided,
|
||||
however there are various options to give slightly different
|
||||
behavior and these can be interrogated with the `-h` option.
|
||||
|
||||
The environment variables should be of the form:
|
||||
|
||||
GITEA__SECTION_NAME__KEY_NAME
|
||||
|
||||
Environment variables are usually restricted to a reduced character
|
||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
||||
characters outside of that set, they should be escaped as following:
|
||||
"_0X2E_" for ".". The entire section and key names can be escaped as
|
||||
a UTF8 byte string if necessary. E.g. to configure:
|
||||
|
||||
"""
|
||||
...
|
||||
[log.console]
|
||||
COLORIZE=false
|
||||
STDERR=true
|
||||
...
|
||||
"""
|
||||
|
||||
You would set the environment variables: "GITEA__LOG_0x2E_CONSOLE__COLORIZE=false"
|
||||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
||||
on the configuration cheat sheet.
|
||||
|
||||
To plug this command in to the docker, you simply compile the provided go file using:
|
||||
|
||||
go build environment-to-ini.go
|
||||
|
||||
And copy the resulting `environment-to-ini` command to /app/gitea in the docker.
|
||||
|
||||
Apply the below patch to /etc/s6/gitea.setup to wire this in.
|
||||
|
||||
If you find this useful please comment on #7287
|
||||
|
||||
|
||||
diff --git a/docker/root/etc/s6/gitea/setup b/docker/root/etc/s6/gitea/setup
|
||||
index f87ce9115..565bfcba9 100755
|
||||
--- a/docker/root/etc/s6/gitea/setup
|
||||
+++ b/docker/root/etc/s6/gitea/setup
|
||||
@@ -44,6 +44,8 @@ if [ ! -f ${GITEA_CUSTOM}/conf/app.ini ]; then
|
||||
SECRET_KEY=${SECRET_KEY:-""} \
|
||||
envsubst < /etc/templates/app.ini > ${GITEA_CUSTOM}/conf/app.ini
|
||||
|
||||
+ /app/gitea/environment-to-ini -c ${GITEA_CUSTOM}/conf/app.ini
|
||||
+
|
||||
chown ${USER}:git ${GITEA_CUSTOM}/conf/app.ini
|
||||
fi
|
||||
|
@@ -1,224 +0,0 @@
|
||||
// Copyright 2019 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 main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
|
||||
const EnvironmentPrefix = "GITEA"
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "environment-to-ini"
|
||||
app.Usage = "Use provided environment to update configuration ini"
|
||||
app.Description = `As a helper to allow docker users to update the gitea configuration
|
||||
through the environment, this command allows environment variables to
|
||||
be mapped to values in the ini.
|
||||
|
||||
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME"
|
||||
will be mapped to the ini section "[section_name]" and the key
|
||||
"KEY_NAME" with the value as provided.
|
||||
|
||||
Environment variables are usually restricted to a reduced character
|
||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
||||
characters outside of that set, they should be escaped as following:
|
||||
"_0X2E_" for ".". The entire section and key names can be escaped as
|
||||
a UTF8 byte string if necessary. E.g. to configure:
|
||||
|
||||
"""
|
||||
...
|
||||
[log.console]
|
||||
COLORIZE=false
|
||||
STDERR=true
|
||||
...
|
||||
"""
|
||||
|
||||
You would set the environment variables: "GITEA__LOG_0x2E_CONSOLE__COLORIZE=false"
|
||||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
||||
on the configuration cheat sheet.`
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "custom-path, C",
|
||||
Value: setting.CustomPath,
|
||||
Usage: "Custom path file path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "work-path, w",
|
||||
Value: setting.AppWorkPath,
|
||||
Usage: "Set the gitea working path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "out, o",
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "clear",
|
||||
Usage: "Clears the matched variables from the environment",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prefix, p",
|
||||
Value: EnvironmentPrefix,
|
||||
Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
||||
}
|
||||
}
|
||||
|
||||
func runEnvironmentToIni(c *cli.Context) error {
|
||||
providedCustom := c.String("custom-path")
|
||||
providedConf := c.String("config")
|
||||
providedWorkPath := c.String("work-path")
|
||||
setting.SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath)
|
||||
|
||||
cfg := ini.Empty()
|
||||
if com.IsFile(setting.CustomConf) {
|
||||
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
} else {
|
||||
log.Warn("Custom config '%s' not found, ignore this if you're running first time", setting.CustomConf)
|
||||
}
|
||||
cfg.NameMapper = ini.SnackCase
|
||||
|
||||
prefix := c.String("prefix") + "__"
|
||||
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
value := kv[idx+1:]
|
||||
if !strings.HasPrefix(eKey, prefix) {
|
||||
continue
|
||||
}
|
||||
eKey = eKey[len(prefix):]
|
||||
sectionName, keyName := DecodeSectionKey(eKey)
|
||||
if len(keyName) == 0 {
|
||||
continue
|
||||
}
|
||||
section, err := cfg.GetSection(sectionName)
|
||||
if err != nil {
|
||||
section, err = cfg.NewSection(sectionName)
|
||||
if err != nil {
|
||||
log.Error("Error creating section: %s : %v", sectionName, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
key := section.Key(keyName)
|
||||
if key == nil {
|
||||
key, err = section.NewKey(keyName, value)
|
||||
if err != nil {
|
||||
log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, value, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
key.SetValue(value)
|
||||
}
|
||||
destination := c.String("out")
|
||||
if len(destination) == 0 {
|
||||
destination = setting.CustomConf
|
||||
}
|
||||
err := cfg.SaveTo(destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Bool("clear") {
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
if strings.HasPrefix(eKey, prefix) {
|
||||
_ = os.Unsetenv(eKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
|
||||
|
||||
var escapeRegex = regexp.MustCompile(escapeRegexpString)
|
||||
|
||||
// DecodeSectionKey will decode a portable string encoded Section__Key pair
|
||||
// Portable strings are considered to be of the form [A-Z0-9_]*
|
||||
// We will encode a disallowed value as the UTF8 byte string preceded by _0X and
|
||||
// followed by _. E.g. _0X2C_ for a '-' and _0X2E_ for '.'
|
||||
// Section and Key are separated by a plain '__'.
|
||||
// The entire section can be encoded as a UTF8 byte string
|
||||
func DecodeSectionKey(encoded string) (string, string) {
|
||||
section := ""
|
||||
key := ""
|
||||
|
||||
inKey := false
|
||||
last := 0
|
||||
escapeStringIndices := escapeRegex.FindAllStringIndex(encoded, -1)
|
||||
for _, unescapeIdx := range escapeStringIndices {
|
||||
preceding := encoded[last:unescapeIdx[0]]
|
||||
if !inKey {
|
||||
if splitter := strings.Index(preceding, "__"); splitter > -1 {
|
||||
section += preceding[:splitter]
|
||||
inKey = true
|
||||
key += preceding[splitter+2:]
|
||||
} else {
|
||||
section += preceding
|
||||
}
|
||||
} else {
|
||||
key += preceding
|
||||
}
|
||||
toDecode := encoded[unescapeIdx[0]+3 : unescapeIdx[1]-1]
|
||||
decodedBytes := make([]byte, len(toDecode)/2)
|
||||
for i := 0; i < len(toDecode)/2; i++ {
|
||||
// Can ignore error here as we know these should be hexadecimal from the regexp
|
||||
byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 0)
|
||||
decodedBytes[i] = byte(byteInt)
|
||||
}
|
||||
if inKey {
|
||||
key += string(decodedBytes)
|
||||
} else {
|
||||
section += string(decodedBytes)
|
||||
}
|
||||
last = unescapeIdx[1]
|
||||
}
|
||||
remaining := encoded[last:]
|
||||
if !inKey {
|
||||
if splitter := strings.Index(remaining, "__"); splitter > -1 {
|
||||
section += remaining[:splitter]
|
||||
inKey = true
|
||||
key += remaining[splitter+2:]
|
||||
} else {
|
||||
section += remaining
|
||||
}
|
||||
} else {
|
||||
key += remaining
|
||||
}
|
||||
return section, key
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
########################################################################
|
||||
# This script some defaults for gitea to run in a FHS compliant manner #
|
||||
########################################################################
|
||||
|
||||
# It assumes that you place this script as gitea in /usr/bin
|
||||
#
|
||||
# And place the original in /usr/lib/gitea with working files in /var/lib/gitea
|
||||
# and main configuration in /etc/gitea/app.ini
|
||||
GITEA="/usr/lib/gitea/gitea"
|
||||
WORK_DIR="/var/lib/gitea"
|
||||
APP_INI="/etc/gitea/app.ini"
|
||||
|
||||
APP_INI_SET=""
|
||||
for i in "$@"; do
|
||||
case "$i" in
|
||||
"-c")
|
||||
APP_INI_SET=1
|
||||
;;
|
||||
"-c="*)
|
||||
APP_INI_SET=1
|
||||
;;
|
||||
"--config")
|
||||
APP_INI_SET=1
|
||||
;;
|
||||
"--config="*)
|
||||
APP_INI_SET=1
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$APP_INI_SET" ]; then
|
||||
CONF_ARG="-c \"$APP_INI\""
|
||||
fi
|
||||
|
||||
# Provide FHS compliant defaults to
|
||||
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" "$GITEA" $CONF_ARG "$@"
|
||||
|
||||
|
@@ -1,12 +0,0 @@
|
||||
# IDE and code editor configuration
|
||||
|
||||
## Table of Contents
|
||||
- [IDE and code editor configuration](#ide-and-code-editor-configuration)
|
||||
- [Microsoft Visual Studio Code](#microsoft-visual-studio-code)
|
||||
|
||||
## Microsoft Visual Studio Code
|
||||
Download Microsoft Visual Studio Code at https://code.visualstudio.com/ and follow instructions at https://code.visualstudio.com/docs/languages/go to setup Go extension for it.
|
||||
|
||||
Create new directory `.vscode` in Gitea root folder and copy contents of folder [contrib/ide/vscode](vscode/) to it. You can now use `Ctrl`+`Shift`+`B` to build gitea executable and `F5` to run it in debug mode.
|
||||
|
||||
Supported on Debian, Ubuntu, Red Hat, Fedora, SUSE Linux, MacOS and Microsoft Windows.
|
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"buildFlags": "",
|
||||
"port": 2345,
|
||||
"host": "127.0.0.1",
|
||||
"program": "${workspaceRoot}/main.go",
|
||||
"env": {},
|
||||
"args": ["web"],
|
||||
"showLog": true
|
||||
},
|
||||
{
|
||||
"name": "Launch (with SQLite3)",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"buildFlags": "-tags=\"sqlite sqlite_unlock_notify\"",
|
||||
"port": 2345,
|
||||
"host": "127.0.0.1",
|
||||
"program": "${workspaceRoot}/main.go",
|
||||
"env": {},
|
||||
"args": ["web"],
|
||||
"showLog": true
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "Build",
|
||||
"type": "shell",
|
||||
"command": "go",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"args": ["build"],
|
||||
"linux": {
|
||||
"args": [ "-o", "gitea", "${workspaceRoot}/main.go" ]
|
||||
},
|
||||
"osx": {
|
||||
"args": [ "-o", "gitea", "${workspaceRoot}/main.go" ]
|
||||
},
|
||||
"windows": {
|
||||
"args": [ "-o", "gitea.exe", "\"${workspaceRoot}\\main.go\""]
|
||||
},
|
||||
"problemMatcher": ["$go"]
|
||||
},
|
||||
{
|
||||
"taskName": "Build (with SQLite3)",
|
||||
"type": "shell",
|
||||
"command": "go",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"args": ["build", "-tags=\"sqlite sqlite_unlock_notify\""],
|
||||
"linux": {
|
||||
"args": ["-o", "gitea", "${workspaceRoot}/main.go"]
|
||||
},
|
||||
"osx": {
|
||||
"args": ["-o", "gitea", "${workspaceRoot}/main.go"]
|
||||
},
|
||||
"windows": {
|
||||
"args": ["-o", "gitea.exe", "\"${workspaceRoot}\\main.go\""]
|
||||
},
|
||||
"problemMatcher": ["$go"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,93 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# /etc/rc.d/init.d/gitea
|
||||
#
|
||||
# Runs the Gitea Git with a cup of tea.
|
||||
#
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
#
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: gitea
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start gitea at boot time.
|
||||
# Description: Control gitea.
|
||||
### END INIT INFO
|
||||
|
||||
# Source function library.
|
||||
. /etc/init.d/functions
|
||||
|
||||
# Default values
|
||||
|
||||
NAME=gitea
|
||||
GITEA_HOME=/var/lib/${NAME}
|
||||
GITEA_PATH=/usr/local/bin/${NAME}
|
||||
GITEA_USER=git
|
||||
SERVICENAME="Gitea - Git with a cup of tea"
|
||||
LOCKFILE=/var/lock/subsys/gitea
|
||||
LOGPATH=${GITEA_HOME}/log
|
||||
LOGFILE=${LOGPATH}/gitea.log
|
||||
RETVAL=0
|
||||
|
||||
# Read configuration from /etc/sysconfig/gitea to override defaults
|
||||
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
|
||||
|
||||
# Don't do anything if nothing is installed
|
||||
[ -x ${GITEA_PATH} ] || exit 0
|
||||
# exit if logpath dir is not created.
|
||||
[ -x ${LOGPATH} ] || exit 0
|
||||
|
||||
DAEMON_OPTS="--check $NAME"
|
||||
|
||||
# Set additional options, if any
|
||||
[ ! -z "$GITEA_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GITEA_USER}"
|
||||
|
||||
start() {
|
||||
cd ${GITEA_HOME}
|
||||
echo -n "Starting ${SERVICENAME}: "
|
||||
daemon $DAEMON_OPTS "${GITEA_PATH} web -c /etc/${NAME}/app.ini > ${LOGFILE} 2>&1 &"
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL = 0 ] && touch ${LOCKFILE}
|
||||
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
stop() {
|
||||
cd ${GITEA_HOME}
|
||||
echo -n "Shutting down ${SERVICENAME}: "
|
||||
killproc ${NAME}
|
||||
RETVAL=$?
|
||||
echo
|
||||
[ $RETVAL = 0 ] && rm -f ${LOCKFILE}
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
status ${NAME} > /dev/null 2>&1 && exit 0
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
status)
|
||||
status ${NAME}
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
reload)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ${NAME} {start|stop|status|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
@@ -1,89 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: gitea
|
||||
# Required-Start: $syslog $network
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: A self-hosted Git service written in Go.
|
||||
# Description: A self-hosted Git service written in Go.
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Danny Boisvert
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
|
||||
DESC="Gitea - Git with a cup of tea"
|
||||
NAME=gitea
|
||||
SERVICEVERBOSE=yes
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
WORKINGDIR=/var/lib/$NAME
|
||||
DAEMON=/usr/local/bin/$NAME
|
||||
DAEMON_ARGS="web -c /etc/$NAME/app.ini"
|
||||
USER=git
|
||||
USERBIND=""
|
||||
# If you want to bind Gitea to a port below 1024 uncomment
|
||||
# the line below
|
||||
#USERBIND="setcap cap_net_bind_service=+ep"
|
||||
STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/1/KILL/5}"
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
do_start()
|
||||
{
|
||||
$USERBIND $DAEMON
|
||||
sh -c "USER=$USER HOME=/home/$USER GITEA_WORK_DIR=$WORKINGDIR start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \\
|
||||
--background --chdir $WORKINGDIR --chuid $USER \\
|
||||
--exec $DAEMON -- $DAEMON_ARGS"
|
||||
}
|
||||
|
||||
do_stop()
|
||||
{
|
||||
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PIDFILE --name $NAME --oknodo
|
||||
rm -f $PIDFILE
|
||||
}
|
||||
|
||||
do_status()
|
||||
{
|
||||
if [ -f $PIDFILE ]; then
|
||||
if kill -0 $(cat "$PIDFILE"); then
|
||||
echo "$NAME is running, PID is $(cat $PIDFILE)"
|
||||
else
|
||||
echo "$NAME process is dead, but pidfile exists"
|
||||
fi
|
||||
else
|
||||
echo "$NAME is not running"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
echo "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
;;
|
||||
status)
|
||||
do_status
|
||||
;;
|
||||
restart)
|
||||
echo "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
@@ -1,48 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# PROVIDE: gitea
|
||||
# REQUIRE: NETWORKING SYSLOG
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf to enable gitea:
|
||||
#
|
||||
#gitea_enable="YES"
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="gitea"
|
||||
rcvar="gitea_enable"
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
: ${gitea_user:="git"}
|
||||
: ${gitea_enable:="NO"}
|
||||
: ${gitea_directory:="/var/lib/gitea"}
|
||||
|
||||
command="/usr/local/bin/gitea web -c /etc/gitea/app.ini"
|
||||
procname="$(echo $command |cut -d' ' -f1)"
|
||||
|
||||
pidfile="${gitea_directory}/${name}.pid"
|
||||
|
||||
start_cmd="${name}_start"
|
||||
stop_cmd="${name}_stop"
|
||||
|
||||
gitea_start() {
|
||||
cd ${gitea_directory}
|
||||
export USER=${gitea_user}
|
||||
export HOME=/usr/home/${gitea_user}
|
||||
export GITEA_WORK_DIR=${gitea_directory}
|
||||
/usr/sbin/daemon -f -u ${gitea_user} -p ${pidfile} $command
|
||||
}
|
||||
|
||||
gitea_stop() {
|
||||
if [ ! -f $pidfile ]; then
|
||||
echo "GITEA PID File not found. Maybe GITEA is not running?"
|
||||
else
|
||||
kill $(cat $pidfile)
|
||||
fi
|
||||
}
|
||||
|
||||
run_rc_command "$1"
|
@@ -1,15 +0,0 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
DIR=/var/lib/gitea
|
||||
USER=git
|
||||
|
||||
start_stop_daemon_args="--user ${USER} --chdir ${DIR}"
|
||||
command="/usr/local/bin/gitea"
|
||||
command_args="web -c /etc/gitea/app.ini"
|
||||
command_background=yes
|
||||
pidfile=/var/run/gitea.pid
|
||||
|
||||
depend()
|
||||
{
|
||||
need net
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $OpenBSD$
|
||||
|
||||
daemon="/usr/local/bin/gitea"
|
||||
daemon_user="git"
|
||||
daemon_flags="web -c /etc/gitea/app.ini"
|
||||
|
||||
gitea_directory="/var/lib/gitea"
|
||||
|
||||
rc_bg=YES
|
||||
|
||||
. /etc/rc.d/rc.subr
|
||||
|
||||
rc_start() {
|
||||
${rcexec} "cd ${gitea_directory}; ${daemon} ${daemon_flags} ${_bg}"
|
||||
}
|
||||
|
||||
rc_cmd $1
|
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
|
||||
<service_bundle type="manifest" name="export">
|
||||
<service name="gitea" type="service" version="1">
|
||||
<create_default_instance enabled="false"/>
|
||||
|
||||
<dependency name="network" grouping="require_all" restart_on="refresh" type="service">
|
||||
<service_fmri value="svc:/milestone/network:default"/>
|
||||
</dependency>
|
||||
|
||||
<dependency name="filesystem" grouping="require_all" restart_on="refresh" type="service">
|
||||
<service_fmri value="svc:/system/filesystem/local"/>
|
||||
</dependency>
|
||||
|
||||
<exec_method
|
||||
type="method"
|
||||
name="start"
|
||||
exec="/opt/local/bin/gitea web"
|
||||
timeout_seconds="60">
|
||||
<method_context>
|
||||
<method_credential user="git" group="git" />
|
||||
<method_environment>
|
||||
<envvar name='GITEA_WORK_DIR' value='/opt/local/share/gitea'/>
|
||||
<envvar name='GITEA_CUSTOM' value='/opt/local/etc/gitea'/>
|
||||
<envvar name='HOME' value='/var/db/gitea'/>
|
||||
<envvar name='PATH' value='/opt/local/bin:${PATH}'/>
|
||||
<envvar name='USER' value='git'/>
|
||||
</method_environment>
|
||||
</method_context>
|
||||
</exec_method>
|
||||
<exec_method type="method" name="stop" exec=":kill" timeout_seconds="60"/>
|
||||
|
||||
<property_group name="application" type="application"></property_group>
|
||||
<property_group name="startd" type="framework">
|
||||
<propval name="duration" type="astring" value="child"/>
|
||||
<propval name="ignore_error" type="astring" value="core,signal"/>
|
||||
</property_group>
|
||||
|
||||
<template>
|
||||
<common_name>
|
||||
<loctext xml:lang="C">A painless, self-hosted Git service</loctext>
|
||||
</common_name>
|
||||
</template>
|
||||
|
||||
</service>
|
||||
</service_bundle>
|
@@ -1,115 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# /etc/init.d/gitea
|
||||
#
|
||||
# Runs the Gitea Git with a cup of tea.
|
||||
#
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: gitea
|
||||
# Required-Start: $remote_fs
|
||||
# Required-Stop: $remote_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start gitea at boot time.
|
||||
# Description: Control gitea.
|
||||
### END INIT INFO
|
||||
|
||||
# Default values
|
||||
|
||||
NAME=gitea
|
||||
GITEA_HOME=/var/lib/$NAME
|
||||
GITEA_PATH=/usr/local/bin/$NAME
|
||||
GITEA_USER=git
|
||||
SERVICENAME="Gitea - Git with a cup of tea"
|
||||
LOCKFILE=/var/lock/subsys/gitea
|
||||
LOGPATH=${GITEA_HOME}/log
|
||||
LOGFILE=${LOGPATH}/error.log
|
||||
# gitea creates its own gitea.log from stdout
|
||||
RETVAL=0
|
||||
|
||||
# Read configuration from /etc/sysconfig/gitea to override defaults
|
||||
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
|
||||
|
||||
# Don't do anything if nothing is installed
|
||||
test -x ${GITEA_PATH} || { echo "$NAME not installed";
|
||||
if [ "$1" = "stop" ]; then exit 0;
|
||||
else exit 5; fi; }
|
||||
|
||||
# exit if logpath dir is not created.
|
||||
test -r ${LOGPATH} || { echo "$LOGPATH not existing";
|
||||
if [ "$1" = "stop" ]; then exit 0;
|
||||
else exit 6; fi; }
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.status
|
||||
|
||||
# Reset status of this service
|
||||
rc_reset
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting ${SERVICENAME} "
|
||||
|
||||
# As we can't use startproc, we have to check ourselves if the service is already running
|
||||
/sbin/checkproc ${GITEA_PATH}
|
||||
if [ $? -eq 0 ]; then
|
||||
# return skipped as service is already running
|
||||
(exit 5)
|
||||
else
|
||||
su - ${GITEA_USER} -c "USER=${GITEA_USER} GITEA_WORK_DIR=${GITEA_HOME} ${GITEA_PATH} web -c /etc/${NAME}/app.ini 2>&1 >>${LOGFILE} &"
|
||||
fi
|
||||
|
||||
# Remember status and be verbose
|
||||
rc_status -v
|
||||
;;
|
||||
|
||||
stop)
|
||||
echo -n "Shutting down ${SERVICENAME} "
|
||||
|
||||
## Stop daemon with killproc(8) and if this fails
|
||||
## killproc sets the return value according to LSB.
|
||||
/sbin/killproc ${GITEA_PATH}
|
||||
|
||||
# Remember status and be verbose
|
||||
rc_status -v
|
||||
;;
|
||||
|
||||
restart)
|
||||
## Stop the service and regardless of whether it was
|
||||
## running or not, start it again.
|
||||
$0 stop
|
||||
$0 start
|
||||
|
||||
# Remember status and be quiet
|
||||
rc_status
|
||||
;;
|
||||
|
||||
status)
|
||||
echo -n "Checking for ${SERVICENAME} "
|
||||
## Check status with checkproc(8), if process is running
|
||||
## checkproc will return with exit status 0.
|
||||
|
||||
# Return value is slightly different for the status command:
|
||||
# 0 - service up and running
|
||||
# 1 - service dead, but /var/run/ pid file exists
|
||||
# 2 - service dead, but /var/lock/ lock file exists
|
||||
# 3 - service not running (unused)
|
||||
# 4 - service status unknown :-(
|
||||
# 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
|
||||
|
||||
# NOTE: checkproc returns LSB compliant status values.
|
||||
/sbin/checkproc ${GITEA_PATH}
|
||||
# NOTE: rc_status knows that we called this init script with
|
||||
# "status" option and adapts its messages accordingly.
|
||||
rc_status -v
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|status|restart}"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
rc_exit
|
@@ -1,107 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: gitea
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
name: gitea
|
||||
labels:
|
||||
app: gitea
|
||||
spec:
|
||||
containers:
|
||||
- name: gitea
|
||||
image: gitea/gitea:latest
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- mountPath: "/var/lib/gitea"
|
||||
name: "root"
|
||||
- mountPath: "/data"
|
||||
name: "data"
|
||||
ports:
|
||||
- containerPort: 22
|
||||
name: ssh
|
||||
protocol: TCP
|
||||
- containerPort: 3000
|
||||
name: http
|
||||
protocol: TCP
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
# Set up a data directory for gitea
|
||||
# For production usage, you should consider using PV/PVC instead(or simply using storage like NAS)
|
||||
# For more details, please see https://kubernetes.io/docs/concepts/storage/volumes/
|
||||
- name: "root"
|
||||
hostPath:
|
||||
# directory location on host
|
||||
path: "/var/lib/gitea"
|
||||
# this field is optional
|
||||
type: Directory
|
||||
- name: "data"
|
||||
hostPath:
|
||||
path: "/data/gitea"
|
||||
type: Directory
|
||||
selector:
|
||||
matchLabels:
|
||||
app: gitea
|
||||
---
|
||||
# Using cluster mode
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-web
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea-web
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 3000
|
||||
name: http
|
||||
selector:
|
||||
app: gitea
|
||||
---
|
||||
# Using node-port mode
|
||||
# This mainly open a specific TCP port for SSH usage on each host,
|
||||
# so you can use a proxy layer to handle it(e.g. slb, nginx)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gitea-ssh
|
||||
namespace: gitea
|
||||
labels:
|
||||
app: gitea-ssh
|
||||
spec:
|
||||
ports:
|
||||
- port: 22
|
||||
targetPort: 22
|
||||
nodePort: 30022
|
||||
name: ssh
|
||||
selector:
|
||||
app: gitea
|
||||
type: NodePort
|
||||
---
|
||||
# Ingress is always suitable for HTTP usage,
|
||||
# we suggest using an proxy layer such as slb to send traffic to different ports.
|
||||
# Usually 80/443 for web and 22 directly for SSH.
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: gitea
|
||||
namespace: gitea
|
||||
spec:
|
||||
rules:
|
||||
- host: your-gitea-host.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: gitea-web
|
||||
servicePort: 80
|
@@ -1,265 +0,0 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
Checkout a PR and load the tests data into sqlite database
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
|
||||
context2 "github.com/gorilla/context"
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/config"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
var codeFilePath = "contrib/pr/checkout.go"
|
||||
|
||||
func runPR() {
|
||||
log.Printf("[PR] Starting gitea ...\n")
|
||||
curDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.NewContext()
|
||||
|
||||
setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
|
||||
if err != nil {
|
||||
log.Fatalf("TempDir: %v\n", err)
|
||||
}
|
||||
setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata")
|
||||
if err != nil {
|
||||
log.Fatalf("TempDir: %v\n", err)
|
||||
}
|
||||
setting.AppWorkPath = curDir
|
||||
setting.StaticRootPath = curDir
|
||||
setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/")
|
||||
if err != nil {
|
||||
log.Fatalf("url.Parse: %v\n", err)
|
||||
}
|
||||
|
||||
setting.AppURL = "http://localhost:8080/"
|
||||
setting.HTTPPort = "8080"
|
||||
setting.SSH.Domain = "localhost"
|
||||
setting.SSH.Port = 3000
|
||||
setting.InstallLock = true
|
||||
setting.SecretKey = "9pCviYTWSb"
|
||||
setting.InternalToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8"
|
||||
curUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
setting.RunUser = curUser.Username
|
||||
|
||||
log.Printf("[PR] Loading fixtures data ...\n")
|
||||
setting.CheckLFSVersion()
|
||||
//models.LoadConfigs()
|
||||
/*
|
||||
setting.Database.Type = "sqlite3"
|
||||
setting.Database.Path = ":memory:"
|
||||
setting.Database.Timeout = 500
|
||||
*/
|
||||
db := setting.Cfg.Section("database")
|
||||
db.NewKey("DB_TYPE", "sqlite3")
|
||||
db.NewKey("PATH", ":memory:")
|
||||
|
||||
routers.NewServices()
|
||||
setting.Database.LogSQL = true
|
||||
//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||
|
||||
var helper testfixtures.Helper = &testfixtures.SQLite{}
|
||||
models.NewEngine(context.Background(), func(_ *xorm.Engine) error {
|
||||
return nil
|
||||
})
|
||||
models.HasEngine = true
|
||||
//x.ShowSQL(true)
|
||||
err = models.InitFixtures(
|
||||
helper,
|
||||
path.Join(curDir, "models/fixtures/"),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("Error initializing test database: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
models.LoadFixtures()
|
||||
os.RemoveAll(setting.RepoRootPath)
|
||||
os.RemoveAll(models.LocalCopyPath())
|
||||
com.CopyDir(path.Join(curDir, "integrations/gitea-repositories-meta"), setting.RepoRootPath)
|
||||
|
||||
log.Printf("[PR] Setting up router\n")
|
||||
//routers.GlobalInit()
|
||||
external.RegisterParsers()
|
||||
markup.Init()
|
||||
m := routes.NewMacaron()
|
||||
routes.RegisterRoutes(m)
|
||||
|
||||
log.Printf("[PR] Ready for testing !\n")
|
||||
log.Printf("[PR] Login with user1, user2, user3, ... with pass: password\n")
|
||||
/*
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
log.Info("LFS server enabled")
|
||||
}
|
||||
|
||||
if setting.EnablePprof {
|
||||
go func() {
|
||||
log.Info("Starting pprof server on localhost:6060")
|
||||
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
|
||||
}()
|
||||
}
|
||||
*/
|
||||
|
||||
//Start the server
|
||||
http.ListenAndServe(":8080", context2.ClearHandler(m))
|
||||
|
||||
log.Printf("[PR] Cleaning up ...\n")
|
||||
/*
|
||||
if err = os.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
||||
fmt.Printf("os.RemoveAll: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = os.RemoveAll(setting.Indexer.RepoPath); err != nil {
|
||||
fmt.Printf("Unable to remove repo indexer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
*/
|
||||
if err = os.RemoveAll(setting.RepoRootPath); err != nil {
|
||||
log.Fatalf("os.RemoveAll: %v\n", err)
|
||||
}
|
||||
if err = os.RemoveAll(setting.AppDataPath); err != nil {
|
||||
log.Fatalf("os.RemoveAll: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var runPRFlag = flag.Bool("run", false, "Run the PR code")
|
||||
flag.Parse()
|
||||
if *runPRFlag {
|
||||
runPR()
|
||||
return
|
||||
}
|
||||
|
||||
// To force checkout (e.g. Windows complains about unclean work tree) set env variable FORCE=true
|
||||
force, err := strconv.ParseBool(os.Getenv("FORCE"))
|
||||
if err != nil {
|
||||
force = false
|
||||
}
|
||||
|
||||
//Otherwise checkout PR
|
||||
if len(os.Args) != 2 {
|
||||
log.Fatal("Need only one arg: the PR number")
|
||||
}
|
||||
pr := os.Args[1]
|
||||
|
||||
codeFilePath = filepath.FromSlash(codeFilePath) //Convert to running OS
|
||||
|
||||
//Copy this file if it will not exist in the PR branch
|
||||
dat, err := ioutil.ReadFile(codeFilePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to cache this code file : %v", err)
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(".")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open the repo : %v", err)
|
||||
}
|
||||
|
||||
//Find remote upstream
|
||||
remotes, err := repo.Remotes()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to list remotes of repo : %v", err)
|
||||
}
|
||||
remoteUpstream := "origin" //Default
|
||||
for _, r := range remotes {
|
||||
if r.Config().URLs[0] == "https://github.com/go-gitea/gitea" || r.Config().URLs[0] == "git@github.com:go-gitea/gitea.git" { //fetch at index 0
|
||||
remoteUpstream = r.Config().Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
branch := fmt.Sprintf("pr-%s-%d", pr, time.Now().Unix())
|
||||
branchRef := plumbing.NewBranchReferenceName(branch)
|
||||
|
||||
log.Printf("Fetching PR #%s in %s\n", pr, branch)
|
||||
if runtime.GOOS == "windows" {
|
||||
//Use git cli command for windows
|
||||
runCmd("git", "fetch", remoteUpstream, fmt.Sprintf("pull/%s/head:%s", pr, branch))
|
||||
} else {
|
||||
ref := fmt.Sprintf("refs/pull/%s/head:%s", pr, branchRef)
|
||||
err = repo.Fetch(&git.FetchOptions{
|
||||
RemoteName: remoteUpstream,
|
||||
RefSpecs: []config.RefSpec{
|
||||
config.RefSpec(ref),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to fetch %s from %s : %v", ref, remoteUpstream, err)
|
||||
}
|
||||
}
|
||||
|
||||
tree, err := repo.Worktree()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse git tree : %v", err)
|
||||
}
|
||||
log.Printf("Checkout PR #%s in %s\n", pr, branch)
|
||||
err = tree.Checkout(&git.CheckoutOptions{
|
||||
Branch: branchRef,
|
||||
Force: force,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to checkout %s : %v", branch, err)
|
||||
}
|
||||
|
||||
//Copy this file if not exist
|
||||
if _, err := os.Stat(codeFilePath); os.IsNotExist(err) {
|
||||
err = os.MkdirAll(filepath.Dir(codeFilePath), 0755)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||
}
|
||||
err = ioutil.WriteFile(codeFilePath, dat, 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||
}
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
//Start with integration test
|
||||
runCmd("go", "run", "-tags", "sqlite sqlite_unlock_notify", codeFilePath, "-run")
|
||||
}
|
||||
func runCmd(cmd ...string) {
|
||||
log.Printf("Executing : %s ...\n", cmd)
|
||||
c := exec.Command(cmd[0], cmd[1:]...)
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
if err := c.Start(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
if err := c.Wait(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
[Unit]
|
||||
Description=Gitea (Git with a cup of tea)
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
###
|
||||
# Don't forget to add the database service requirements
|
||||
###
|
||||
#
|
||||
#Requires=mysql.service
|
||||
#Requires=mariadb.service
|
||||
#Requires=postgresql.service
|
||||
#Requires=memcached.service
|
||||
#Requires=redis.service
|
||||
#
|
||||
###
|
||||
# If using socket activation for main http/s
|
||||
###
|
||||
#
|
||||
#After=gitea.main.socket
|
||||
#Requires=gitea.main.socket
|
||||
#
|
||||
###
|
||||
# (You can also provide gitea an http fallback and/or ssh socket too)
|
||||
#
|
||||
# An example of /etc/systemd/system/gitea.main.socket
|
||||
###
|
||||
##
|
||||
## [Unit]
|
||||
## Description=Gitea Web Socket
|
||||
## PartOf=gitea.service
|
||||
##
|
||||
## [Socket]
|
||||
## Service=gitea.service
|
||||
## ListenStream=<some_port>
|
||||
## NoDelay=true
|
||||
##
|
||||
## [Install]
|
||||
## WantedBy=sockets.target
|
||||
##
|
||||
###
|
||||
|
||||
[Service]
|
||||
# Modify these two values and uncomment them if you have
|
||||
# repos with lots of files and get an HTTP error 500 because
|
||||
# of that
|
||||
###
|
||||
#LimitMEMLOCK=infinity
|
||||
#LimitNOFILE=65535
|
||||
RestartSec=2s
|
||||
Type=simple
|
||||
User=git
|
||||
Group=git
|
||||
WorkingDirectory=/var/lib/gitea/
|
||||
# If using Unix socket: tells systemd to create the /run/gitea folder, which will contain the gitea.sock file
|
||||
# (manually creating /run/gitea doesn't work, because it would not persist across reboots)
|
||||
#RuntimeDirectory=gitea
|
||||
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
||||
Restart=always
|
||||
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
|
||||
# If you want to bind Gitea to a port below 1024, uncomment
|
||||
# the two values below, or use socket activation to pass Gitea its ports as above
|
||||
###
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
#AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
###
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -1,964 +0,0 @@
|
||||
|
||||
; This file lists the default values used by Gitea
|
||||
; Copy required sections to your own app.ini (default is custom/conf/app.ini)
|
||||
; and modify as needed.
|
||||
|
||||
; see https://docs.gitea.io/en-us/config-cheat-sheet/ for additional documentation.
|
||||
|
||||
; App name that shows in every page title
|
||||
APP_NAME = Gitea: Git with a cup of tea
|
||||
; Change it if you run locally
|
||||
RUN_USER = git
|
||||
; Either "dev", "prod" or "test", default is "dev"
|
||||
RUN_MODE = dev
|
||||
|
||||
[repository]
|
||||
ROOT =
|
||||
SCRIPT_TYPE = bash
|
||||
; Default ANSI charset
|
||||
ANSI_CHARSET =
|
||||
; Force every new repository to be private
|
||||
FORCE_PRIVATE = false
|
||||
; Default privacy setting when creating a new repository, allowed values: last, private, public. Default is last which means the last setting used.
|
||||
DEFAULT_PRIVATE = last
|
||||
; Global limit of repositories per user, applied at creation time. -1 means no limit
|
||||
MAX_CREATION_LIMIT = -1
|
||||
; Mirror sync queue length, increase if mirror syncing starts hanging
|
||||
MIRROR_QUEUE_LENGTH = 1000
|
||||
; Patch test queue length, increase if pull request patch testing starts hanging
|
||||
PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||
; Preferred Licenses to place at the top of the List
|
||||
; The name here must match the filename in conf/license or custom/conf/license
|
||||
PREFERRED_LICENSES = Apache License 2.0,MIT License
|
||||
; Disable the ability to interact with repositories using the HTTP protocol
|
||||
DISABLE_HTTP_GIT = false
|
||||
; Value for Access-Control-Allow-Origin header, default is not to present
|
||||
; WARNING: This maybe harmful to you website if you do not give it a right value.
|
||||
ACCESS_CONTROL_ALLOW_ORIGIN =
|
||||
; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
||||
USE_COMPAT_SSH_URI = false
|
||||
; Close issues as long as a commit on any branch marks it as fixed
|
||||
DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
|
||||
; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
|
||||
ENABLE_PUSH_CREATE_USER = false
|
||||
ENABLE_PUSH_CREATE_ORG = false
|
||||
|
||||
[repository.editor]
|
||||
; List of file extensions for which lines should be wrapped in the CodeMirror editor
|
||||
; Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||
; Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match
|
||||
PREVIEWABLE_FILE_MODES = markdown
|
||||
|
||||
[repository.local]
|
||||
; Path for local repository copy. Defaults to `tmp/local-repo`
|
||||
LOCAL_COPY_PATH = tmp/local-repo
|
||||
; Path for local wiki copy. Defaults to `tmp/local-wiki`
|
||||
LOCAL_WIKI_PATH = tmp/local-wiki
|
||||
|
||||
[repository.upload]
|
||||
; Whether repository file uploads are enabled. Defaults to `true`
|
||||
ENABLED = true
|
||||
; Path for uploads. Defaults to `data/tmp/uploads` (tmp gets deleted on gitea restart)
|
||||
TEMP_PATH = data/tmp/uploads
|
||||
; One or more allowed types, e.g. image/jpeg|image/png. Nothing means any file type
|
||||
ALLOWED_TYPES =
|
||||
; Max size of each file in megabytes. Defaults to 3MB
|
||||
FILE_MAX_SIZE = 3
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[repository.pull-request]
|
||||
; List of prefixes used in Pull Request title to mark them as Work In Progress
|
||||
WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
|
||||
; List of keywords used in Pull Request comments to automatically close a related issue
|
||||
CLOSE_KEYWORDS=close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved
|
||||
; List of keywords used in Pull Request comments to automatically reopen a related issue
|
||||
REOPEN_KEYWORDS=reopen,reopens,reopened
|
||||
; In the default merge message for squash commits include at most this many commits
|
||||
DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT=50
|
||||
; In the default merge message for squash commits limit the size of the commit messages to this
|
||||
DEFAULT_MERGE_MESSAGE_SIZE=5120
|
||||
; In the default merge message for squash commits walk all commits to include all authors in the Co-authored-by otherwise just use those in the limited list
|
||||
DEFAULT_MERGE_MESSAGE_ALL_AUTHORS=false
|
||||
; In default merge messages limit the number of approvers listed as Reviewed-by: to this many
|
||||
DEFAULT_MERGE_MESSAGE_MAX_APPROVERS=10
|
||||
; In default merge messages only include approvers who are official
|
||||
DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY=true
|
||||
|
||||
[repository.issue]
|
||||
; List of reasons why a Pull Request or Issue can be locked
|
||||
LOCK_REASONS=Too heated,Off-topic,Resolved,Spam
|
||||
|
||||
[repository.signing]
|
||||
; GPG key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey
|
||||
; run in the context of the RUN_USER
|
||||
; Switch to none to stop signing completely
|
||||
SIGNING_KEY = default
|
||||
; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer.
|
||||
; These should match a publicized name and email address for the key. (When SIGNING_KEY is default these are set to
|
||||
; the results of git config --get user.name and git config --get user.email respectively and can only be overrided
|
||||
; by setting the SIGNING_KEY ID to the correct ID.)
|
||||
SIGNING_NAME =
|
||||
SIGNING_EMAIL =
|
||||
; Determines when gitea should sign the initial commit when creating a repository
|
||||
; Either:
|
||||
; - never
|
||||
; - pubkey: only sign if the user has a pubkey
|
||||
; - twofa: only sign if the user has logged in with twofa
|
||||
; - always
|
||||
; options other than none and always can be combined as comma separated list
|
||||
INITIAL_COMMIT = always
|
||||
; Determines when to sign for CRUD actions
|
||||
; - as above
|
||||
; - parentsigned: requires that the parent commit is signed.
|
||||
CRUD_ACTIONS = pubkey, twofa, parentsigned
|
||||
; Determines when to sign Wiki commits
|
||||
; - as above
|
||||
WIKI = never
|
||||
; Determines when to sign on merges
|
||||
; - basesigned: require that the parent of commit on the base repo is signed.
|
||||
; - commitssigned: require that all the commits in the head branch are signed.
|
||||
; - approved: only sign when merging an approved pr to a protected branch
|
||||
MERGES = pubkey, twofa, basesigned, commitssigned
|
||||
|
||||
[cors]
|
||||
; More information about CORS can be found here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#The_HTTP_response_headers
|
||||
; enable cors headers (disabled by default)
|
||||
ENABLED=false
|
||||
; scheme of allowed requests
|
||||
SCHEME=http
|
||||
; list of requesting domains that are allowed
|
||||
ALLOW_DOMAIN=*
|
||||
; allow subdomains of headers listed above to request
|
||||
ALLOW_SUBDOMAIN=false
|
||||
; list of methods allowed to request
|
||||
METHODS=GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS
|
||||
; max time to cache response
|
||||
MAX_AGE=10m
|
||||
; allow request with credentials
|
||||
ALLOW_CREDENTIALS=false
|
||||
|
||||
[ui]
|
||||
; Number of repositories that are displayed on one explore page
|
||||
EXPLORE_PAGING_NUM = 20
|
||||
; Number of issues that are displayed on one page
|
||||
ISSUE_PAGING_NUM = 10
|
||||
; Number of maximum commits displayed in one activity feed
|
||||
FEED_MAX_COMMIT_NUM = 5
|
||||
; Number of maximum commits displayed in commit graph.
|
||||
GRAPH_MAX_COMMIT_NUM = 100
|
||||
; Number of line of codes shown for a code comment
|
||||
CODE_COMMENT_LINES = 4
|
||||
; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||
; An invalid color like "none" or "disable" will have the default style
|
||||
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||
THEME_COLOR_META_TAG = `#6cc644`
|
||||
; Max size of files to be displayed (default is 8MiB)
|
||||
MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
; Whether the email of the user should be shown in the Explore Users page
|
||||
SHOW_USER_EMAIL = true
|
||||
; Set the default theme for the Gitea install
|
||||
DEFAULT_THEME = gitea
|
||||
; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
|
||||
THEMES = gitea,arc-green
|
||||
; All available reactions. Allow users react with different emoji's
|
||||
; For the whole list look at https://gitea.com/gitea/gitea.com/issues/8
|
||||
REACTIONS = +1, -1, laugh, hooray, confused, heart, rocket, eyes
|
||||
; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
|
||||
DEFAULT_SHOW_FULL_NAME = false
|
||||
; Whether to search within description at repository search on explore page.
|
||||
SEARCH_REPO_DESCRIPTION = true
|
||||
; Whether to enable a Service Worker to cache frontend assets
|
||||
USE_SERVICE_WORKER = true
|
||||
|
||||
[ui.admin]
|
||||
; Number of users that are displayed on one page
|
||||
USER_PAGING_NUM = 50
|
||||
; Number of repos that are displayed on one page
|
||||
REPO_PAGING_NUM = 50
|
||||
; Number of notices that are displayed on one page
|
||||
NOTICE_PAGING_NUM = 25
|
||||
; Number of organizations that are displayed on one page
|
||||
ORG_PAGING_NUM = 50
|
||||
|
||||
[ui.user]
|
||||
; Number of repos that are displayed on one page
|
||||
REPO_PAGING_NUM = 15
|
||||
|
||||
[ui.meta]
|
||||
AUTHOR = Gitea - Git with a cup of tea
|
||||
DESCRIPTION = Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go
|
||||
KEYWORDS = go,git,self-hosted,gitea
|
||||
|
||||
[markdown]
|
||||
; Enable hard line break extension
|
||||
ENABLE_HARD_LINE_BREAK = false
|
||||
; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
|
||||
; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
|
||||
; URLs starting with http and https are always displayed, whatever is put in this entry.
|
||||
CUSTOM_URL_SCHEMES =
|
||||
; List of file extensions that should be rendered/edited as Markdown
|
||||
; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma
|
||||
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
|
||||
[server]
|
||||
; The protocol the server listens on. One of 'http', 'https', 'unix' or 'fcgi'.
|
||||
PROTOCOL = http
|
||||
DOMAIN = localhost
|
||||
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
; when STATIC_URL_PREFIX is empty it will follow APP_URL
|
||||
STATIC_URL_PREFIX =
|
||||
; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
|
||||
HTTP_ADDR = 0.0.0.0
|
||||
HTTP_PORT = 3000
|
||||
; If REDIRECT_OTHER_PORT is true, and PROTOCOL is set to https an http server
|
||||
; will be started on PORT_TO_REDIRECT and it will redirect plain, non-secure http requests to the main
|
||||
; ROOT_URL. Defaults are false for REDIRECT_OTHER_PORT and 80 for
|
||||
; PORT_TO_REDIRECT.
|
||||
REDIRECT_OTHER_PORT = false
|
||||
PORT_TO_REDIRECT = 80
|
||||
; Permission for unix socket
|
||||
UNIX_SOCKET_PERMISSION = 666
|
||||
; Local (DMZ) URL for Gitea workers (such as SSH update) accessing web service.
|
||||
; In most cases you do not need to change the default value.
|
||||
; Alter it only if your SSH server node is not the same as HTTP node.
|
||||
; Do not set this variable if PROTOCOL is set to 'unix'.
|
||||
LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
||||
; Disable SSH feature when not available
|
||||
DISABLE_SSH = false
|
||||
; Whether to use the builtin SSH server or not.
|
||||
START_SSH_SERVER = false
|
||||
; Username to use for the builtin SSH server. If blank, then it is the value of RUN_USER.
|
||||
BUILTIN_SSH_SERVER_USER =
|
||||
; Domain name to be exposed in clone URL
|
||||
SSH_DOMAIN = %(DOMAIN)s
|
||||
; The network interface the builtin SSH server should listen on
|
||||
SSH_LISTEN_HOST =
|
||||
; Port number to be exposed in clone URL
|
||||
SSH_PORT = 22
|
||||
; The port number the builtin SSH server should listen on
|
||||
SSH_LISTEN_PORT = %(SSH_PORT)s
|
||||
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
||||
SSH_ROOT_PATH =
|
||||
; Gitea will create a authorized_keys file by default when it is not using the internal ssh server
|
||||
; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
||||
SSH_CREATE_AUTHORIZED_KEYS_FILE = true
|
||||
; For the built-in SSH server, choose the ciphers to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128
|
||||
; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_KEY_EXCHANGES = diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, curve25519-sha256@libssh.org
|
||||
; For the built-in SSH server, choose the MACs to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_MACS = hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1, hmac-sha1-96
|
||||
; Directory to create temporary files in when testing public keys using ssh-keygen,
|
||||
; default is the system temporary directory.
|
||||
SSH_KEY_TEST_PATH =
|
||||
; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||
SSH_KEYGEN_PATH = ssh-keygen
|
||||
; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
||||
SSH_BACKUP_AUTHORIZED_KEYS = true
|
||||
; Enable exposure of SSH clone URL to anonymous visitors, default is false
|
||||
SSH_EXPOSE_ANONYMOUS = false
|
||||
; Indicate whether to check minimum key size with corresponding type
|
||||
MINIMUM_KEY_SIZE_CHECK = false
|
||||
; Disable CDN even in "prod" mode
|
||||
OFFLINE_MODE = false
|
||||
DISABLE_ROUTER_LOG = false
|
||||
; Generate steps:
|
||||
; $ ./gitea cert -ca=true -duration=8760h0m0s -host=myhost.example.com
|
||||
;
|
||||
; Or from a .pfx file exported from the Windows certificate store (do
|
||||
; 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
|
||||
; Root directory containing templates and static files.
|
||||
; default is the path where Gitea is executed
|
||||
STATIC_ROOT_PATH =
|
||||
; Default path for App data
|
||||
APP_DATA_PATH = data
|
||||
; Application level GZIP support
|
||||
ENABLE_GZIP = false
|
||||
; Application profiling (memory and cpu)
|
||||
; For "web" command it listens on localhost:6060
|
||||
; For "serve" command it dumps to disk at PPROF_DATA_PATH as (cpuprofile|memprofile)_<username>_<temporary id>
|
||||
ENABLE_PPROF = false
|
||||
; PPROF_DATA_PATH, use an absolute path when you start gitea as service
|
||||
PPROF_DATA_PATH = data/tmp/pprof
|
||||
; Landing page, can be "home", "explore", "organizations" or "login"
|
||||
; The "login" choice is not a security measure but just a UI flow change, use REQUIRE_SIGNIN_VIEW to force users to log in.
|
||||
LANDING_PAGE = home
|
||||
; Enables git-lfs support. true or false, default is false.
|
||||
LFS_START_SERVER = false
|
||||
; Where your lfs files reside, default is data/lfs.
|
||||
LFS_CONTENT_PATH = data/lfs
|
||||
; LFS authentication secret, change this yourself
|
||||
LFS_JWT_SECRET =
|
||||
; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
|
||||
LFS_HTTP_AUTH_EXPIRY = 20m
|
||||
; Allow graceful restarts using SIGHUP to fork
|
||||
ALLOW_GRACEFUL_RESTARTS = true
|
||||
; After a restart the parent will finish ongoing requests before
|
||||
; shutting down. Force shutdown if this process takes longer than this delay.
|
||||
; set to a negative value to disable
|
||||
GRACEFUL_HAMMER_TIME = 60s
|
||||
; Allows the setting of a startup timeout and waithint for Windows as SVC service
|
||||
; 0 disables this.
|
||||
STARTUP_TIMEOUT = 0
|
||||
; Static resources, includes resources on custom/, public/ and all uploaded avatars web browser cache time, default is 6h
|
||||
STATIC_CACHE_TIME = 6h
|
||||
|
||||
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
|
||||
[ssh.minimum_key_sizes]
|
||||
ED25519 = 256
|
||||
ECDSA = 256
|
||||
RSA = 2048
|
||||
DSA = 1024
|
||||
|
||||
[database]
|
||||
; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice
|
||||
DB_TYPE = mysql
|
||||
HOST = 127.0.0.1:3306
|
||||
NAME = gitea
|
||||
USER = root
|
||||
; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
PASSWD =
|
||||
; For Postgres, either "disable" (default), "require", or "verify-full"
|
||||
; For MySQL, either "false" (default), "true", or "skip-verify"
|
||||
SSL_MODE = disable
|
||||
; For MySQL only, either "utf8" or "utf8mb4", default is "utf8".
|
||||
; NOTICE: for "utf8mb4" you must use MySQL InnoDB > 5.6. Gitea is unable to check this.
|
||||
CHARSET = utf8
|
||||
; For "sqlite3" and "tidb", use an absolute path when you start gitea as service
|
||||
PATH = data/gitea.db
|
||||
; For "sqlite3" only. Query timeout
|
||||
SQLITE_TIMEOUT = 500
|
||||
; For iterate buffer, default is 50
|
||||
ITERATE_BUFFER_SIZE = 50
|
||||
; Show the database generated SQL
|
||||
LOG_SQL = true
|
||||
; Maximum number of DB Connect retries
|
||||
DB_RETRIES = 10
|
||||
; Backoff time per DB retry (time.Duration)
|
||||
DB_RETRY_BACKOFF = 3s
|
||||
; Max idle database connections on connnection pool, default is 2
|
||||
MAX_IDLE_CONNS = 2
|
||||
; Database connection max life time, default is 0 or 3s mysql (See #6804 & #7071 for reasoning)
|
||||
CONN_MAX_LIFETIME = 3s
|
||||
; Database maximum number of open connections, default is 0 meaning no maximum
|
||||
MAX_OPEN_CONNS = 0
|
||||
|
||||
[indexer]
|
||||
; Issue indexer type, currently support: bleve or db, default is bleve
|
||||
ISSUE_INDEXER_TYPE = bleve
|
||||
; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
||||
ISSUE_INDEXER_PATH = indexers/issues.bleve
|
||||
; Issue indexer queue, currently support: channel, levelqueue or redis, default is levelqueue
|
||||
ISSUE_INDEXER_QUEUE_TYPE = levelqueue
|
||||
; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the queue will be saved path,
|
||||
; default is indexers/issues.queue
|
||||
ISSUE_INDEXER_QUEUE_DIR = indexers/issues.queue
|
||||
; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
||||
ISSUE_INDEXER_QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"
|
||||
; Batch queue number, default is 20
|
||||
ISSUE_INDEXER_QUEUE_BATCH_NUMBER = 20
|
||||
; Timeout the indexer if it takes longer than this to start.
|
||||
; Set to zero to disable timeout.
|
||||
STARTUP_TIMEOUT=30s
|
||||
|
||||
; repo indexer by default disabled, since it uses a lot of disk space
|
||||
REPO_INDEXER_ENABLED = false
|
||||
REPO_INDEXER_PATH = indexers/repos.bleve
|
||||
UPDATE_BUFFER_LEN = 20
|
||||
MAX_FILE_SIZE = 1048576
|
||||
; A comma separated list of glob patterns (see https://github.com/gobwas/glob) to include
|
||||
; in the index; default is empty
|
||||
REPO_INDEXER_INCLUDE =
|
||||
; A comma separated list of glob patterns to exclude from the index; ; default is empty
|
||||
REPO_INDEXER_EXCLUDE =
|
||||
|
||||
[queue]
|
||||
; Specific queues can be individually configured with [queue.name]. [queue] provides defaults
|
||||
;
|
||||
; General queue queue type, currently support: persistable-channel, channel, level, redis, dummy
|
||||
; default to persistable-channel
|
||||
TYPE = persistable-channel
|
||||
; data-dir for storing persistable queues and level queues, individual queues will be named by their type
|
||||
DATADIR = queues/
|
||||
; Default queue length before a channel queue will block
|
||||
LENGTH = 20
|
||||
; Batch size to send for batched queues
|
||||
BATCH_LENGTH = 20
|
||||
; Connection string for redis queues this will store the redis connection string.
|
||||
CONN_STR = "addrs=127.0.0.1:6379 db=0"
|
||||
; Provide the suffix of the default redis queue name - specific queues can be overriden within in their [queue.name] sections.
|
||||
QUEUE_NAME = "_queue"
|
||||
; If the queue cannot be created at startup - level queues may need a timeout at startup - wrap the queue:
|
||||
WRAP_IF_NECESSARY = true
|
||||
; Attempt to create the wrapped queue at max
|
||||
MAX_ATTEMPTS = 10
|
||||
; Timeout queue creation
|
||||
TIMEOUT = 15m30s
|
||||
; Create a pool with this many workers
|
||||
WORKERS = 1
|
||||
; Dynamically scale the worker pool to at this many workers
|
||||
MAX_WORKERS = 10
|
||||
; Add boost workers when the queue blocks for BLOCK_TIMEOUT
|
||||
BLOCK_TIMEOUT = 1s
|
||||
; Remove the boost workers after BOOST_TIMEOUT
|
||||
BOOST_TIMEOUT = 5m
|
||||
; During a boost add BOOST_WORKERS
|
||||
BOOST_WORKERS = 5
|
||||
|
||||
[admin]
|
||||
; Disallow regular (non-admin) users from creating organizations.
|
||||
DISABLE_REGULAR_ORG_CREATION = false
|
||||
; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||
DEFAULT_EMAIL_NOTIFICATIONS = enabled
|
||||
|
||||
[security]
|
||||
; Whether the installer is disabled
|
||||
INSTALL_LOCK = false
|
||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
|
||||
SECRET_KEY = !#@FDEWREWR&*(
|
||||
; How long to remember that a user is logged in before requiring relogin (in days)
|
||||
LOGIN_REMEMBER_DAYS = 7
|
||||
COOKIE_USERNAME = gitea_awesome
|
||||
COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
; Reverse proxy authentication header name of user name
|
||||
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
||||
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
|
||||
; The minimum password length for new Users
|
||||
MIN_PASSWORD_LENGTH = 6
|
||||
; Set to true to allow users to import local server paths
|
||||
IMPORT_LOCAL_PATHS = false
|
||||
; Set to true to prevent all users (including admin) from creating custom git hooks
|
||||
DISABLE_GIT_HOOKS = false
|
||||
; Set to false to allow pushes to gitea repositories despite having an incomplete environment - NOT RECOMMENDED
|
||||
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = true
|
||||
;Comma separated list of character classes required to pass minimum complexity.
|
||||
;If left empty or no valid values are specified, the default values ("lower,upper,digit,spec") will be used.
|
||||
;Use "off" to disable checking.
|
||||
PASSWORD_COMPLEXITY = lower,upper,digit,spec
|
||||
; Password Hash algorithm, either "pbkdf2", "argon2", "scrypt" or "bcrypt"
|
||||
PASSWORD_HASH_ALGO = pbkdf2
|
||||
; Set false to allow JavaScript to read CSRF cookie
|
||||
CSRF_COOKIE_HTTP_ONLY = true
|
||||
|
||||
[openid]
|
||||
;
|
||||
; OpenID is an open, standard and decentralized authentication protocol.
|
||||
; Your identity is the address of a webpage you provide, which describes
|
||||
; how to prove you are in control of that page.
|
||||
;
|
||||
; For more info: https://en.wikipedia.org/wiki/OpenID
|
||||
;
|
||||
; Current implementation supports OpenID-2.0
|
||||
;
|
||||
; Tested to work providers at the time of writing:
|
||||
; - Any GNUSocial node (your.hostname.tld/username)
|
||||
; - Any SimpleID provider (http://simpleid.koinic.net)
|
||||
; - http://openid.org.cn/
|
||||
; - openid.stackexchange.com
|
||||
; - login.launchpad.net
|
||||
; - <username>.livejournal.com
|
||||
;
|
||||
; Whether to allow signin in via OpenID
|
||||
ENABLE_OPENID_SIGNIN = true
|
||||
; Whether to allow registering via OpenID
|
||||
; Do not include to rely on rhw DISABLE_REGISTRATION setting
|
||||
;ENABLE_OPENID_SIGNUP = true
|
||||
; Allowed URI patterns (POSIX regexp).
|
||||
; Space separated.
|
||||
; Only these would be allowed if non-blank.
|
||||
; Example value: trusted.domain.org trusted.domain.net
|
||||
WHITELISTED_URIS =
|
||||
; Forbidden URI patterns (POSIX regexp).
|
||||
; Space separated.
|
||||
; Only used if WHITELISTED_URIS is blank.
|
||||
; Example value: loadaverage.org/badguy stackexchange.com/.*spammer
|
||||
BLACKLISTED_URIS =
|
||||
|
||||
[service]
|
||||
; Time limit to confirm account/email registration
|
||||
ACTIVE_CODE_LIVE_MINUTES = 180
|
||||
; Time limit to perform the reset of a forgotten password
|
||||
RESET_PASSWD_CODE_LIVE_MINUTES = 180
|
||||
; Whether a new user needs to confirm their email when registering.
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
; List of domain names that are allowed to be used to register on a Gitea instance
|
||||
; gitea.io,example.com
|
||||
EMAIL_DOMAIN_WHITELIST=
|
||||
; Disallow registration, only allow admins to create accounts.
|
||||
DISABLE_REGISTRATION = false
|
||||
; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
|
||||
; User must sign in to view anything.
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
; Mail notification
|
||||
ENABLE_NOTIFY_MAIL = false
|
||||
; This setting enables gitea to be signed in with HTTP BASIC Authentication using the user's password
|
||||
; If you set this to false you will not be able to access the tokens endpoints on the API with your password
|
||||
; Please note that setting this to false will not disable OAuth Basic or Basic authentication using a token
|
||||
ENABLE_BASIC_AUTHENTICATION = true
|
||||
; More detail: https://github.com/gogits/gogs/issues/165
|
||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
|
||||
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
|
||||
ENABLE_REVERSE_PROXY_EMAIL = false
|
||||
; Enable captcha validation for registration
|
||||
ENABLE_CAPTCHA = false
|
||||
; Type of captcha you want to use. Options: image, recaptcha
|
||||
CAPTCHA_TYPE = image
|
||||
; Enable recaptcha to use Google's recaptcha service
|
||||
; Go to https://www.google.com/recaptcha/admin to sign up for a key
|
||||
RECAPTCHA_SECRET =
|
||||
RECAPTCHA_SITEKEY =
|
||||
; Change this to use recaptcha.net or other recaptcha service
|
||||
RECAPTCHA_URL = https://www.google.com/recaptcha/
|
||||
; Default value for KeepEmailPrivate
|
||||
; Each new user will get the value of this setting copied into their profile
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
; Default value for AllowCreateOrganization
|
||||
; Every new user will have rights set to create organizations depending on this setting
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
; Either "public", "limited" or "private", default is "public"
|
||||
; Limited is for signed user only
|
||||
; Private is only for member of the organization
|
||||
; Public is for everyone
|
||||
DEFAULT_ORG_VISIBILITY = public
|
||||
; Default value for DefaultOrgMemberVisible
|
||||
; True will make the membership of the users visible when added to the organisation
|
||||
DEFAULT_ORG_MEMBER_VISIBLE = false
|
||||
; Default value for EnableDependencies
|
||||
; Repositories will use dependencies by default depending on this setting
|
||||
DEFAULT_ENABLE_DEPENDENCIES = true
|
||||
; Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting.
|
||||
ALLOW_CROSS_REPOSITORY_DEPENDENCIES = true
|
||||
; Enable heatmap on users profiles.
|
||||
ENABLE_USER_HEATMAP = true
|
||||
; Enable Timetracking
|
||||
ENABLE_TIMETRACKING = true
|
||||
; Default value for EnableTimetracking
|
||||
; Repositories will use timetracking by default depending on this setting
|
||||
DEFAULT_ENABLE_TIMETRACKING = true
|
||||
; Default value for AllowOnlyContributorsToTrackTime
|
||||
; Only users with write permissions can track time if this is true
|
||||
DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = true
|
||||
; Default value for the domain part of the user's email address in the git log
|
||||
; if he has set KeepEmailPrivate to true. The user's email will be replaced with a
|
||||
; concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
|
||||
NO_REPLY_ADDRESS = noreply.%(DOMAIN)s
|
||||
; Show Registration button
|
||||
SHOW_REGISTRATION_BUTTON = true
|
||||
; Show milestones dashboard page - a view of all the user's milestones
|
||||
SHOW_MILESTONES_DASHBOARD_PAGE = true
|
||||
; Default value for AutoWatchNewRepos
|
||||
; When adding a repo to a team or creating a new repo all team members will watch the
|
||||
; repo automatically if enabled
|
||||
AUTO_WATCH_NEW_REPOS = true
|
||||
; Default value for AutoWatchOnChanges
|
||||
; Make the user watch a repository When they commit for the first time
|
||||
AUTO_WATCH_ON_CHANGES = false
|
||||
|
||||
[webhook]
|
||||
; Hook task queue length, increase if webhook shooting starts hanging
|
||||
QUEUE_LENGTH = 1000
|
||||
; Deliver timeout in seconds
|
||||
DELIVER_TIMEOUT = 5
|
||||
; Allow insecure certification
|
||||
SKIP_TLS_VERIFY = false
|
||||
; Number of history information in each page
|
||||
PAGING_NUM = 10
|
||||
; Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
|
||||
PROXY_URL =
|
||||
; Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
|
||||
PROXY_HOSTS =
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
; Buffer length of channel, keep it as it is if you don't know what it is.
|
||||
SEND_BUFFER_LEN = 100
|
||||
; Prefix displayed before subject in mail
|
||||
SUBJECT_PREFIX =
|
||||
; Mail server
|
||||
; Gmail: smtp.gmail.com:587
|
||||
; QQ: smtp.qq.com:465
|
||||
; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
|
||||
HOST =
|
||||
; Disable HELO operation when hostnames are different.
|
||||
DISABLE_HELO =
|
||||
; Custom hostname for HELO operation, if no value is provided, one is retrieved from system.
|
||||
HELO_HOSTNAME =
|
||||
; Do not verify the certificate of the server. Only use this for self-signed certificates
|
||||
SKIP_VERIFY =
|
||||
; Use client certificate
|
||||
USE_CERTIFICATE = false
|
||||
CERT_FILE = custom/mailer/cert.pem
|
||||
KEY_FILE = custom/mailer/key.pem
|
||||
; Should SMTP connection use TLS
|
||||
IS_TLS_ENABLED = false
|
||||
; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
|
||||
FROM =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
PASSWD =
|
||||
; Send mails as plain text
|
||||
SEND_AS_PLAIN_TEXT = false
|
||||
; Set Mailer Type (either SMTP, sendmail or dummy to just send to the log)
|
||||
MAILER_TYPE = smtp
|
||||
; Specify an alternative sendmail binary
|
||||
SENDMAIL_PATH = sendmail
|
||||
; Specify any extra sendmail arguments
|
||||
SENDMAIL_ARGS =
|
||||
|
||||
[cache]
|
||||
; Either "memory", "redis", or "memcache", default is "memory"
|
||||
ADAPTER = memory
|
||||
; For "memory" only, GC interval in seconds, default is 60
|
||||
INTERVAL = 60
|
||||
; For "redis" and "memcache", connection host address
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; memcache: `127.0.0.1:11211`
|
||||
HOST =
|
||||
; Time to keep items in cache if not used, default is 16 hours.
|
||||
; Setting it to 0 disables caching
|
||||
ITEM_TTL = 16h
|
||||
|
||||
[session]
|
||||
; Either "memory", "file", or "redis", default is "memory"
|
||||
PROVIDER = memory
|
||||
; Provider config options
|
||||
; memory: doesn't have any config yet
|
||||
; file: session file path, e.g. `data/sessions`
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
PROVIDER_CONFIG = data/sessions
|
||||
; Session cookie name
|
||||
COOKIE_NAME = i_like_gitea
|
||||
; If you use session in https only, default is false
|
||||
COOKIE_SECURE = false
|
||||
; Enable set cookie, default is true
|
||||
ENABLE_SET_COOKIE = true
|
||||
; Session GC time interval in seconds, default is 86400 (1 day)
|
||||
GC_INTERVAL_TIME = 86400
|
||||
; Session life time in seconds, default is 86400 (1 day)
|
||||
SESSION_LIFE_TIME = 86400
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = data/avatars
|
||||
REPOSITORY_AVATAR_UPLOAD_PATH = data/repo-avatars
|
||||
; How Gitea deals with missing repository avatars
|
||||
; none = no avatar will be displayed; random = random avatar will be displayed; image = default image will be used
|
||||
REPOSITORY_AVATAR_FALLBACK = none
|
||||
REPOSITORY_AVATAR_FALLBACK_IMAGE = /img/repo_default.png
|
||||
; Max Width and Height of uploaded avatars.
|
||||
; This is to limit the amount of RAM used when resizing the image.
|
||||
AVATAR_MAX_WIDTH = 4096
|
||||
AVATAR_MAX_HEIGHT = 3072
|
||||
; Maximum alloved file size for uploaded avatars.
|
||||
; This is to limit the amount of RAM used when resizing the image.
|
||||
AVATAR_MAX_FILE_SIZE = 1048576
|
||||
; Chinese users can choose "duoshuo"
|
||||
; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
GRAVATAR_SOURCE = gravatar
|
||||
; This value will always be true in offline mode.
|
||||
DISABLE_GRAVATAR = false
|
||||
; Federated avatar lookup uses DNS to discover avatar associated
|
||||
; with emails, see https://www.libravatar.org
|
||||
; This value will always be false in offline mode or when Gravatar is disabled.
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[attachment]
|
||||
; Whether attachments are enabled. Defaults to `true`
|
||||
ENABLED = true
|
||||
; Path for attachments. Defaults to `data/attachments`
|
||||
PATH = data/attachments
|
||||
; One or more allowed types, e.g. image/jpeg|image/png
|
||||
ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip
|
||||
; Max size of each file. Defaults to 4MB
|
||||
MAX_SIZE = 4
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[time]
|
||||
; Specifies the format for fully outputted dates. Defaults to RFC1123
|
||||
; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
|
||||
; For more information about the format see http://golang.org/pkg/time/#pkg-constants
|
||||
FORMAT =
|
||||
; Location the UI time display i.e. Asia/Shanghai
|
||||
; Empty means server's location setting
|
||||
DEFAULT_UI_LOCATION =
|
||||
|
||||
[log]
|
||||
ROOT_PATH =
|
||||
; Either "console", "file", "conn", "smtp" or "database", default is "console"
|
||||
; Use comma to separate multiple modes, e.g. "console, file"
|
||||
MODE = console
|
||||
; Buffer length of the channel, keep it as it is if you don't know what it is.
|
||||
BUFFER_LEN = 10000
|
||||
REDIRECT_MACARON_LOG = false
|
||||
MACARON = file
|
||||
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
|
||||
ROUTER_LOG_LEVEL = Info
|
||||
ROUTER = console
|
||||
ENABLE_ACCESS_LOG = false
|
||||
ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"
|
||||
ACCESS = file
|
||||
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
|
||||
LEVEL = Info
|
||||
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "None"
|
||||
STACKTRACE_LEVEL = None
|
||||
|
||||
; Generic log modes
|
||||
[log.x]
|
||||
FLAGS = stdflags
|
||||
EXPRESSION =
|
||||
PREFIX =
|
||||
COLORIZE = false
|
||||
|
||||
; For "console" mode only
|
||||
[log.console]
|
||||
LEVEL =
|
||||
STDERR = false
|
||||
|
||||
; For "file" mode only
|
||||
[log.file]
|
||||
LEVEL =
|
||||
; Set the file_name for the logger. If this is a relative path this
|
||||
; will be relative to ROOT_PATH
|
||||
FILE_NAME =
|
||||
; This enables automated log rotate(switch of following options), default is true
|
||||
LOG_ROTATE = true
|
||||
; Max number of lines in a single file, default is 1000000
|
||||
MAX_LINES = 1000000
|
||||
; Max size shift of a single file, default is 28 means 1 << 28, 256MB
|
||||
MAX_SIZE_SHIFT = 28
|
||||
; Segment log daily, default is true
|
||||
DAILY_ROTATE = true
|
||||
; delete the log file after n days, default is 7
|
||||
MAX_DAYS = 7
|
||||
; compress logs with gzip
|
||||
COMPRESS = true
|
||||
; compression level see godoc for compress/gzip
|
||||
COMPRESSION_LEVEL = -1
|
||||
|
||||
; For "conn" mode only
|
||||
[log.conn]
|
||||
LEVEL =
|
||||
; Reconnect host for every single message, default is false
|
||||
RECONNECT_ON_MSG = false
|
||||
; Try to reconnect when connection is lost, default is false
|
||||
RECONNECT = false
|
||||
; Either "tcp", "unix" or "udp", default is "tcp"
|
||||
PROTOCOL = tcp
|
||||
; Host address
|
||||
ADDR =
|
||||
|
||||
; For "smtp" mode only
|
||||
[log.smtp]
|
||||
LEVEL =
|
||||
; Name displayed in mail title, default is "Diagnostic message from server"
|
||||
SUBJECT = Diagnostic message from server
|
||||
; Mail server
|
||||
HOST =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
PASSWD =
|
||||
; Receivers, can be one or more, e.g. 1@example.com,2@example.com
|
||||
RECEIVERS =
|
||||
|
||||
[cron]
|
||||
; Enable running cron tasks periodically.
|
||||
ENABLED = true
|
||||
; Run cron tasks when Gitea starts.
|
||||
RUN_AT_START = false
|
||||
|
||||
; Update mirrors
|
||||
[cron.update_mirrors]
|
||||
SCHEDULE = @every 10m
|
||||
|
||||
; Repository health check
|
||||
[cron.repo_health_check]
|
||||
SCHEDULE = @every 24h
|
||||
TIMEOUT = 60s
|
||||
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
|
||||
; see more on http://git-scm.com/docs/git-fsck
|
||||
ARGS =
|
||||
|
||||
; Check repository statistics
|
||||
[cron.check_repo_stats]
|
||||
RUN_AT_START = true
|
||||
SCHEDULE = @every 24h
|
||||
|
||||
; Clean up old repository archives
|
||||
[cron.archive_cleanup]
|
||||
; Whether to enable the job
|
||||
ENABLED = true
|
||||
; Whether to always run at least once at start up time (if ENABLED)
|
||||
RUN_AT_START = true
|
||||
; Time interval for job to run
|
||||
SCHEDULE = @every 24h
|
||||
; Archives created more than OLDER_THAN ago are subject to deletion
|
||||
OLDER_THAN = 24h
|
||||
|
||||
; Synchronize external user data (only LDAP user synchronization is supported)
|
||||
[cron.sync_external_users]
|
||||
; Synchronize external user data when starting server (default false)
|
||||
RUN_AT_START = false
|
||||
; Interval as a duration between each synchronization (default every 24h)
|
||||
SCHEDULE = @every 24h
|
||||
; Create new users, update existing user data and disable users that are not in external source anymore (default)
|
||||
; or only create new users if UPDATE_EXISTING is set to false
|
||||
UPDATE_EXISTING = true
|
||||
|
||||
; Update migrated repositories' issues and comments' posterid, it will always attempt synchronization when the instance starts.
|
||||
[cron.update_migration_post_id]
|
||||
; Interval as a duration between each synchronization. (default every 24h)
|
||||
SCHEDULE = @every 24h
|
||||
|
||||
[git]
|
||||
; The path of git executable. If empty, Gitea searches through the PATH environment.
|
||||
PATH =
|
||||
; Disables highlight of added and removed changes
|
||||
DISABLE_DIFF_HIGHLIGHT = false
|
||||
; Max number of lines allowed in a single file in diff view
|
||||
MAX_GIT_DIFF_LINES = 1000
|
||||
; Max number of allowed characters in a line in diff view
|
||||
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
|
||||
; Max number of files shown in diff view
|
||||
MAX_GIT_DIFF_FILES = 100
|
||||
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
||||
; see more on http://git-scm.com/docs/git-gc/
|
||||
GC_ARGS =
|
||||
; 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
|
||||
EnableAutoGitWireProtocol = true
|
||||
|
||||
; Operation timeout in seconds
|
||||
[git.timeout]
|
||||
DEFAULT = 360
|
||||
MIGRATE = 600
|
||||
MIRROR = 300
|
||||
CLONE = 300
|
||||
PULL = 300
|
||||
GC = 60
|
||||
|
||||
[mirror]
|
||||
; Default interval as a duration between each check
|
||||
DEFAULT_INTERVAL = 8h
|
||||
; Min interval as a duration must be > 1m
|
||||
MIN_INTERVAL = 10m
|
||||
|
||||
[api]
|
||||
; Enables Swagger. True or false; default is true.
|
||||
ENABLE_SWAGGER = true
|
||||
; Max number of items in a page
|
||||
MAX_RESPONSE_ITEMS = 50
|
||||
; Default paging number of api
|
||||
DEFAULT_PAGING_NUM = 30
|
||||
; Default and maximum number of items per page for git trees api
|
||||
DEFAULT_GIT_TREES_PER_PAGE = 1000
|
||||
; Default size of a blob returned by the blobs API (default is 10MiB)
|
||||
DEFAULT_MAX_BLOB_SIZE = 10485760
|
||||
|
||||
[oauth2]
|
||||
; Enables OAuth2 provider
|
||||
ENABLE = true
|
||||
; Lifetime of an OAuth2 access token in seconds
|
||||
ACCESS_TOKEN_EXPIRATION_TIME=3600
|
||||
; Lifetime of an OAuth2 access token in hours
|
||||
REFRESH_TOKEN_EXPIRATION_TIME=730
|
||||
; Check if refresh token got already used
|
||||
INVALIDATE_REFRESH_TOKENS=false
|
||||
; OAuth2 authentication secret for access and refresh tokens, change this to a unique string.
|
||||
JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
|
||||
|
||||
[i18n]
|
||||
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
|
||||
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어
|
||||
|
||||
; Used for datetimepicker
|
||||
[i18n.datelang]
|
||||
en-US = en
|
||||
zh-CN = zh
|
||||
zh-HK = zh-HK
|
||||
zh-TW = zh-TW
|
||||
de-DE = de
|
||||
fr-FR = fr
|
||||
nl-NL = nl
|
||||
lv-LV = lv
|
||||
ru-RU = ru
|
||||
uk-UA = uk
|
||||
ja-JP = ja
|
||||
es-ES = es
|
||||
pt-BR = pt-BR
|
||||
pl-PL = pl
|
||||
bg-BG = bg
|
||||
it-IT = it
|
||||
fi-FI = fi
|
||||
tr-TR = tr
|
||||
cs-CZ = cs-CZ
|
||||
sr-SP = sr
|
||||
sv-SE = sv
|
||||
ko-KR = ko
|
||||
|
||||
[U2F]
|
||||
; NOTE: THE DEFAULT VALUES HERE WILL NEED TO BE CHANGED
|
||||
; Two Factor authentication with security keys
|
||||
; https://developers.yubico.com/U2F/App_ID.html
|
||||
;APP_ID = http://localhost:3000/
|
||||
; Comma seperated list of trusted facets
|
||||
;TRUSTED_FACETS = http://localhost:3000/
|
||||
|
||||
; Extension mapping to highlight class
|
||||
; e.g. .toml=ini
|
||||
[highlight.mapping]
|
||||
|
||||
[other]
|
||||
SHOW_FOOTER_BRANDING = false
|
||||
; Show version information about Gitea and Go in the footer
|
||||
SHOW_FOOTER_VERSION = true
|
||||
; Show template execution time in the footer
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
||||
|
||||
[markup.sanitizer]
|
||||
; The following keys can be used multiple times to define sanitation policy rules.
|
||||
;ELEMENT = span
|
||||
;ALLOW_ATTR = class
|
||||
;REGEXP = ^(info|warning|error)$
|
||||
|
||||
[markup.asciidoc]
|
||||
ENABLED = false
|
||||
; List of file extensions that should be rendered by an external command
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
; External command to render all matching extensions
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
; Don't pass the file on STDIN, pass the filename as argument instead.
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
[metrics]
|
||||
; Enables metrics endpoint. True or false; default is false.
|
||||
ENABLED = false
|
||||
; If you want to add authorization, specify a token here
|
||||
TOKEN =
|
||||
|
||||
[task]
|
||||
; Task queue type, could be `channel` or `redis`.
|
||||
QUEUE_TYPE = channel
|
||||
; Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
QUEUE_LENGTH = 1000
|
||||
; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
||||
; If there is a password of redis, use `addrs=127.0.0.1:6379 password=123 db=0`.
|
||||
QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"
|
||||
|
||||
[migrations]
|
||||
; Max attempts per http/https request on migrations.
|
||||
MAX_ATTEMPTS = 3
|
||||
; Backoff time per http/https request retry (seconds)
|
||||
RETRY_BACKOFF = 3
|
14
docker/Makefile
vendored
14
docker/Makefile
vendored
@@ -1,14 +0,0 @@
|
||||
#Makefile related to docker
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||
|
||||
.PHONY: docker-build
|
||||
docker-build:
|
||||
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" webhippie/golang:edge make clean build
|
2
docker/etc/profile.d/gitea.sh
Executable file
2
docker/etc/profile.d/gitea.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
export GITEA_CUSTOM=/data/gitea
|
6
docker/etc/s6/gitea/run
Executable file
6
docker/etc/s6/gitea/run
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /app/gitea > /dev/null
|
||||
exec su-exec git /app/gitea/gitea web
|
||||
popd
|
19
docker/etc/s6/gitea/setup
Executable file
19
docker/etc/s6/gitea/setup
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d /data/git/.ssh ]; then
|
||||
mkdir -p /data/git/.ssh
|
||||
chmod 700 /data/git/.ssh
|
||||
fi
|
||||
|
||||
if [ ! -f /data/git/.ssh/environment ]; then
|
||||
echo "GITEA_CUSTOM=/data/gitea" >| /data/git/.ssh/environment
|
||||
chmod 600 /data/git/.ssh/environment
|
||||
fi
|
||||
|
||||
if [ ! -f /data/gitea/conf/app.ini ]; then
|
||||
mkdir -p /data/gitea/conf
|
||||
cp /etc/templates/app.ini /data/gitea/conf/app.ini
|
||||
fi
|
||||
|
||||
chown -R git:git /data/gitea /app/gitea /data/git
|
||||
chmod 0755 /data/gitea /app/gitea /data/git
|
2
docker/etc/s6/openssh/finish
Executable file
2
docker/etc/s6/openssh/finish
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
6
docker/etc/s6/openssh/run
Executable file
6
docker/etc/s6/openssh/run
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /root > /dev/null
|
||||
exec su-exec root /usr/sbin/sshd -D
|
||||
popd
|
29
docker/etc/s6/openssh/setup
Executable file
29
docker/etc/s6/openssh/setup
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d /data/ssh ]; then
|
||||
mkdir -p /data/ssh
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_ed25519_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_ed25519_key..."
|
||||
ssh-keygen -t ed25519 -b 4096 -f /data/ssh/ssh_host_ed25519_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_rsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_rsa_key..."
|
||||
ssh-keygen -t rsa -b 2048 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_dsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_dsa_key..."
|
||||
ssh-keygen -t dsa -f /data/ssh/ssh_host_dsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_ecdsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_ecdsa_key..."
|
||||
ssh-keygen -t ecdsa -b 256 -f /data/ssh/ssh_host_ecdsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
chown root:root /data/ssh/*
|
||||
chmod 0700 /data/ssh
|
||||
chmod 0600 /data/ssh/*
|
2
docker/etc/s6/syslogd/finish
Executable file
2
docker/etc/s6/syslogd/finish
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
6
docker/etc/s6/syslogd/run
Executable file
6
docker/etc/s6/syslogd/run
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /root > /dev/null
|
||||
exec su-exec root /sbin/syslogd -nS -O-
|
||||
popd
|
1
docker/etc/s6/syslogd/setup
Executable file
1
docker/etc/s6/syslogd/setup
Executable file
@@ -0,0 +1 @@
|
||||
#!/bin/bash
|
@@ -1,4 +1,4 @@
|
||||
Port ${SSH_LISTEN_PORT}
|
||||
Port 22
|
||||
Protocol 2
|
||||
|
||||
AddressFamily any
|
||||
@@ -25,9 +25,8 @@ ChallengeResponseAuthentication no
|
||||
PasswordAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
|
||||
AllowUsers ${USER}
|
||||
AllowUsers git
|
||||
|
||||
Banner none
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
|
||||
AcceptEnv GIT_PROTOCOL
|
||||
UsePrivilegeSeparation no
|
24
docker/etc/templates/app.ini
Normal file
24
docker/etc/templates/app.ini
Normal file
@@ -0,0 +1,24 @@
|
||||
[repository]
|
||||
ROOT = /data/git/repositories
|
||||
|
||||
[repository.upload]
|
||||
TEMP_PATH = /data/gitea/uploads
|
||||
|
||||
[server]
|
||||
APP_DATA_PATH = /data/gitea
|
||||
|
||||
[database]
|
||||
HOST = mysql:3306
|
||||
PATH = /data/gitea/gitea.db
|
||||
|
||||
[session]
|
||||
PROVIDER_CONFIG = /data/gitea/sessions
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /data/gitea/avatars
|
||||
|
||||
[attachment]
|
||||
PATH = /data/gitea/attachments
|
||||
|
||||
[log]
|
||||
ROOT_PATH = /data/gitea/log
|
19
docker/manifest.tmpl
vendored
19
docker/manifest.tmpl
vendored
@@ -1,19 +0,0 @@
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
s6-svscanctl -t /etc/s6/
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /app/gitea > /dev/null
|
||||
exec su-exec $USER /app/gitea/gitea web
|
||||
popd
|
@@ -1,54 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d /data/git/.ssh ]; then
|
||||
mkdir -p /data/git/.ssh
|
||||
chmod 700 /data/git/.ssh
|
||||
fi
|
||||
|
||||
if [ ! -f /data/git/.ssh/environment ]; then
|
||||
echo "GITEA_CUSTOM=$GITEA_CUSTOM" >| /data/git/.ssh/environment
|
||||
chmod 600 /data/git/.ssh/environment
|
||||
|
||||
elif ! grep -q "^GITEA_CUSTOM=$GITEA_CUSTOM$" /data/git/.ssh/environment; then
|
||||
sed -i /^GITEA_CUSTOM=/d /data/git/.ssh/environment
|
||||
echo "GITEA_CUSTOM=$GITEA_CUSTOM" >> /data/git/.ssh/environment
|
||||
fi
|
||||
|
||||
if [ ! -f ${GITEA_CUSTOM}/conf/app.ini ]; then
|
||||
mkdir -p ${GITEA_CUSTOM}/conf
|
||||
|
||||
# Set INSTALL_LOCK to true only if SECRET_KEY is not empty and
|
||||
# INSTALL_LOCK is empty
|
||||
if [ -n "$SECRET_KEY" ] && [ -z "$INSTALL_LOCK" ]; then
|
||||
INSTALL_LOCK=true
|
||||
fi
|
||||
|
||||
# Substitude the environment variables in the template
|
||||
APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
|
||||
RUN_MODE=${RUN_MODE:-"dev"} \
|
||||
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
|
||||
HTTP_PORT=${HTTP_PORT:-"3000"} \
|
||||
ROOT_URL=${ROOT_URL:-""} \
|
||||
DISABLE_SSH=${DISABLE_SSH:-"false"} \
|
||||
SSH_PORT=${SSH_PORT:-"22"} \
|
||||
SSH_LISTEN_PORT=${SSH_LISTEN_PORT:-"${SSH_PORT}"} \
|
||||
LFS_START_SERVER=${LFS_START_SERVER:-"false"} \
|
||||
DB_TYPE=${DB_TYPE:-"sqlite3"} \
|
||||
DB_HOST=${DB_HOST:-"localhost:3306"} \
|
||||
DB_NAME=${DB_NAME:-"gitea"} \
|
||||
DB_USER=${DB_USER:-"root"} \
|
||||
DB_PASSWD=${DB_PASSWD:-""} \
|
||||
INSTALL_LOCK=${INSTALL_LOCK:-"false"} \
|
||||
DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-"false"} \
|
||||
REQUIRE_SIGNIN_VIEW=${REQUIRE_SIGNIN_VIEW:-"false"} \
|
||||
SECRET_KEY=${SECRET_KEY:-""} \
|
||||
envsubst < /etc/templates/app.ini > ${GITEA_CUSTOM}/conf/app.ini
|
||||
|
||||
chown ${USER}:git ${GITEA_CUSTOM}/conf/app.ini
|
||||
fi
|
||||
|
||||
# only chown if current owner is not already the gitea ${USER}. No recursive check to save time
|
||||
if ! [[ $(ls -ld /data/gitea | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /data/gitea; fi
|
||||
if ! [[ $(ls -ld /app/gitea | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /app/gitea; fi
|
||||
if ! [[ $(ls -ld /data/git | awk '{print $3}') = ${USER} ]]; then chown -R ${USER}:git /data/git; fi
|
||||
chmod 0755 /data/gitea /app/gitea /data/git
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
[[ -f ./setup ]] && source ./setup
|
||||
|
||||
pushd /root > /dev/null
|
||||
exec su-exec root /usr/sbin/sshd -D -e 2>&1
|
||||
popd
|
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d /data/ssh ]; then
|
||||
mkdir -p /data/ssh
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_ed25519_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_ed25519_key..."
|
||||
ssh-keygen -t ed25519 -f /data/ssh/ssh_host_ed25519_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_rsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_rsa_key..."
|
||||
ssh-keygen -t rsa -b 2048 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_dsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_dsa_key..."
|
||||
ssh-keygen -t dsa -f /data/ssh/ssh_host_dsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /data/ssh/ssh_host_ecdsa_key ]; then
|
||||
echo "Generating /data/ssh/ssh_host_ecdsa_key..."
|
||||
ssh-keygen -t ecdsa -b 256 -f /data/ssh/ssh_host_ecdsa_key -N "" > /dev/null
|
||||
fi
|
||||
|
||||
if [ -d /etc/ssh ]; then
|
||||
SSH_PORT=${SSH_PORT:-"22"} \
|
||||
SSH_LISTEN_PORT=${SSH_LISTEN_PORT:-"${SSH_PORT}"} \
|
||||
envsubst < /etc/templates/sshd_config > /etc/ssh/sshd_config
|
||||
|
||||
chmod 0644 /etc/ssh/sshd_config
|
||||
fi
|
||||
|
||||
chown root:root /data/ssh/*
|
||||
chmod 0700 /data/ssh
|
||||
chmod 0600 /data/ssh/*
|
@@ -1,54 +0,0 @@
|
||||
APP_NAME = $APP_NAME
|
||||
RUN_MODE = $RUN_MODE
|
||||
|
||||
[repository]
|
||||
ROOT = /data/git/repositories
|
||||
|
||||
[repository.local]
|
||||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
||||
|
||||
[repository.upload]
|
||||
TEMP_PATH = /data/gitea/uploads
|
||||
|
||||
[server]
|
||||
APP_DATA_PATH = /data/gitea
|
||||
SSH_DOMAIN = $SSH_DOMAIN
|
||||
HTTP_PORT = $HTTP_PORT
|
||||
ROOT_URL = $ROOT_URL
|
||||
DISABLE_SSH = $DISABLE_SSH
|
||||
SSH_PORT = $SSH_PORT
|
||||
SSH_LISTEN_PORT = $SSH_LISTEN_PORT
|
||||
LFS_START_SERVER = $LFS_START_SERVER
|
||||
LFS_CONTENT_PATH = /data/git/lfs
|
||||
|
||||
[database]
|
||||
PATH = /data/gitea/gitea.db
|
||||
DB_TYPE = $DB_TYPE
|
||||
HOST = $DB_HOST
|
||||
NAME = $DB_NAME
|
||||
USER = $DB_USER
|
||||
PASSWD = $DB_PASSWD
|
||||
|
||||
[indexer]
|
||||
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
||||
|
||||
[session]
|
||||
PROVIDER_CONFIG = /data/gitea/sessions
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = /data/gitea/avatars
|
||||
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
|
||||
|
||||
[attachment]
|
||||
PATH = /data/gitea/attachments
|
||||
|
||||
[log]
|
||||
ROOT_PATH = /data/gitea/log
|
||||
|
||||
[security]
|
||||
INSTALL_LOCK = $INSTALL_LOCK
|
||||
SECRET_KEY = $SECRET_KEY
|
||||
|
||||
[service]
|
||||
DISABLE_REGISTRATION = $DISABLE_REGISTRATION
|
||||
REQUIRE_SIGNIN_VIEW = $REQUIRE_SIGNIN_VIEW
|
@@ -1,35 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "${USER}" != "git" ]; then
|
||||
# rename user
|
||||
sed -i -e "s/^git\:/${USER}\:/g" /etc/passwd
|
||||
fi
|
||||
|
||||
if [ -z "${USER_GID}" ]; then
|
||||
USER_GID="`id -g ${USER}`"
|
||||
fi
|
||||
|
||||
if [ -z "${USER_UID}" ]; then
|
||||
USER_UID="`id -u ${USER}`"
|
||||
fi
|
||||
|
||||
## Change GID for USER?
|
||||
if [ -n "${USER_GID}" ] && [ "${USER_GID}" != "`id -g ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*/${USER}:\1:${USER_GID}/" /etc/group
|
||||
sed -i -e "s/^${USER}:\([^:]*\):\([0-9]*\):[0-9]*/${USER}:\1:\2:${USER_GID}/" /etc/passwd
|
||||
fi
|
||||
|
||||
## Change UID for USER?
|
||||
if [ -n "${USER_UID}" ] && [ "${USER_UID}" != "`id -u ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*:\([0-9]*\)/${USER}:\1:${USER_UID}:\2/" /etc/passwd
|
||||
fi
|
||||
|
||||
for FOLDER in /data/gitea/conf /data/gitea/log /data/git /data/ssh; do
|
||||
mkdir -p ${FOLDER}
|
||||
done
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
exec "$@"
|
||||
else
|
||||
exec /bin/s6-svscan /etc/s6
|
||||
fi
|
11
docker/usr/bin/entrypoint
Executable file
11
docker/usr/bin/entrypoint
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
for FOLDER in /data/gitea/conf /data/gitea/log /data/git /data/ssh; do
|
||||
mkdir -p ${FOLDER}
|
||||
done
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
exec "$@"
|
||||
else
|
||||
exec /bin/s6-svscan /etc/s6
|
||||
fi
|
@@ -1,34 +0,0 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*.{tmpl,html}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.{less}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
4
docs/.gitignore
vendored
4
docs/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
public/
|
||||
templates/swagger/v1_json.tmpl
|
||||
themes/
|
||||
resources/
|
@@ -1,30 +0,0 @@
|
||||
THEME := themes/gitea
|
||||
PUBLIC := public
|
||||
ARCHIVE := https://dl.gitea.io/theme/master.tar.gz
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(PUBLIC) $(THEME)
|
||||
|
||||
.PHONY: trans-copy
|
||||
trans-copy:
|
||||
@bash scripts/trans-copy
|
||||
|
||||
.PHONY: server
|
||||
server: $(THEME)
|
||||
hugo server
|
||||
|
||||
.PHONY: build
|
||||
build: $(THEME)
|
||||
hugo --cleanDestinationDir
|
||||
|
||||
.PHONY: update
|
||||
update: $(THEME)
|
||||
|
||||
$(THEME): $(THEME)/theme.toml
|
||||
$(THEME)/theme.toml:
|
||||
mkdir -p $$(dirname $@)
|
||||
curl -s $(ARCHIVE) | tar xz -C $$(dirname $@)
|
@@ -1,51 +0,0 @@
|
||||
# Gitea: Docs
|
||||
|
||||
[](https://discord.gg/Gitea)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
## Hosting
|
||||
|
||||
These pages are hosted using [netlifycms](https://www.netlifycms.org/) and get
|
||||
automatically updated on every push to the `master` branch.
|
||||
|
||||
## Install
|
||||
|
||||
These pages use the [Hugo](https://gohugo.io/) static site generator.
|
||||
If you are planning to contribute you'll want to download and install Hugo on
|
||||
your local machine.
|
||||
|
||||
The installation of Hugo is out of the scope of this document, so please take
|
||||
the [official install instructions](https://gohugo.io/overview/installing/) to
|
||||
get Hugo up and running.
|
||||
|
||||
## Development
|
||||
|
||||
To generate the website and serve it on [localhost:1313](http://localhost:1313)
|
||||
just execute this command and stop it with `Ctrl+C`:
|
||||
|
||||
```
|
||||
make server
|
||||
```
|
||||
|
||||
When you are done with your changes just create a pull request, after merging
|
||||
the pull request the website will be updated automatically.
|
||||
|
||||
## Contributing
|
||||
|
||||
Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## Authors
|
||||
|
||||
* [Maintainers](https://github.com/orgs/go-gitea/people)
|
||||
* [Contributors](https://github.com/go-gitea/docs/graphs/contributors)
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache-2.0 License. See the [LICENSE](LICENSE) file
|
||||
for the full license text.
|
||||
|
||||
## Copyright
|
||||
|
||||
```
|
||||
Copyright (c) 2016 The Gitea Authors <https://gitea.io>
|
||||
```
|
@@ -1,42 +0,0 @@
|
||||
# Gitea: 文档
|
||||
|
||||
[](http://drone.gitea.io/go-gitea/docs)
|
||||
[](https://discord.gg/NsatcWJ)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
## 关于托管方式
|
||||
|
||||
本页面托管在我们 Docker 容器内的基础设施上, 它会在每次推送到 `master` 分支的时候自动更新,如果你想自己管理这个页面,你可以从我们的 Docker 镜像 [gitea/docs](https://hub.docker.com/r/gitea/docs/) 中获取它。
|
||||
|
||||
## 安装 Hugo
|
||||
|
||||
本页面使用了 [Hugo](https://github.com/spf13/hugo) 静态页面生成工具,如果您有维护它的意愿,则需要在本地计算机上下载并安装 Hugo。Hugo 的安装教程不在本文档的讲述范围之内,详情请参见 [官方文档](https://gohugo.io/overview/installing/)。
|
||||
|
||||
## 如何部署
|
||||
|
||||
在 [localhost:1313](http://localhost:1313) 处构建和运行网站的命令如下,如果需要停止可以使用组合键 `Ctrl+C`:
|
||||
|
||||
```
|
||||
make server
|
||||
```
|
||||
|
||||
完成更改后,只需创建一个 Pull Request (PR),该 PR 一经合并网站将自动更新。
|
||||
|
||||
## 如何贡献您的代码
|
||||
|
||||
Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## 关于我们
|
||||
|
||||
* [维护者信息](https://github.com/orgs/go-gitea/people)
|
||||
* [代码贡献者信息](https://github.com/go-gitea/docs/graphs/contributors)
|
||||
|
||||
## 许可证
|
||||
|
||||
此项目采用 Apache-2.0 许可协议,请参见 [协议文件](LICENSE) 获取更多信息。
|
||||
|
||||
## 版权声明
|
||||
|
||||
```
|
||||
Copyright (c) 2016 The Gitea Authors <https://gitea.io>
|
||||
```
|
@@ -1,176 +0,0 @@
|
||||
function ready(fn) {
|
||||
if (document.readyState != 'loading') {
|
||||
fn();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', fn);
|
||||
}
|
||||
}
|
||||
|
||||
ready(doSearch);
|
||||
|
||||
const summaryInclude = 60;
|
||||
const fuseOptions = {
|
||||
shouldSort: true,
|
||||
includeMatches: true,
|
||||
matchAllTokens: true,
|
||||
threshold: 0.0, // for parsing diacritics
|
||||
tokenize: true,
|
||||
location: 0,
|
||||
distance: 100,
|
||||
maxPatternLength: 32,
|
||||
minMatchCharLength: 1,
|
||||
keys: [{
|
||||
name: "title",
|
||||
weight: 0.8
|
||||
},
|
||||
{
|
||||
name: "contents",
|
||||
weight: 0.5
|
||||
},
|
||||
{
|
||||
name: "tags",
|
||||
weight: 0.3
|
||||
},
|
||||
{
|
||||
name: "categories",
|
||||
weight: 0.3
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
function param(name) {
|
||||
return decodeURIComponent((location.search.split(name + '=')[1] || '').split('&')[0]).replace(/\+/g, ' ');
|
||||
}
|
||||
|
||||
let searchQuery = param("s");
|
||||
|
||||
function doSearch() {
|
||||
if (searchQuery) {
|
||||
document.getElementById("search-query").value = searchQuery;
|
||||
executeSearch(searchQuery);
|
||||
} else {
|
||||
const para = document.createElement("P");
|
||||
para.innerText = "Please enter a word or phrase above";
|
||||
document.getElementById("search-results").appendChild(para);
|
||||
}
|
||||
}
|
||||
|
||||
function getJSON(url, fn) {
|
||||
const request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.onload = function () {
|
||||
if (request.status >= 200 && request.status < 400) {
|
||||
const data = JSON.parse(request.responseText);
|
||||
fn(data);
|
||||
} else {
|
||||
console.log("Target reached on " + url + " with error " + request.status);
|
||||
}
|
||||
};
|
||||
request.onerror = function () {
|
||||
console.log("Connection error " + request.status);
|
||||
};
|
||||
request.send();
|
||||
}
|
||||
|
||||
function executeSearch(searchQuery) {
|
||||
getJSON("/" + document.LANG + "/index.json", function (data) {
|
||||
const pages = data;
|
||||
const fuse = new Fuse(pages, fuseOptions);
|
||||
const result = fuse.search(searchQuery);
|
||||
console.log({
|
||||
"matches": result
|
||||
});
|
||||
document.getElementById("search-results").innerHTML = "";
|
||||
if (result.length > 0) {
|
||||
populateResults(result);
|
||||
} else {
|
||||
const para = document.createElement("P");
|
||||
para.innerText = "No matches found";
|
||||
document.getElementById("search-results").appendChild(para);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populateResults(result) {
|
||||
result.forEach(function (value, key) {
|
||||
const content = value.item.contents;
|
||||
let snippet = "";
|
||||
const snippetHighlights = [];
|
||||
if (fuseOptions.tokenize) {
|
||||
snippetHighlights.push(searchQuery);
|
||||
value.matches.forEach(function (mvalue) {
|
||||
if (mvalue.key === "tags" || mvalue.key === "categories") {
|
||||
snippetHighlights.push(mvalue.value);
|
||||
} else if (mvalue.key === "contents") {
|
||||
const ind = content.toLowerCase().indexOf(searchQuery.toLowerCase());
|
||||
const start = ind - summaryInclude > 0 ? ind - summaryInclude : 0;
|
||||
const end = ind + searchQuery.length + summaryInclude < content.length ? ind + searchQuery.length + summaryInclude : content.length;
|
||||
snippet += content.substring(start, end);
|
||||
if (ind > -1) {
|
||||
snippetHighlights.push(content.substring(ind, ind + searchQuery.length))
|
||||
} else {
|
||||
snippetHighlights.push(mvalue.value.substring(mvalue.indices[0][0], mvalue.indices[0][1] - mvalue.indices[0][0] + 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (snippet.length < 1) {
|
||||
snippet += content.substring(0, summaryInclude * 2);
|
||||
}
|
||||
//pull template from hugo templarte definition
|
||||
const templateDefinition = document.getElementById("search-result-template").innerHTML;
|
||||
//replace values
|
||||
const output = render(templateDefinition, {
|
||||
key: key,
|
||||
title: value.item.title,
|
||||
link: value.item.permalink,
|
||||
tags: value.item.tags,
|
||||
categories: value.item.categories,
|
||||
snippet: snippet
|
||||
});
|
||||
document.getElementById("search-results").appendChild(htmlToElement(output));
|
||||
|
||||
snippetHighlights.forEach(function (snipvalue) {
|
||||
new Mark(document.getElementById("summary-" + key)).mark(snipvalue);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function render(templateString, data) {
|
||||
let conditionalMatches, copy;
|
||||
const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
|
||||
//since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop
|
||||
copy = templateString;
|
||||
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
|
||||
if (data[conditionalMatches[1]]) {
|
||||
//valid key, remove conditionals, leave content.
|
||||
copy = copy.replace(conditionalMatches[0], conditionalMatches[2]);
|
||||
} else {
|
||||
//not valid, remove entire section
|
||||
copy = copy.replace(conditionalMatches[0], '');
|
||||
}
|
||||
}
|
||||
templateString = copy;
|
||||
//now any conditionals removed we can do simple substitution
|
||||
let key, find, re;
|
||||
for (key in data) {
|
||||
find = '\\$\\{\\s*' + key + '\\s*\\}';
|
||||
re = new RegExp(find, 'g');
|
||||
templateString = templateString.replace(re, data[key]);
|
||||
}
|
||||
return templateString;
|
||||
}
|
||||
|
||||
/**
|
||||
* By Mark Amery: https://stackoverflow.com/a/35385518
|
||||
* @param {String} HTML representing a single element
|
||||
* @return {Element}
|
||||
*/
|
||||
function htmlToElement(html) {
|
||||
const template = document.createElement('template');
|
||||
html = html.trim(); // Never return a text node of whitespace as the result
|
||||
template.innerHTML = html;
|
||||
return template.content.firstChild;
|
||||
}
|
287
docs/config.yaml
287
docs/config.yaml
@@ -1,287 +0,0 @@
|
||||
baseurl: https://docs.gitea.io/
|
||||
languageCode: en-us
|
||||
title: Docs
|
||||
theme: gitea
|
||||
|
||||
defaultContentLanguage: en-us
|
||||
defaultContentLanguageInSubdir: true
|
||||
enableMissingTranslationPlaceholders: true
|
||||
enableEmoji: true
|
||||
|
||||
permalinks:
|
||||
post: /:year/:month/:title/
|
||||
doc: /:slug/
|
||||
page: /:slug/
|
||||
default: /:slug/
|
||||
|
||||
params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.10.2
|
||||
|
||||
outputs:
|
||||
home:
|
||||
- HTML
|
||||
- RSS
|
||||
- JSON
|
||||
|
||||
menu:
|
||||
page:
|
||||
- name: Website
|
||||
url: https://gitea.io/en-us/
|
||||
weight: 10
|
||||
pre: home
|
||||
- name: Docs
|
||||
url: /en-us/
|
||||
weight: 20
|
||||
pre: question
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: Code
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: Downloads
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
||||
|
||||
languages:
|
||||
en-us:
|
||||
weight: 0
|
||||
languageName: English
|
||||
|
||||
zh-cn:
|
||||
weight: 1
|
||||
languageName: 中文(简体)
|
||||
menu:
|
||||
page:
|
||||
- name: 网站
|
||||
url: https://gitea.io/zh-cn/
|
||||
weight: 10
|
||||
pre: home
|
||||
- name: 文档
|
||||
url: /zh-cn/
|
||||
weight: 20
|
||||
pre: question
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: 博客
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: 导入
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: 下载
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
||||
|
||||
zh-tw:
|
||||
weight: 2
|
||||
languageName: 中文(繁體)
|
||||
menu:
|
||||
page:
|
||||
- name: 網站
|
||||
url: https://gitea.io/zh-tw/
|
||||
weight: 10
|
||||
pre: home
|
||||
- name: 文件
|
||||
url: /zh-tw/
|
||||
weight: 20
|
||||
pre: question
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: 部落格
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: 程式碼
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: 下载
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
||||
|
||||
pt-br:
|
||||
weight: 3
|
||||
languageName: Português Brasileiro
|
||||
menu:
|
||||
page:
|
||||
- name: Página inicial
|
||||
url: https://gitea.io/pt-br/
|
||||
weight: 10
|
||||
pre: home
|
||||
- name: Documentação
|
||||
url: /pt-br/
|
||||
weight: 20
|
||||
pre: question
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: Código-fonte
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: Downloads
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Chat no Discord
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
||||
|
||||
nl-nl:
|
||||
weight: 4
|
||||
languageName: Nederlands
|
||||
menu:
|
||||
page:
|
||||
- name: Website
|
||||
url: https://gitea.io/nl-nl/
|
||||
weight: 10
|
||||
pre: home
|
||||
- name: Docs
|
||||
url: /nl-nl/
|
||||
weight: 20
|
||||
pre: question
|
||||
post: active
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: Code
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: Downloads
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
||||
|
||||
fr-fr:
|
||||
weight: 5
|
||||
languageName: Français
|
||||
menu:
|
||||
page:
|
||||
- name: Site
|
||||
url: https://gitea.io/en-us/
|
||||
weight: 10
|
||||
pre: home
|
||||
post: active
|
||||
- name: Documentation
|
||||
url: /fr-fr/
|
||||
weight: 20
|
||||
pre: question
|
||||
- name: API
|
||||
url: https://try.gitea.io/api/swagger
|
||||
weight: 45
|
||||
pre: plug
|
||||
- name: Blog
|
||||
url: https://blog.gitea.io/
|
||||
weight: 30
|
||||
pre: rss
|
||||
- name: Code
|
||||
url: https://code.gitea.io/
|
||||
weight: 40
|
||||
pre: code
|
||||
- name: Téléchargement
|
||||
url: https://dl.gitea.io/
|
||||
weight: 50
|
||||
pre: download
|
||||
- name: GitHub
|
||||
url: https://github.com/go-gitea/
|
||||
weight: 60
|
||||
pre: github
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/NsatcWJ
|
||||
weight: 70
|
||||
pre: comment
|
||||
- name: Forum
|
||||
url: https://discourse.gitea.io/
|
||||
weight: 80
|
||||
pre: group
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2016-12-01T16:00:00+02:00"
|
||||
title: "Advanced"
|
||||
slug: "advanced"
|
||||
weight: 30
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Advanced"
|
||||
weight: 40
|
||||
identifier: "advanced"
|
||||
---
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2017-08-23T09:00:00+02:00"
|
||||
title: "Avancé"
|
||||
slug: "advanced"
|
||||
weight: 30
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Avancé"
|
||||
weight: 40
|
||||
identifier: "advanced"
|
||||
---
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2016-12-01T16:00:00+02:00"
|
||||
title: "进阶"
|
||||
slug: "advanced"
|
||||
weight: 30
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "进阶"
|
||||
weight: 40
|
||||
identifier: "advanced"
|
||||
---
|
@@ -1,101 +0,0 @@
|
||||
---
|
||||
date: "2018-06-24:00:00+02:00"
|
||||
title: "API Usage"
|
||||
slug: "api-usage"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "API Usage"
|
||||
weight: 40
|
||||
identifier: "api-usage"
|
||||
---
|
||||
|
||||
# Gitea API Usage
|
||||
|
||||
## Enabling/configuring API access
|
||||
|
||||
By default, `ENABLE_SWAGGER` is true, and
|
||||
`MAX_RESPONSE_ITEMS` is set to 50. See [Config Cheat
|
||||
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for more
|
||||
information.
|
||||
|
||||
## Authentication via the API
|
||||
|
||||
Gitea supports these methods of API authentication:
|
||||
|
||||
- HTTP basic authentication
|
||||
- `token=...` parameter in URL query string
|
||||
- `access_token=...` parameter in URL query string
|
||||
- `Authorization: token ...` header in HTTP headers
|
||||
|
||||
All of these methods accept the same API key token type. You can
|
||||
better understand this by looking at the code -- as of this writing,
|
||||
Gitea parses queries and headers to find the token in
|
||||
[modules/auth/auth.go](https://github.com/go-gitea/gitea/blob/6efdcaed86565c91a3dc77631372a9cc45a58e89/modules/auth/auth.go#L47).
|
||||
|
||||
You can create an API key token via your Gitea installation's web interface:
|
||||
`Settings | Applications | Generate New Token`.
|
||||
|
||||
### OAuth2
|
||||
|
||||
Access tokens obtained from Gitea's [OAuth2 provider](https://docs.gitea.io/en-us/oauth2-provider) are accepted by these methods:
|
||||
|
||||
- `Authorization bearer ...` header in HTTP headers
|
||||
- `token=...` parameter in URL query string
|
||||
- `access_token=...` parameter in URL query string
|
||||
|
||||
### More on the `Authorization:` header
|
||||
|
||||
For historical reasons, Gitea needs the word `token` included before
|
||||
the API key token in an authorization header, like this:
|
||||
|
||||
```
|
||||
Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675
|
||||
```
|
||||
|
||||
In a `curl` command, for instance, this would look like:
|
||||
|
||||
```
|
||||
curl -X POST "http://localhost:4000/api/v1/repos/test1/test1/issues" \
|
||||
-H "accept: application/json" \
|
||||
-H "Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675" \
|
||||
-H "Content-Type: application/json" -d "{ \"body\": \"testing\", \"title\": \"test 20\"}" -i
|
||||
```
|
||||
|
||||
As mentioned above, the token used is the same one you would use in
|
||||
the `token=` string in a GET request.
|
||||
|
||||
## API Guide:
|
||||
|
||||
API Reference guide is auto-generated by swagger and available on:
|
||||
`https://gitea.your.host/api/swagger`
|
||||
or on
|
||||
[gitea demo instance](https://try.gitea.io/api/swagger)
|
||||
|
||||
|
||||
## Listing your issued tokens via the API
|
||||
|
||||
As mentioned in
|
||||
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346),
|
||||
`/users/:name/tokens` is special and requires you to authenticate
|
||||
using BasicAuth, as follows:
|
||||
|
||||
### Using basic authentication:
|
||||
|
||||
```
|
||||
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
||||
```
|
||||
|
||||
As of v1.8.0 of Gitea, if using basic authentication with the API and your user has two factor authentication enabled, you'll need to send an additional header that contains the one time password (6 digit rotating token). An example of the header is `X-Gitea-OTP: 123456` where `123456` is where you'd place the code from your authenticator. Here is how the request would look like in curl:
|
||||
|
||||
```
|
||||
$ curl -H "X-Gitea-OTP: 123456" --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||
```
|
||||
|
||||
## Sudo
|
||||
|
||||
The API allows admin users to sudo API requests as another user. Simply add either a `sudo=` parameter or `Sudo:` request header with the username of the user to sudo.
|
@@ -1,71 +0,0 @@
|
||||
---
|
||||
date: "2018-06-24:00:00+02:00"
|
||||
title: "API 使用指南"
|
||||
slug: "api-usage"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "API 使用指南"
|
||||
weight: 40
|
||||
identifier: "api-usage"
|
||||
---
|
||||
|
||||
# Gitea API 使用指南
|
||||
|
||||
## 开启/配置 API 访问
|
||||
|
||||
通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat
|
||||
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) 中获取更多配置相关信息。
|
||||
|
||||
## 通过 API 认证
|
||||
|
||||
Gitea 支持以下几种 API 认证方式:
|
||||
|
||||
- HTTP basic authentication 方式
|
||||
- 通过指定 `token=...` URL 查询参数方式
|
||||
- 通过指定 `access_token=...` URL 查询参数方式
|
||||
- 通过指定 `Authorization: token ...` HTTP header 方式
|
||||
|
||||
以上提及的认证方法接受相同的 apiKey token 类型,您可以在编码时通过查阅代码更好地理解这一点。
|
||||
Gitea 调用解析查询参数以及头部信息来获取 token 的代码可以在 [modules/auth/auth.go](https://github.com/go-gitea/gitea/blob/6efdcaed86565c91a3dc77631372a9cc45a58e89/modules/auth/auth.go#L47) 中找到。
|
||||
|
||||
您可以通过您的 gitea web 界面来创建 apiKey token:
|
||||
`Settings | Applications | Generate New Token`.
|
||||
|
||||
### 关于 `Authorization:` header
|
||||
|
||||
由于一些历史原因,Gitea 需要在 header 的 apiKey token 里引入前缀 `token`,类似于如下形式:
|
||||
|
||||
```
|
||||
Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675
|
||||
```
|
||||
|
||||
以 `curl` 命令为例,它会以如下形式携带在请求中:
|
||||
|
||||
```
|
||||
curl -X POST "http://localhost:4000/api/v1/repos/test1/test1/issues" \
|
||||
-H "accept: application/json" \
|
||||
-H "Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675" \
|
||||
-H "Content-Type: application/json" -d "{ \"body\": \"testing\", \"title\": \"test 20\"}" -i
|
||||
```
|
||||
|
||||
正如上例所示,您也可以在 GET 请求中使用同一个 token 并以 `token=` 的查询参数形式携带 token 来进行认证。
|
||||
|
||||
## 通过 API 列出您发布的令牌
|
||||
|
||||
`/users/:name/tokens` 是一个特殊的接口,需要您使用 basic authentication 进行认证,具体原因在 issue 中
|
||||
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346) 有所提及,使用方法如下所示:
|
||||
|
||||
### 使用 Basic authentication 认证:
|
||||
|
||||
```
|
||||
$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
|
||||
[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
|
||||
```
|
||||
|
||||
## 使用 Sudo 方式请求 API
|
||||
|
||||
此 API 允许管理员借用其他用户身份进行 API 请求。只需在请求中指定查询参数 `sudo=` 或是指定 header 中的 `Sudo:` 为需要使用的用户 username 即可。
|
@@ -1,34 +0,0 @@
|
||||
---
|
||||
date: "2019-08-27:00:00+02:00"
|
||||
title: "CI/CD Usage"
|
||||
slug: "ci-cd"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "CI/CD Usage"
|
||||
weight: 40
|
||||
identifier: "ci-cd"
|
||||
---
|
||||
|
||||
# Gitea and CI/CD
|
||||
|
||||
**NOTE:** These tools are not endorsed by Gitea. They are listed here for convenience only.
|
||||
|
||||
## Listing
|
||||
|
||||
CI/CD solutions that have integration with Gitea. Following list is not complete,
|
||||
the purpose is to give a starting point to integrate a CI/CD process with your Gitea instance.
|
||||
|
||||
- [Drone](https://drone.io) with [Gitea documentation](https://docs.drone.io/installation/providers/gitea/)
|
||||
- [Jenkins](https://jenkins.io/) with [Gitea plugin](https://plugins.jenkins.io/gitea)
|
||||
- [Agola](https://agola.io)
|
||||
- [Buildkite](https://buildkite.com) with [Gitea connector](https://github.com/techknowlogick/gitea-buildkite-connector)
|
||||
- [AppVeyor](https://www.appveyor.com) with [built-in Gitea support](https://www.appveyor.com/blog/2019/09/05/gitea-receives-first-class-support-in-appveyor/)
|
||||
- [Buildbot](https://www.buildbot.net/) with [Gitea plugin](https://github.com/lab132/buildbot-gitea)
|
||||
|
||||
|
||||
Others CI/CD solutions that partially can be integrated with Gitea:
|
||||
- [Concourse](https://www.concourse-ci.org), see more information at [Concourse community forum](https://discuss.concourse-ci.org/t/concourse-ci-and-gitea-oauth/1475)
|
@@ -1,650 +0,0 @@
|
||||
---
|
||||
date: "2016-12-26T16:00:00+02:00"
|
||||
title: "Config Cheat Sheet"
|
||||
slug: "config-cheat-sheet"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Config Cheat Sheet"
|
||||
weight: 20
|
||||
identifier: "config-cheat-sheet"
|
||||
---
|
||||
|
||||
# Configuration Cheat Sheet
|
||||
|
||||
This is a cheat sheet for the Gitea configuration file. It contains most of the settings
|
||||
that can be configured as well as their default values.
|
||||
|
||||
Any changes to the Gitea configuration file should be made in `custom/conf/app.ini`
|
||||
or any corresponding location. When installing from a distribution, this will
|
||||
typically be found at `/etc/gitea/conf/app.ini`.
|
||||
|
||||
The defaults provided here are best-effort (not built automatically). They are
|
||||
accurately recorded in [app.ini.sample](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
|
||||
(s/master/\<tag|release\>). Any string in the format `%(X)s` is a feature powered
|
||||
by [ini](https://github.com/go-ini/ini/#recursive-values), for reading values recursively.
|
||||
|
||||
Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
|
||||
**Note:** A full restart is required for Gitea configuration changes to take effect.
|
||||
|
||||
## Overall (`DEFAULT`)
|
||||
|
||||
- `APP_NAME`: **Gitea: Git with a cup of tea**: Application name, used in the page title.
|
||||
- `RUN_USER`: **git**: The user Gitea will run as. This should be a dedicated system
|
||||
(non-user) account. Setting this incorrectly will cause Gitea to not start.
|
||||
- `RUN_MODE`: **dev**: For performance and other purposes, change this to `prod` when
|
||||
deployed to a production environment. The installation process will set this to `prod`
|
||||
automatically. \[prod, dev, test\]
|
||||
|
||||
## Repository (`repository`)
|
||||
|
||||
- `ROOT`: **~/gitea-repositories/**: Root path for storing all repository data. It must be
|
||||
an absolute path.
|
||||
- `SCRIPT_TYPE`: **bash**: The script type this server supports. Usually this is `bash`,
|
||||
but some users report that only `sh` is available.
|
||||
- `ANSI_CHARSET`: **\<empty\>**: The default charset for an unrecognized charset.
|
||||
- `FORCE_PRIVATE`: **false**: Force every new repository to be private.
|
||||
- `DEFAULT_PRIVATE`: **last**: Default private when creating a new repository.
|
||||
\[last, private, public\]
|
||||
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
|
||||
`-1` means no limit.
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`: **1000**: Length of pull request patch test queue, make it
|
||||
as large as possible. Use caution when editing this value.
|
||||
- `MIRROR_QUEUE_LENGTH`: **1000**: Patch test queue length, increase if pull request patch
|
||||
testing starts hanging.
|
||||
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
|
||||
the top of the list. Name must match file name in conf/license or custom/conf/license.
|
||||
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
|
||||
HTTP protocol.
|
||||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
|
||||
default SSH port is used.
|
||||
- `ACCESS_CONTROL_ALLOW_ORIGIN`: **\<empty\>**: Value for Access-Control-Allow-Origin header,
|
||||
default is not to present. **WARNING**: This maybe harmful to you website if you do not
|
||||
give it a right value.
|
||||
- `DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH`: **false**: Close an issue if a commit on a non default branch marks it as closed.
|
||||
- `ENABLE_PUSH_CREATE_USER`: **false**: Allow users to push local repositories to Gitea and have them automatically created for a user.
|
||||
- `ENABLE_PUSH_CREATE_ORG`: **false**: Allow users to push local repositories to Gitea and have them automatically created for an org.
|
||||
|
||||
### Repository - Pull Request (`repository.pull-request`)
|
||||
|
||||
- `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: List of prefixes used in Pull Request
|
||||
title to mark them as Work In Progress
|
||||
- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: List of
|
||||
keywords used in Pull Request comments to automatically close a related issue
|
||||
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: List of keywords used in Pull Request comments to automatically reopen
|
||||
a related issue
|
||||
- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: In the default merge message for squash commits include at most this many commits. Set to `-1` to include all commits
|
||||
- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: In the default merge message for squash commits limit the size of the commit messages. Set to `-1` to have no limit.
|
||||
- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: In the default merge message for squash commits walk all commits to include all authors in the Co-authored-by otherwise just use those in the limited list
|
||||
- `DEFAULT_MERGE_MESSAGE_MAX_APPROVERS`: **10**: In default merge messages limit the number of approvers listed as `Reviewed-by:`. Set to `-1` to include all.
|
||||
- `DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY`: **true**: In default merge messages only include approvers who are officially allowed to review.
|
||||
|
||||
### Repository - Issue (`repository.issue`)
|
||||
|
||||
- `LOCK_REASONS`: **Too heated,Off-topic,Resolved,Spam**: A list of reasons why a Pull Request or Issue can be locked
|
||||
|
||||
### Repository - Signing (`repository.signing`)
|
||||
|
||||
- `SIGNING_KEY`: **default**: \[none, KEYID, default \]: Key to sign with.
|
||||
- `SIGNING_NAME` & `SIGNING_EMAIL`: if a KEYID is provided as the `SIGNING_KEY`, use these as the Name and Email address of the signer. These should match publicized name and email address for the key.
|
||||
- `INITIAL_COMMIT`: **always**: \[never, pubkey, twofa, always\]: Sign initial commit.
|
||||
- `never`: Never sign
|
||||
- `pubkey`: Only sign if the user has a public key
|
||||
- `twofa`: Only sign if the user is logged in with twofa
|
||||
- `always`: Always sign
|
||||
- Options other than `never` and `always` can be combined as a comma separated list.
|
||||
- `WIKI`: **never**: \[never, pubkey, twofa, always, parentsigned\]: Sign commits to wiki.
|
||||
- `CRUD_ACTIONS`: **pubkey, twofa, parentsigned**: \[never, pubkey, twofa, parentsigned, always\]: Sign CRUD actions.
|
||||
- Options as above, with the addition of:
|
||||
- `parentsigned`: Only sign if the parent commit is signed.
|
||||
- `MERGES`: **pubkey, twofa, basesigned, commitssigned**: \[never, pubkey, twofa, approved, basesigned, commitssigned, always\]: Sign merges.
|
||||
- `approved`: Only sign approved merges to a protected branch.
|
||||
- `basesigned`: Only sign if the parent commit in the base repo is signed.
|
||||
- `headsigned`: Only sign if the head commit in the head branch is signed.
|
||||
- `commitssigned`: Only sign if all the commits in the head branch to the merge point are signed.
|
||||
|
||||
## CORS (`cors`)
|
||||
|
||||
- `ENABLED`: **false**: enable cors headers (disabled by default)
|
||||
- `SCHEME`: **http**: scheme of allowed requests
|
||||
- `ALLOW_DOMAIN`: **\***: list of requesting domains that are allowed
|
||||
- `ALLOW_SUBDOMAIN`: **false**: allow subdomains of headers listed above to request
|
||||
- `METHODS`: **GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS**: list of methods allowed to request
|
||||
- `MAX_AGE`: **10m**: max time to cache response
|
||||
- `ALLOW_CREDENTIALS`: **false**: allow request with credentials
|
||||
|
||||
## UI (`ui`)
|
||||
|
||||
- `EXPLORE_PAGING_NUM`: **20**: Number of repositories that are shown in one explore page.
|
||||
- `ISSUE_PAGING_NUM`: **10**: Number of issues that are shown in one page (for all pages that list issues).
|
||||
- `MEMBERS_PAGING_NUM`: **20**: Number of members that are shown in organization members.
|
||||
- `FEED_MAX_COMMIT_NUM`: **5**: Number of maximum commits shown in one activity feed.
|
||||
- `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph.
|
||||
- `DEFAULT_THEME`: **gitea**: \[gitea, arc-green\]: Set the default theme for the Gitea install.
|
||||
- `THEMES`: **gitea,arc-green**: All available themes. Allow users select personalized themes
|
||||
regardless of the value of `DEFAULT_THEME`.
|
||||
- `REACTIONS`: All available reactions. Allow users react with different emoji's.
|
||||
- `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
|
||||
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
|
||||
- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets.
|
||||
|
||||
### UI - Admin (`ui.admin`)
|
||||
|
||||
- `USER_PAGING_NUM`: **50**: Number of users that are shown in one page.
|
||||
- `REPO_PAGING_NUM`: **50**: Number of repos that are shown in one page.
|
||||
- `NOTICE_PAGING_NUM`: **25**: Number of notices that are shown in one page.
|
||||
- `ORG_PAGING_NUM`: **50**: Number of organizations that are shown in one page.
|
||||
|
||||
## Markdown (`markdown`)
|
||||
|
||||
- `ENABLE_HARD_LINE_BREAK`: **false**: Enable Markdown's hard line break extension.
|
||||
- `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
|
||||
URL hyperlinks to be rendered in Markdown. URLs beginning in http and https are
|
||||
always displayed
|
||||
|
||||
## Server (`server`)
|
||||
|
||||
- `PROTOCOL`: **http**: \[http, https, fcgi, unix, fcgi+unix\]
|
||||
- `DOMAIN`: **localhost**: Domain name of this server.
|
||||
- `ROOT_URL`: **%(PROTOCOL)s://%(DOMAIN)s:%(HTTP\_PORT)s/**:
|
||||
Overwrite the automatically generated public URL.
|
||||
This is useful if the internal and the external URL don't match (e.g. in Docker).
|
||||
- `STATIC_URL_PREFIX`: **\<empty\>**:
|
||||
Overwrite this option to request static resources from a different URL.
|
||||
This includes CSS files, images, JS files and web fonts.
|
||||
Avatar images are dynamic resources and still served by gitea.
|
||||
The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`.
|
||||
Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective.
|
||||
The static files are located in the `public/` directory of the gitea source repository.
|
||||
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
|
||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
||||
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||
- If `PROTOCOL` is set to `unix` or `fcgi+unix`, this should be the name of the Unix socket file to use.
|
||||
- `HTTP_PORT`: **3000**: HTTP listen port.
|
||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
||||
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||
- `UNIX_SOCKET_PERMISSION`: **666**: Permissions for the Unix socket.
|
||||
- `LOCAL_ROOT_URL`: **%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/**: Local
|
||||
(DMZ) URL for Gitea workers (such as SSH update) accessing web service. In
|
||||
most cases you do not need to change the default value. Alter it only if
|
||||
your SSH server node is not the same as HTTP node. Do not set this variable
|
||||
if `PROTOCOL` is set to `unix`.
|
||||
- `DISABLE_SSH`: **false**: Disable SSH feature when it's not available.
|
||||
- `START_SSH_SERVER`: **false**: When enabled, use the built-in SSH server.
|
||||
- `SSH_DOMAIN`: **%(DOMAIN)s**: Domain name of this server, used for displayed clone URL.
|
||||
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
|
||||
- `SSH_LISTEN_HOST`: **0.0.0.0**: Listen address for the built-in SSH server.
|
||||
- `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
|
||||
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
||||
- `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.
|
||||
- `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.
|
||||
- `LANDING_PAGE`: **home**: Landing page for unauthenticated users \[home, explore, organizations, login\].
|
||||
- `LFS_START_SERVER`: **false**: Enables git-lfs support.
|
||||
- `LFS_CONTENT_PATH`: **./data/lfs**: Where to store LFS files.
|
||||
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
||||
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
||||
- `ENABLE_LETSENCRYPT`: **false**: If enabled you must set `DOMAIN` to valid internet facing domain (ensure DNS is set and port 80 is accessible by letsencrypt validation server).
|
||||
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
|
||||
- `LETSENCRYPT_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service for Let's Encrypt.
|
||||
- `LETSENCRYPT_DIRECTORY`: **https**: Directory that Letsencrypt will use to cache information such as certs and private keys.
|
||||
- `LETSENCRYPT_EMAIL`: **email@example.com**: Email used by Letsencrypt to notify about problems with issued certificates. (No default)
|
||||
- `ALLOW_GRACEFUL_RESTARTS`: **true**: Perform a graceful restart on SIGHUP
|
||||
- `GRACEFUL_HAMMER_TIME`: **60s**: After a restart the parent process will stop accepting new connections and will allow requests to finish before stopping. Shutdown will be forced if it takes longer than this time.
|
||||
- `STARTUP_TIMEOUT`: **0**: Shutsdown the server if startup takes longer than the provided time. On Windows setting this sends a waithint to the SVC host to tell the SVC host startup may take some time. Please note startup is determined by the opening of the listeners - HTTP/HTTPS/SSH. Indexers may take longer to startup and can have their own timeouts.
|
||||
|
||||
## Database (`database`)
|
||||
|
||||
- `DB_TYPE`: **mysql**: The database type in use \[mysql, postgres, mssql, sqlite3\].
|
||||
- `HOST`: **127.0.0.1:3306**: Database host address and port or absolute path for unix socket \[mysql, postgres\] (ex: /var/run/mysqld/mysqld.sock).
|
||||
- `NAME`: **gitea**: Database name.
|
||||
- `USER`: **root**: Database username.
|
||||
- `PASSWD`: **\<empty\>**: Database user password. Use \`your password\` for quoting if you use special characters in the password.
|
||||
- `SSL_MODE`: **disable**: For PostgreSQL and MySQL only.
|
||||
- `CHARSET`: **utf8**: For MySQL only, either "utf8" or "utf8mb4", default is "utf8". NOTICE: for "utf8mb4" you must use MySQL InnoDB > 5.6. Gitea is unable to check this.
|
||||
- `PATH`: **data/gitea.db**: For SQLite3 only, the database file path.
|
||||
- `LOG_SQL`: **true**: Log the executed SQL.
|
||||
- `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed.
|
||||
- `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured.
|
||||
- `MAX_OPEN_CONNS` **0**: Database maximum open connections - default is 0, meaning there is no limit.
|
||||
- `MAX_IDLE_CONNS` **2**: Max idle database connections on connnection pool, default is 2 - this will be capped to `MAX_OPEN_CONNS`.
|
||||
- `CONN_MAX_LIFETIME` **0 or 3s**: Sets the maximum amount of time a DB connection may be reused - default is 0, meaning there is no limit (except on MySQL where it is 3s - see #6804 & #7071).
|
||||
|
||||
Please see #8540 & #8273 for further discussion of the appropriate values for `MAX_OPEN_CONNS`, `MAX_IDLE_CONNS` & `CONN_MAX_LIFETIME` and their
|
||||
relation to port exhaustion.
|
||||
|
||||
## Indexer (`indexer`)
|
||||
|
||||
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently support: bleve or db, if it's db, below issue indexer item will be invalid.
|
||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search.
|
||||
- The next 4 configuration values are deprecated and should be set in `queue.issue_indexer` however are kept for backwards compatibility:
|
||||
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: Issue indexer queue, currently supports:`channel`, `levelqueue`, `redis`.
|
||||
- `ISSUE_INDEXER_QUEUE_DIR`: **indexers/issues.queue**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the queue will be saved path.
|
||||
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
||||
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number.
|
||||
|
||||
- `REPO_INDEXER_ENABLED`: **false**: Enables code search (uses a lot of disk space, about 6 times more than the repository size).
|
||||
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: Index file used for code search.
|
||||
- `REPO_INDEXER_INCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **include** in the index. Use `**.txt` to match any files with .txt extension. An empty list means include all files.
|
||||
- `REPO_INDEXER_EXCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **exclude** from the index. Files that match this list will not be indexed, even if they match in `REPO_INDEXER_INCLUDE`.
|
||||
- `UPDATE_BUFFER_LEN`: **20**: Buffer length of index request.
|
||||
- `MAX_FILE_SIZE`: **1048576**: Maximum size in bytes of files to be indexed.
|
||||
- `STARTUP_TIMEOUT`: **30s**: If the indexer takes longer than this timeout to start - fail. (This timeout will be added to the hammer time above for child processes - as bleve will not start until the previous parent is shutdown.) Set to zero to never timeout.
|
||||
|
||||
## Queue (`queue` and `queue.*`)
|
||||
|
||||
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel`, `channel`, `level`, `redis`, `dummy`
|
||||
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for inidividual queues can be set in `queue.name` sections but will default to `DATADIR/`**`name`**.
|
||||
- `LENGTH`: **20**: Maximal queue size before channel queues block
|
||||
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
||||
- `CONN_STR`: **addrs=127.0.0.1:6379 db=0**: Connection string for the redis queue type.
|
||||
- `QUEUE_NAME`: **_queue**: The suffix for default redis queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overriden in the specific `queue.name` section.
|
||||
- `WRAP_IF_NECESSARY`: **true**: Will wrap queues with a timeoutable queue if the selected queue is not ready to be created - (Only relevant for the level queue.)
|
||||
- `MAX_ATTEMPTS`: **10**: Maximum number of attempts to create the wrapped queue
|
||||
- `TIMEOUT`: **GRACEFUL_HAMMER_TIME + 30s**: Timeout the creation of the wrapped queue if it takes longer than this to create.
|
||||
- Queues by default come with a dynamically scaling worker pool. The following settings configure this:
|
||||
- `WORKERS`: **1**: Number of initial workers for the queue.
|
||||
- `MAX_WORKERS`: **10**: Maximum number of worker go-routines for the queue.
|
||||
- `BLOCK_TIMEOUT`: **1s**: If the queue blocks for this time, boost the number of workers - the `BLOCK_TIMEOUT` will then be doubled before boosting again whilst the boost is ongoing.
|
||||
- `BOOST_TIMEOUT`: **5m**: Boost workers will timeout after this long.
|
||||
- `BOOST_WORKERS`: **5**: This many workers will be added to the worker pool if there is a boost.
|
||||
|
||||
## Admin (`admin`)
|
||||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||
|
||||
## Security (`security`)
|
||||
|
||||
- `INSTALL_LOCK`: **false**: Disallow access to the install page.
|
||||
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This should be changed.
|
||||
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
|
||||
- `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username.
|
||||
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
|
||||
information.
|
||||
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy
|
||||
authentication.
|
||||
- `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**: Header name for reverse proxy
|
||||
authentication provided email.
|
||||
- `DISABLE_GIT_HOOKS`: **false**: Set to `true` to prevent all users (including admin) from creating custom
|
||||
git hooks.
|
||||
- `ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET`: **true**: Set to `false` to allow local users to push to gitea-repositories without setting up the Gitea environment. This is not recommended and if you want local users to push to gitea repositories you should set the environment appropriately.
|
||||
- `IMPORT_LOCAL_PATHS`: **false**: Set to `false` to prevent all users (including admin) from importing local path on server.
|
||||
- `INTERNAL_TOKEN`: **\<random at every install if no uri set\>**: Secret used to validate communication within Gitea binary.
|
||||
- `INTERNAL_TOKEN_URI`: **<empty>**: Instead of defining internal token in the configuration, this configuration option can be used to give Gitea a path to a file that contains the internal token (example value: `file:/etc/gitea/internal_token`)
|
||||
- `PASSWORD_HASH_ALGO`: **pbkdf2**: The hash algorithm to use \[pbkdf2, argon2, scrypt, bcrypt\].
|
||||
- `CSRF_COOKIE_HTTP_ONLY`: **true**: Set false to allow JavaScript to read CSRF cookie.
|
||||
- `PASSWORD_COMPLEXITY`: **lower,upper,digit,spec**: Comma separated list of character classes required to pass minimum complexity. If left empty or no valid values are specified, the default values will be used. Possible values are:
|
||||
- lower - use one or more lower latin characters
|
||||
- upper - use one or more upper latin characters
|
||||
- digit - use one or more digits
|
||||
- spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
|
||||
- off - do not check password complexity
|
||||
|
||||
## OpenID (`openid`)
|
||||
|
||||
- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID.
|
||||
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
|
||||
- `WHITELISTED_URIS`: **\<empty\>**: If non-empty, list of POSIX regex patterns matching
|
||||
OpenID URI's to permit.
|
||||
- `BLACKLISTED_URIS`: **\<empty\>**: If non-empty, list of POSIX regex patterns matching
|
||||
OpenID URI's to block.
|
||||
|
||||
## Service (`service`)
|
||||
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm account/email registration.
|
||||
- `RESET_PASSWD_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm forgot password reset
|
||||
process.
|
||||
- `REGISTER_EMAIL_CONFIRM`: **false**: Enable this to ask for mail confirmation of registration.
|
||||
Requires `Mailer` to be enabled.
|
||||
- `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create
|
||||
accounts for users.
|
||||
- `REQUIRE_EXTERNAL_REGISTRATION_PASSWORD`: **false**: Enable this to force externally created
|
||||
accounts (via GitHub, OpenID Connect, etc) to create a password. Warning: enabling this will
|
||||
decrease security, so you should only enable it if you know what you're doing.
|
||||
- `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page.
|
||||
- `ENABLE_NOTIFY_MAIL`: **false**: Enable this to send e-mail to watchers of a repository when
|
||||
something happens, like creating issues. Requires `Mailer` to be enabled.
|
||||
- `ENABLE_BASIC_AUTHENTICATION`: **true**: Disable this to disallow authenticaton using HTTP
|
||||
BASIC and the user's password. Please note if you disable this you will not be able to access the
|
||||
tokens API endpoints using a password. Further, this only disables BASIC authentication using the
|
||||
password - not tokens or OAuth Basic.
|
||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication.
|
||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: Enable this to allow auto-registration
|
||||
for reverse authentication.
|
||||
- `ENABLE_REVERSE_PROXY_EMAIL`: **false**: Enable this to allow to auto-registration with a
|
||||
provided email rather than a generated email.
|
||||
- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
|
||||
- `REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA`: **false**: Enable this to force captcha validation
|
||||
even for External Accounts (i.e. GitHub, OpenID Connect, etc). You must `ENABLE_CAPTCHA` also.
|
||||
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha\]
|
||||
- `RECAPTCHA_SECRET`: **""**: Go to https://www.google.com/recaptcha/admin to get a secret for recaptcha.
|
||||
- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha.
|
||||
- `RECAPTCHA_URL`: **https://www.google.com/recaptcha/**: Set the recaptcha url - allows the use of recaptcha net.
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: **true**: Enable this to have dependencies enabled by default.
|
||||
- `ALLOW_CROSS_REPOSITORY_DEPENDENCIES` : **true** Enable this to allow dependencies on issues from any repository where the user is granted access.
|
||||
- `ENABLE_USER_HEATMAP`: **true**: Enable this to display the heatmap on users profiles.
|
||||
- `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register
|
||||
on this instance.
|
||||
- `SHOW_REGISTRATION_BUTTON`: **! DISABLE\_REGISTRATION**: Show Registration Button
|
||||
- `SHOW_MILESTONES_DASHBOARD_PAGE`: **true** Enable this to show the milestones dashboard page - a view of all the user's milestones
|
||||
- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
|
||||
- `AUTO_WATCH_ON_CHANGES`: **false**: Enable this to make users watch a repository after their first commit to it
|
||||
- `DEFAULT_ORG_VISIBILITY`: **public**: Set default visibility mode for organisations, either "public", "limited" or "private".
|
||||
- `DEFAULT_ORG_MEMBER_VISIBLE`: **false** True will make the membership of the users visible when added to the organisation.
|
||||
- `ALLOW_ONLY_EXTERNAL_REGISTRATION`: **false** Set to true to force registration only using third-party services.
|
||||
- `NO_REPLY_ADDRESS`: **DOMAIN** Default value for the domain part of the user's email address in the git log if he has set KeepEmailPrivate to true.
|
||||
The user's email will be replaced with a concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
|
||||
|
||||
## Webhook (`webhook`)
|
||||
|
||||
- `QUEUE_LENGTH`: **1000**: Hook task queue length. Use caution when editing this value.
|
||||
- `DELIVER_TIMEOUT`: **5**: Delivery timeout (sec) for shooting webhooks.
|
||||
- `SKIP_TLS_VERIFY`: **false**: Allow insecure certification.
|
||||
- `PAGING_NUM`: **10**: Number of webhook history events that are shown in one page.
|
||||
- `PROXY_URL`: ****: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
|
||||
- `PROXY_HOSTS`: ****: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
|
||||
|
||||
## Mailer (`mailer`)
|
||||
|
||||
- `ENABLED`: **false**: Enable to use a mail service.
|
||||
- `DISABLE_HELO`: **\<empty\>**: Disable HELO operation.
|
||||
- `HELO_HOSTNAME`: **\<empty\>**: Custom hostname for HELO operation.
|
||||
- `HOST`: **\<empty\>**: SMTP mail host address and port (example: smtp.gitea.io:587).
|
||||
- `FROM`: **\<empty\>**: Mail from address, RFC 5322. This can be just an email address, or
|
||||
the "Name" \<email@example.com\> format.
|
||||
- `USER`: **\<empty\>**: Username of mailing user (usually the sender's e-mail address).
|
||||
- `PASSWD`: **\<empty\>**: Password of mailing user. Use \`your password\` for quoting if you use special characters in the password.
|
||||
- `SKIP_VERIFY`: **\<empty\>**: Do not verify the self-signed certificates.
|
||||
- **Note:** Gitea only supports SMTP with STARTTLS.
|
||||
- `SUBJECT_PREFIX`: **\<empty\>**: Prefix to be placed before e-mail subject lines.
|
||||
- `MAILER_TYPE`: **smtp**: \[smtp, sendmail, dummy\]
|
||||
- **smtp** Use SMTP to send mail
|
||||
- **sendmail** Use the operating system's `sendmail` command instead of SMTP.
|
||||
This is common on linux systems.
|
||||
- **dummy** Send email messages to the log as a testing phase.
|
||||
- Note that enabling sendmail will ignore all other `mailer` settings except `ENABLED`,
|
||||
`FROM`, `SUBJECT_PREFIX` and `SENDMAIL_PATH`.
|
||||
- Enabling dummy will ignore all settings except `ENABLED`, `SUBJECT_PREFIX` and `FROM`.
|
||||
- `SENDMAIL_PATH`: **sendmail**: The location of sendmail on the operating system (can be
|
||||
command or full path).
|
||||
- ``IS_TLS_ENABLED`` : **false** : Decide if SMTP connections should use TLS.
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, or `memcache`.
|
||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory cache only.
|
||||
- `HOST`: **\<empty\>**: Connection string for `redis` and `memcache`.
|
||||
- Redis: `network=tcp,addr=127.0.0.1:6379,password=macaron,db=0,pool_size=100,idle_timeout=180`
|
||||
- Memcache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to 0 disables caching.
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, mysql, couchbase, memcache, nodb, postgres\].
|
||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for others, the connection string.
|
||||
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
||||
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
||||
- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
|
||||
|
||||
## Picture (`picture`)
|
||||
|
||||
- `GRAVATAR_SOURCE`: **gravatar**: Can be `gravatar`, `duoshuo` or anything like
|
||||
`http://cn.gravatar.com/avatar/`.
|
||||
- `DISABLE_GRAVATAR`: **false**: Enable this to use local avatars only.
|
||||
- `ENABLE_FEDERATED_AVATAR`: **false**: Enable support for federated avatars (see
|
||||
[http://www.libravatar.org](http://www.libravatar.org)).
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
|
||||
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
|
||||
- `REPOSITORY_AVATAR_FALLBACK`: **none**: How Gitea deals with missing repository avatars
|
||||
- none = no avatar will be displayed
|
||||
- random = random avatar will be generated
|
||||
- image = default image will be used (which is set in `REPOSITORY_AVATAR_DEFAULT_IMAGE`)
|
||||
- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **/img/repo_default.png**: Image used as default repository avatar (if `REPOSITORY_AVATAR_FALLBACK` is set to image and none was uploaded)
|
||||
- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
|
||||
- `AVATAR_MAX_HEIGHT`: **3072**: Maximum avatar image height in pixels.
|
||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): Maximum avatar image file size in bytes.
|
||||
|
||||
## Attachment (`attachment`)
|
||||
|
||||
- `ENABLED`: **true**: Enable this to allow uploading attachments.
|
||||
- `PATH`: **data/attachments**: Path to store attachments.
|
||||
- `ALLOWED_TYPES`: **see app.ini.sample**: Allowed MIME types, e.g. `image/jpeg|image/png`.
|
||||
Use `*/*` for all types.
|
||||
- `MAX_SIZE`: **4**: Maximum size (MB).
|
||||
- `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once.
|
||||
|
||||
## Log (`log`)
|
||||
|
||||
- `ROOT_PATH`: **\<empty\>**: Root path for log files.
|
||||
- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values. You can configure each mode in per mode log subsections `\[log.modename\]`. By default the file mode will log to `$ROOT_PATH/gitea.log`.
|
||||
- `LEVEL`: **Info**: General log level. \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
|
||||
- `STACKTRACE_LEVEL`: **None**: Default log level at which to log create stack traces. \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
|
||||
- `REDIRECT_MACARON_LOG`: **false**: Redirects the Macaron log to its own logger or the default logger.
|
||||
- `MACARON`: **file**: Logging mode for the macaron logger, use a comma to separate values. Configure each mode in per mode log subsections `\[log.modename.macaron\]`. By default the file mode will log to `$ROOT_PATH/macaron.log`. (If you set this to `,` it will log to default gitea logger.)
|
||||
- `ROUTER_LOG_LEVEL`: **Info**: The log level that the router should log at. (If you are setting the access log, its recommended to place this at Debug.)
|
||||
- `ROUTER`: **console**: The mode or name of the log the router should log to. (If you set this to `,` it will log to default gitea logger.)
|
||||
NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false` for this option to take effect. Configure each mode in per mode log subsections `\[log.modename.router\]`.
|
||||
- `ENABLE_ACCESS_LOG`: **false**: Creates an access.log in NCSA common log format, or as per the following template
|
||||
- `ACCESS`: **file**: Logging mode for the access logger, use a comma to separate values. Configure each mode in per mode log subsections `\[log.modename.access\]`. By default the file mode will log to `$ROOT_PATH/access.log`. (If you set this to `,` it will log to the default gitea logger.)
|
||||
- `ACCESS_LOG_TEMPLATE`: **`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`**: Sets the template used to create the access log.
|
||||
- The following variables are available:
|
||||
- `Ctx`: the `macaron.Context` of the request.
|
||||
- `Identity`: the SignedUserName or `"-"` if not logged in.
|
||||
- `Start`: the start time of the request.
|
||||
- `ResponseWriter`: the responseWriter from the request.
|
||||
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside of the panic/recovery script.
|
||||
- `ENABLE_XORM_LOG`: **true**: Set whether to perform XORM logging. Please note SQL statement logging can be disabled by setting `LOG_SQL` to false in the `[database]` section.
|
||||
|
||||
### Log subsections (`log.name`, `log.name.*`)
|
||||
|
||||
- `LEVEL`: **log.LEVEL**: Sets the log-level of this sublogger. Defaults to the `LEVEL` set in the global `[log]` section.
|
||||
- `STACKTRACE_LEVEL`: **log.STACKTRACE_LEVEL**: Sets the log level at which to log stack traces.
|
||||
- `MODE`: **name**: Sets the mode of this sublogger - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels.
|
||||
- `EXPRESSION`: **""**: A regular expression to match either the function name, file or message. Defaults to empty. Only log messages that match the expression will be saved in the logger.
|
||||
- `FLAGS`: **stdflags**: A comma separated string representing the log flags. Defaults to `stdflags` which represents the prefix: `2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message`. `none` means don't prefix log lines. See `modules/log/base.go` for more information.
|
||||
- `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty.
|
||||
- `COLORIZE`: **false**: Colorize the log lines by default
|
||||
|
||||
### Console log mode (`log.console`, `log.console.*`, or `MODE=console`)
|
||||
|
||||
- For the console logger `COLORIZE` will default to `true` if not on windows or the terminal is determined to be able to color.
|
||||
- `STDERR`: **false**: Use Stderr instead of Stdout.
|
||||
|
||||
### File log mode (`log.file`, `log.file.*` or `MODE=file`)
|
||||
|
||||
- `FILE_NAME`: Set the file name for this logger. Defaults as described above. If relative will be relative to the `ROOT_PATH`
|
||||
- `LOG_ROTATE`: **true**: Rotate the log files.
|
||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
|
||||
- `DAILY_ROTATE`: **true**: Rotate logs daily.
|
||||
- `MAX_DAYS`: **7**: Delete the log file after n days
|
||||
- `COMPRESS`: **true**: Compress old log files by default with gzip
|
||||
- `COMPRESSION_LEVEL`: **-1**: Compression level
|
||||
|
||||
### Conn log mode (`log.conn`, `log.conn.*` or `MODE=conn`)
|
||||
|
||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||
|
||||
### SMTP log mode (`log.smtp`, `log.smtp.*` or `MODE=smtp`)
|
||||
|
||||
- `USER`: User email address to send from.
|
||||
- `PASSWD`: Password for the smtp server.
|
||||
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
||||
- `RECEIVERS`: Email addresses to send to.
|
||||
- `SUBJECT`: **Diagnostic message from Gitea**
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
- `ENABLED`: **true**: Run cron tasks periodically.
|
||||
- `RUN_AT_START`: **false**: Run cron tasks at application start-up.
|
||||
|
||||
### Cron - Cleanup old repository archives (`cron.archive_cleanup`)
|
||||
|
||||
- `ENABLED`: **true**: Enable service.
|
||||
- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
|
||||
- `SCHEDULE`: **@every 24h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
|
||||
- `OLDER_THAN`: **24h**: Archives created more than `OLDER_THAN` ago are subject to deletion, e.g. `12h`.
|
||||
|
||||
### Cron - Update Mirrors (`cron.update_mirrors`)
|
||||
|
||||
- `SCHEDULE`: **@every 10m**: Cron syntax for scheduling update mirrors, e.g. `@every 3h`.
|
||||
|
||||
### Cron - Repository Health Check (`cron.repo_health_check`)
|
||||
|
||||
- `SCHEDULE`: **every 24h**: Cron syntax for scheduling repository health check.
|
||||
- `TIMEOUT`: **60s**: Time duration syntax for health check execution timeout.
|
||||
- `ARGS`: **\<empty\>**: Arguments for command `git fsck`, e.g. `--unreachable --tags`. See more on http://git-scm.com/docs/git-fsck
|
||||
|
||||
### Cron - Repository Statistics Check (`cron.check_repo_stats`)
|
||||
|
||||
- `RUN_AT_START`: **true**: Run repository statistics check at start time.
|
||||
- `SCHEDULE`: **@every 24h**: Cron syntax for scheduling repository statistics check.
|
||||
|
||||
### Cron - Update Migration Poster ID (`cron.update_migration_post_id`)
|
||||
|
||||
- `SCHEDULE`: **@every 24h** : Interval as a duration between each synchronization, it will always attempt synchronization when the instance starts.
|
||||
|
||||
## Git (`git`)
|
||||
|
||||
- `PATH`: **""**: The path of git executable. If empty, Gitea searches through the PATH environment.
|
||||
- `MAX_GIT_DIFF_LINES`: **100**: Max number of lines allowed of a single file in diff view.
|
||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
||||
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
||||
- `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
|
||||
|
||||
## Git - Timeout settings (`git.timeout`)
|
||||
- `DEFAUlT`: **360**: Git operations default timeout seconds.
|
||||
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
||||
- `MIRROR`: **300**: Mirror external repositories timeout seconds.
|
||||
- `CLONE`: **300**: Git clone from internal repositories timeout seconds.
|
||||
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
|
||||
- `GC`: **60**: Git repository GC timeout seconds.
|
||||
|
||||
## Metrics (`metrics`)
|
||||
|
||||
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
||||
- `TOKEN`: **\<empty\>**: You need to specify the token, if you want to include in the authorization the metrics . The same token need to be used in prometheus parameters `bearer_token` or `bearer_token_file`.
|
||||
|
||||
## API (`api`)
|
||||
|
||||
- `ENABLE_SWAGGER`: **true**: Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
|
||||
- `MAX_RESPONSE_ITEMS`: **50**: Max number of items in a page.
|
||||
- `DEFAULT_PAGING_NUM`: **30**: Default paging number of API.
|
||||
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: Default and maximum number of items per page for git trees API.
|
||||
- `DEFAULT_MAX_BLOB_SIZE`: **10485760**: Default max size of a blob that can be return by the blobs API.
|
||||
|
||||
## OAuth2 (`oauth2`)
|
||||
|
||||
- `ENABLE`: **true**: Enables OAuth2 provider.
|
||||
- `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds
|
||||
- `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 access token in hours
|
||||
- `INVALIDATE_REFRESH_TOKEN`: **false**: Check if refresh token got already used
|
||||
- `JWT_SECRET`: **\<empty\>**: OAuth2 authentication secret for access and refresh tokens, change this a unique string.
|
||||
|
||||
## i18n (`i18n`)
|
||||
|
||||
- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR**: List of locales shown in language selector
|
||||
- `NAMES`: **English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어**: Visible names corresponding to the locales
|
||||
|
||||
### i18n - Datepicker Language (`i18n.datelang`)
|
||||
Maps locales to the languages used by the datepicker plugin
|
||||
|
||||
- `en-US`: **en**
|
||||
- `zh-CN`: **zh**
|
||||
- `zh-HK`: **zh-HK**
|
||||
- `zh-TW`: **zh-TW**
|
||||
- `de-DE`: **de**
|
||||
- `fr-FR`: **fr**
|
||||
- `nl-NL`: **nl**
|
||||
- `lv-LV`: **lv**
|
||||
- `ru-RU`: **ru**
|
||||
- `ja-JP`: **ja**
|
||||
- `es-ES`: **es**
|
||||
- `pt-BR`: **pt-BR**
|
||||
- `pl-PL`: **pl**
|
||||
- `bg-BG`: **bg**
|
||||
- `it-IT`: **it**
|
||||
- `fi-FI`: **fi**
|
||||
- `tr-TR`: **tr**
|
||||
- `cs-CZ`: **cs-CZ**
|
||||
- `sr-SP`: **sr**
|
||||
- `sv-SE`: **sv**
|
||||
- `ko-KR`: **ko**
|
||||
|
||||
## U2F (`U2F`)
|
||||
- `APP_ID`: **`ROOT_URL`**: Declares the facet of the application. Requires HTTPS.
|
||||
- `TRUSTED_FACETS`: List of additional facets which are trusted. This is not support by all browsers.
|
||||
|
||||
## Markup (`markup`)
|
||||
|
||||
Gitea can support Markup using external tools. The example below will add a markup named `asciidoc`.
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
- ENABLED: **false** Enable markup support; set to **true** to enable this renderer.
|
||||
- FILE\_EXTENSIONS: **\<empty\>** List of file extensions that should be rendered by an external
|
||||
command. Multiple extentions needs a comma as splitter.
|
||||
- RENDER\_COMMAND: External command to render all matching extensions.
|
||||
- IS\_INPUT\_FILE: **false** Input is not a standard input but a file param followed `RENDER_COMMAND`.
|
||||
|
||||
Two special environment variables are passed to the render command:
|
||||
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
|
||||
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
|
||||
|
||||
|
||||
Gitea supports customizing the sanitization policy for rendered HTML. The example below will support KaTeX output from pandoc.
|
||||
|
||||
```ini
|
||||
[markup.sanitizer]
|
||||
; Pandoc renders TeX segments as <span>s with the "math" class, optionally
|
||||
; with "inline" or "display" classes depending on context.
|
||||
ELEMENT = span
|
||||
ALLOW_ATTR = class
|
||||
REGEXP = ^\s*((math(\s+|$)|inline(\s+|$)|display(\s+|$)))+
|
||||
```
|
||||
|
||||
- `ELEMENT`: The element this policy applies to. Must be non-empty.
|
||||
- `ALLOW_ATTR`: The attribute this policy allows. Must be non-empty.
|
||||
- `REGEXP`: A regex to match the contents of the attribute against. Must be present but may be empty for unconditional whitelisting of this attribute.
|
||||
|
||||
You may redefine `ELEMENT`, `ALLOW_ATTR`, and `REGEXP` multiple times; each time all three are defined is a single policy entry.
|
||||
|
||||
## Time (`time`)
|
||||
|
||||
- `FORMAT`: Time format to diplay on UI. i.e. RFC1123 or 2006-01-02 15:04:05
|
||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia
|
||||
|
||||
## Task (`task`)
|
||||
|
||||
- Task queue configuration has been moved to `queue.task` however, the below configuration values are kept for backwards compatibilityx:
|
||||
- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`.
|
||||
- `QUEUE_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
- `QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If there redis needs a password, use `addrs=127.0.0.1:6379 password=123 db=0`.
|
||||
|
||||
## Migrations (`migrations`)
|
||||
|
||||
- `MAX_ATTEMPTS`: **3**: Max attempts per http/https request on migrations.
|
||||
- `RETRY_BACKOFF`: **3**: Backoff time per http/https request retry (seconds)
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
|
||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea version information in the footer.
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
@@ -1,284 +0,0 @@
|
||||
---
|
||||
date: "2016-12-26T16:00:00+02:00"
|
||||
title: "配置说明"
|
||||
slug: "config-cheat-sheet"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "配置说明"
|
||||
weight: 20
|
||||
identifier: "config-cheat-sheet"
|
||||
---
|
||||
|
||||
# 配置说明
|
||||
|
||||
这是针对Gitea配置文件的说明,你可以了解Gitea的强大配置。需要说明的是,你的所有改变请修改 `custom/conf/app.ini` 文件而不是源文件。所有默认值可以通过 [app.ini.sample](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample) 查看到。如果你发现 `%(X)s` 这样的内容,请查看 [ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。
|
||||
|
||||
## Overall (`DEFAULT`)
|
||||
|
||||
- `APP_NAME`: 应用名称,改成你希望的名字。
|
||||
- `RUN_USER`: 运行Gitea的用户,推荐使用 `git`;如果在你自己的个人电脑使用改成你自己的用户名。如果设置不正确,Gitea可能崩溃。
|
||||
- `RUN_MODE`: 从性能考虑,如果在产品级的服务上改成 `prod`。如果您使用安装向导安装的那么会自动设置为 `prod`。
|
||||
|
||||
## Repository (`repository`)
|
||||
|
||||
- `ROOT`: 存放git工程的根目录。这里必须填绝对路径,默认值是 `~/<username>/gitea-repositories`。
|
||||
- `SCRIPT_TYPE`: 服务器支持的Shell类型,通常是 `bash`,但有些服务器也有可能是 `sh`。
|
||||
- `ANSI_CHARSET`: 默认字符编码。
|
||||
- `FORCE_PRIVATE`: 强制所有git工程必须私有。
|
||||
- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private` 或 `public`。默认值是 `last`表示用户最后创建的Repo的选择。
|
||||
- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`: 小心:合并请求测试队列的长度,尽量放大。
|
||||
|
||||
## UI (`ui`)
|
||||
|
||||
- `EXPLORE_PAGING_NUM`: 探索页面每页显示的仓库数量。
|
||||
- `ISSUE_PAGING_NUM`: 工单页面每页显示的工单数量。
|
||||
- `MEMBERS_PAGING_NUM`: **20**: 组织成员页面每页显示的成员数量。
|
||||
- `FEED_MAX_COMMIT_NUM`: 活动流页面显示的最大提交数量。
|
||||
|
||||
### UI - Admin (`ui.admin`)
|
||||
|
||||
- `USER_PAGING_NUM`: 用户管理页面每页显示的用户数量。
|
||||
- `REPO_PAGING_NUM`: 仓库管理页面每页显示的仓库数量。
|
||||
- `NOTICE_PAGING_NUM`: 系统提示页面每页显示的提示数量。
|
||||
- `ORG_PAGING_NUM`: 组织管理页面每页显示的组织数量。
|
||||
|
||||
## Markdown (`markdown`)
|
||||
|
||||
- `ENABLE_HARD_LINE_BREAK`: 是否启用硬换行扩展。
|
||||
|
||||
## Server (`server`)
|
||||
|
||||
- `PROTOCOL`: 可选 `http` 或 `https`。
|
||||
- `DOMAIN`: 服务器域名。
|
||||
- `ROOT_URL`: Gitea服务器的对外 URL。
|
||||
- `HTTP_ADDR`: HTTP 监听地址。
|
||||
- `HTTP_PORT`: HTTP 监听端口。
|
||||
- `DISABLE_SSH`: 是否禁用SSH。
|
||||
- `START_SSH_SERVER`: 是否启用内部SSH服务器。
|
||||
- `SSH_PORT`: SSH端口,默认为 `22`。
|
||||
- `OFFLINE_MODE`: 针对静态和头像文件禁用 CDN。
|
||||
- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。
|
||||
- `CERT_FILE`: 启用HTTPS的证书文件。
|
||||
- `KEY_FILE`: 启用HTTPS的密钥文件。
|
||||
- `STATIC_ROOT_PATH`: 存放模板和静态文件的根目录,默认是 Gitea 的根目录。
|
||||
- `STATIC_CACHE_TIME`: **6h**: 静态资源文件,包括 `custom/`, `public/` 和所有上传的头像的浏览器缓存时间。
|
||||
- `ENABLE_GZIP`: 启用应用级别的 GZIP 压缩。
|
||||
- `LANDING_PAGE`: 未登录用户的默认页面,可选 `home` 或 `explore`。
|
||||
- `LFS_START_SERVER`: 是否启用 git-lfs 支持. 可以为 `true` 或 `false`, 默认是 `false`。
|
||||
- `LFS_CONTENT_PATH`: 存放 lfs 命令上传的文件的地方,默认是 `data/lfs`。
|
||||
- `LFS_JWT_SECRET`: LFS 认证密钥,改成自己的。
|
||||
|
||||
## Database (`database`)
|
||||
|
||||
- `DB_TYPE`: 数据库类型,可选 `mysql`, `postgres`, `mssql`, `tidb` 或 `sqlite3`。
|
||||
- `HOST`: 数据库服务器地址和端口。
|
||||
- `NAME`: 数据库名称。
|
||||
- `USER`: 数据库用户名。
|
||||
- `PASSWD`: 数据库用户密码。
|
||||
- `SSL_MODE`: MySQL 或 PostgreSQL数据库是否启用SSL模式。
|
||||
- `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。
|
||||
- `PATH`: Tidb 或者 SQLite3 数据文件存放路径。
|
||||
- `LOG_SQL`: **true**: 显示生成的SQL,默认为真。
|
||||
- `MAX_IDLE_CONNS` **0**: 最大空闲数据库连接
|
||||
- `CONN_MAX_LIFETIME` **3s**: 数据库连接最大存活时间
|
||||
|
||||
## Indexer (`indexer`)
|
||||
|
||||
- `ISSUE_INDEXER_TYPE`: **bleve**: 工单索引类型,当前支持 `bleve` 或 `db`,当为 `db` 时其它工单索引项可不用设置。
|
||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: 工单索引文件存放路径,当索引类型为 `bleve` 时有效。
|
||||
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: 工单索引队列类型,当前支持 `channel`, `levelqueue` 或 `redis`。
|
||||
- `ISSUE_INDEXER_QUEUE_DIR`: **indexers/issues.queue**: 当 `ISSUE_INDEXER_QUEUE_TYPE` 为 `levelqueue` 时,保存索引队列的磁盘路径。
|
||||
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: 当 `ISSUE_INDEXER_QUEUE_TYPE` 为 `redis` 时,保存Redis队列的连接字符串。
|
||||
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: 队列处理中批量提交数量。
|
||||
|
||||
- `REPO_INDEXER_ENABLED`: **false**: 是否启用代码搜索(启用后会占用比较大的磁盘空间)。
|
||||
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: 用于代码搜索的索引文件路径。
|
||||
- `UPDATE_BUFFER_LEN`: **20**: 代码索引请求的缓冲区长度。
|
||||
- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。
|
||||
|
||||
## Security (`security`)
|
||||
|
||||
- `INSTALL_LOCK`: 是否允许运行安装向导,(跟管理员账号有关,十分重要)。
|
||||
- `SECRET_KEY`: 全局服务器安全密钥 **最好改成你自己的** (当你运行安装向导的时候会被设置为一个随机值)。
|
||||
- `LOGIN_REMEMBER_DAYS`: Cookie 保存时间,单位天。
|
||||
- `COOKIE_USERNAME`: 保存用户名的 cookie 名称。
|
||||
- `COOKIE_REMEMBER_NAME`: 保存自动登录信息的 cookie 名称。
|
||||
- `REVERSE_PROXY_AUTHENTICATION_USER`: 反向代理认证的 HTTP 头名称。
|
||||
|
||||
## Service (`service`)
|
||||
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: 登录验证码失效时间,单位分钟。
|
||||
- `RESET_PASSWD_CODE_LIVE_MINUTES`: 重置密码失效时间,单位分钟。
|
||||
- `REGISTER_EMAIL_CONFIRM`: 启用注册邮件激活,前提是 `Mailer` 已经启用。
|
||||
- `DISABLE_REGISTRATION`: 禁用注册,启用后只能用管理员添加用户。
|
||||
- `SHOW_REGISTRATION_BUTTON`: 是否显示注册按钮。
|
||||
- `REQUIRE_SIGNIN_VIEW`: 是否所有页面都必须登录后才可访问。
|
||||
- `ENABLE_CACHE_AVATAR`: 是否缓存来自 Gravatar 的头像。
|
||||
- `ENABLE_NOTIFY_MAIL`: 是否发送工单创建等提醒邮件,需要 `Mailer` 被激活。
|
||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: 允许反向代理认证,更多细节见:https://github.com/gogits/gogs/issues/165
|
||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: 允许通过反向认证做自动注册。
|
||||
- `ENABLE_CAPTCHA`: 注册时使用图片验证码。
|
||||
|
||||
## Webhook (`webhook`)
|
||||
|
||||
- `QUEUE_LENGTH`: 说明: Hook 任务队列长度。
|
||||
- `DELIVER_TIMEOUT`: 请求webhooks的超时时间,单位秒。
|
||||
- `SKIP_TLS_VERIFY`: 是否允许不安全的证书。
|
||||
- `PAGING_NUM`: 每页显示的Webhook 历史数量。
|
||||
- `PROXY_URL`: ****: 代理服务器网址,支持 http://, https//, socks://, 为空将使用环境变量中的 http_proxy/https_proxy 设置。
|
||||
- `PROXY_HOSTS`: ****: 逗号分隔的需要代理的域名或IP地址。支持 * 号匹配符,使用 ** 匹配所有域名和IP地址。
|
||||
|
||||
## Mailer (`mailer`)
|
||||
|
||||
- `ENABLED`: 是否启用邮件服务。
|
||||
- `DISABLE_HELO`: 禁用 HELO 命令。
|
||||
- `HELO_HOSTNAME`: 自定义主机名来回应 HELO 命令。
|
||||
- `HOST`: SMTP 主机地址和端口 (例如:smtp.gitea.io:587)。
|
||||
- `FROM`: 邮件发送地址,RFC 5322. 这里可以填一个邮件地址或者 "Name" \<email@example.com\> 格式。
|
||||
- `USER`: 用户名(通常就是邮件地址)。
|
||||
- `PASSWD`: 密码。
|
||||
- `SKIP_VERIFY`: 忽略证书验证。
|
||||
|
||||
说明:实际上 Gitea 仅仅支持基于 STARTTLS 的 SMTP。
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ADAPTER`: **memory**: 缓存引擎,可以为 `memory`, `redis` 或 `memcache`。
|
||||
- `INTERVAL`: **60**: 只对内存缓存有效,GC间隔,单位秒。
|
||||
- `HOST`: **\<empty\>**: 针对redis和memcache有效,主机地址和端口。
|
||||
- Redis: `network=tcp,addr=127.0.0.1:6379,password=macaron,db=0,pool_size=100,idle_timeout=180`
|
||||
- Memache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
- `ITEM_TTL`: **16h**: 缓存项目失效时间,设置为 0 则禁用缓存。
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: Session 内容存储方式,可选 `memory`, `file`, `redis` 或 `mysql`。
|
||||
- `PROVIDER_CONFIG`: 如果是文件,那么这里填根目录;其他的要填主机地址和端口。
|
||||
- `COOKIE_SECURE`: 强制使用 HTTPS 作为session访问。
|
||||
- `GC_INTERVAL_TIME`: Session失效时间。
|
||||
|
||||
## Picture (`picture`)
|
||||
|
||||
- `GRAVATAR_SOURCE`: 头像来源,可以是 `gravatar`, `duoshuo` 或者类似 `http://cn.gravatar.com/avatar/` 的来源
|
||||
- `DISABLE_GRAVATAR`: 开启则只使用内部头像。
|
||||
- `ENABLE_FEDERATED_AVATAR`: 启用头像联盟支持 (参见 http://www.libravatar.org)
|
||||
|
||||
## Attachment (`attachment`)
|
||||
|
||||
- `ENABLED`: 是否允许用户上传附件。
|
||||
- `PATH`: 附件存储路径
|
||||
- `ALLOWED_TYPES`: 允许上传的附件类型。比如:`image/jpeg|image/png`,用 `*/*` 表示允许任何类型。
|
||||
- `MAX_SIZE`: 附件最大限制,单位 MB,比如: `4`。
|
||||
- `MAX_FILES`: 一次最多上传的附件数量,比如: `5`。
|
||||
|
||||
关于 `ALLOWED_TYPES`, 在 (*)unix 系统中可以使用`file -I <filename>` 来快速获得对应的 `MIME type`。
|
||||
|
||||
```shell
|
||||
$ file -I test00.tar.xz
|
||||
test00.tar.xz: application/x-xz; charset=binary
|
||||
|
||||
$ file --mime test00.xlsx
|
||||
test00.xlsx: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary
|
||||
|
||||
file -I test01.xls
|
||||
test01.xls: application/vnd.ms-excel; charset=binary
|
||||
```
|
||||
|
||||
|
||||
## Log (`log`)
|
||||
|
||||
- `ROOT_PATH`: 日志文件根目录。
|
||||
- `MODE`: 日志记录模式,默认是为 `console`。如果要写到多个通道,用逗号分隔
|
||||
- `LEVEL`: 日志级别,默认为`Trace`。
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
- `ENABLED`: 是否在后台运行定期任务。
|
||||
- `RUN_AT_START`: 是否启动时自动运行。
|
||||
|
||||
### Cron - Update Mirrors (`cron.update_mirrors`)
|
||||
|
||||
- `SCHEDULE`: 自动同步镜像仓库的Cron语法,比如:`@every 1h`。
|
||||
|
||||
### Cron - Repository Health Check (`cron.repo_health_check`)
|
||||
|
||||
- `SCHEDULE`: 仓库健康监测的Cron语法,比如:`@every 24h`。
|
||||
- `TIMEOUT`: 仓库健康监测的超时时间,比如:`60s`.
|
||||
- `ARGS`: 执行 `git fsck` 命令的参数,比如:`--unreachable --tags`。
|
||||
|
||||
### Cron - Repository Statistics Check (`cron.check_repo_stats`)
|
||||
|
||||
- `RUN_AT_START`: 是否启动时自动运行仓库统计。
|
||||
- `SCHEDULE`: 仓库统计时的Cron 语法,比如:`@every 24h`.
|
||||
|
||||
### Cron - Update Migration Poster ID (`cron.update_migration_post_id`)
|
||||
|
||||
- `SCHEDULE`: **@every 24h** : 每次同步的间隔时间。此任务总是在启动时自动进行。
|
||||
|
||||
## Git (`git`)
|
||||
|
||||
- `MAX_GIT_DIFF_LINES`: 比较视图中,一个文件最多显示行数。
|
||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: 比较视图中一行最大字符数。
|
||||
- `MAX_GIT_DIFF_FILES`: 比较视图中的最大现实文件数目。
|
||||
- `GC_ARGS`: 执行 `git gc` 命令的参数, 比如: `--aggressive --auto`。
|
||||
|
||||
## Git - 超时设置 (`git.timeout`)
|
||||
|
||||
- `DEFAUlT`: **360**: Git操作默认超时时间,单位秒
|
||||
- `MIGRATE`: **600**: 迁移外部仓库时的超时时间,单位秒
|
||||
- `MIRROR`: **300**: 镜像外部仓库的超时时间,单位秒
|
||||
- `CLONE`: **300**: 内部仓库间克隆的超时时间,单位秒
|
||||
- `PULL`: **300**: 内部仓库间拉取的超时时间,单位秒
|
||||
- `GC`: **60**: git仓库GC的超时时间,单位秒
|
||||
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: 是否根据 Git Wire Protocol协议支持情况自动切换版本,当 git 版本在 2.18 及以上时会自动切换到版本2。为 `false` 则不切换。
|
||||
|
||||
## API (`api`)
|
||||
|
||||
- `ENABLE_SWAGGER`: **true**: 是否启用swagger路由 /api/swagger, /api/v1/swagger etc. endpoints. True 或 false; 默认是 true.
|
||||
- `MAX_RESPONSE_ITEMS`: **50**: 一个页面最大的项目数。
|
||||
- `DEFAULT_PAGING_NUM`: **30**: API中默认分页条数。
|
||||
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: GIT TREES API每页的默认最大项数.
|
||||
- `DEFAULT_MAX_BLOB_SIZE`: **10485760**: BLOBS API默认最大大小.
|
||||
|
||||
## Markup (`markup`)
|
||||
|
||||
外部渲染工具支持,你可以用你熟悉的文档渲染工具. 比如一下将新增一个名字为 `asciidoc` 的渲染工具which is followed `markup.` ini section. And there are some config items below.
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = false
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
- ENABLED: 是否启用,默认为false。
|
||||
- FILE_EXTENSIONS: 关联的文档的扩展名,多个扩展名用都好分隔。
|
||||
- RENDER_COMMAND: 工具的命令行命令及参数。
|
||||
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。
|
||||
|
||||
## Time (`time`)
|
||||
|
||||
- `FORMAT`: 显示在界面上的时间格式。比如: RFC1123 或者 2006-01-02 15:04:05
|
||||
- `DEFAULT_UI_LOCATION`: 默认显示在界面上的时区,默认为本地时区。比如: Asia/Shanghai
|
||||
|
||||
## Task (`task`)
|
||||
|
||||
- `QUEUE_TYPE`: **channel**: 任务队列类型,可以为 `channel` 或 `redis`。
|
||||
- `QUEUE_LENGTH`: **1000**: 任务队列长度,当 `QUEUE_TYPE` 为 `channel` 时有效。
|
||||
- `QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: 任务队列连接字符串,当 `QUEUE_TYPE` 为 `redis` 时有效。如果redis有密码,则可以 `addrs=127.0.0.1:6379 password=123 db=0`。
|
||||
|
||||
## Migrations (`migrations`)
|
||||
|
||||
- `MAX_ATTEMPTS`: **3**: 在迁移过程中的 http/https 请求重试次数。
|
||||
- `RETRY_BACKOFF`: **3**: 等待下一次重试的时间,单位秒。
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
|
||||
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user