mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-10 04:21:48 +02:00
Compare commits
60 Commits
v1.11.0-rc
...
v1.7.3
Author | SHA1 | Date | |
---|---|---|---|
|
8ab107c2dd | ||
|
cbfc7f52b9 | ||
|
d602ba564f | ||
|
55063f2524 | ||
|
585dd13cce | ||
|
12d883412f | ||
|
597a30b727 | ||
|
b5ae8945e5 | ||
|
5cca840bb8 | ||
|
f4c7e87fc9 | ||
|
fe99c9901d | ||
|
2e1540e827 | ||
|
3b612ce42e | ||
|
1d8e56e6bb | ||
|
57ab65d922 | ||
|
3ac4a7fab8 | ||
|
253efbcb51 | ||
|
c8f061e15b | ||
|
7f7c451de4 | ||
|
b0b574f805 | ||
|
d269179523 | ||
|
6416f06508 | ||
|
1a8ab63dda | ||
|
477b4de0d1 | ||
|
849c85a2ec | ||
|
731275247d | ||
|
022634aa75 | ||
|
dfad569e40 | ||
|
c3b67ff2f6 | ||
|
5c30817b5f | ||
|
438848a2ca | ||
|
9d4aa78113 | ||
|
e5af93af20 | ||
|
3f802a2846 | ||
|
0190d3c243 | ||
|
4fe1a3050e | ||
|
29799537a7 | ||
|
d3a334d99a | ||
|
28d9305ea3 | ||
|
8a9f5b3b50 | ||
|
f28e17473c | ||
|
2c26521579 | ||
|
f635041c98 | ||
|
3fa49f3780 | ||
|
4577cddd28 | ||
|
8da5237107 | ||
|
8006b1bc7a | ||
|
8d400320c6 | ||
|
e9c4609410 | ||
|
176a6048b4 | ||
|
483aa06b07 | ||
|
551dc58a4d | ||
|
41a2bfe3ae | ||
|
652e09fc3e | ||
|
c9b57a5135 | ||
|
2904d8d6aa | ||
|
109fc7975b | ||
|
3ee3a4b595 | ||
|
14e218cbd1 | ||
|
b5f4911afa |
@@ -1,44 +1,44 @@
|
||||
repo: go-gitea/gitea
|
||||
groups:
|
||||
-
|
||||
-
|
||||
name: BREAKING
|
||||
labels:
|
||||
- kind/breaking
|
||||
-
|
||||
-
|
||||
name: FEATURE
|
||||
labels:
|
||||
- kind/feature
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- kind/security
|
||||
-
|
||||
name: BUGFIXES
|
||||
labels:
|
||||
- kind/bug
|
||||
-
|
||||
-
|
||||
name: ENHANCEMENT
|
||||
labels:
|
||||
- kind/enhancement
|
||||
- kind/refactor
|
||||
- kind/ui
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- kind/security
|
||||
-
|
||||
name: TESTING
|
||||
labels:
|
||||
- kind/testing
|
||||
-
|
||||
-
|
||||
name: TRANSLATION
|
||||
labels:
|
||||
- kind/translation
|
||||
-
|
||||
-
|
||||
name: BUILD
|
||||
labels:
|
||||
- kind/build
|
||||
- kind/lint
|
||||
-
|
||||
-
|
||||
name: DOCS
|
||||
labels:
|
||||
- kind/docs
|
||||
-
|
||||
-
|
||||
name: MISC
|
||||
default: true
|
||||
default: true
|
1075
.drone.yml
1075
.drone.yml
File diff suppressed because it is too large
Load Diff
@@ -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,17 @@ indent_size = 8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.less]
|
||||
[*.{less}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml,json}]
|
||||
[*.{yml}]
|
||||
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
|
6
.github/issue_template.md
vendored
6
.github/issue_template.md
vendored
@@ -1,9 +1,7 @@
|
||||
<!-- 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 maintainers can speak and write.
|
||||
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 Discord
|
||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
||||
server (https://discord.gg/NsatcWJ) 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.
|
||||
|
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@@ -42,7 +42,6 @@ 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
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@@ -12,7 +12,6 @@ _test
|
||||
|
||||
# MS VSCode
|
||||
.vscode
|
||||
__debug_bin
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
@@ -52,23 +51,18 @@ coverage.all
|
||||
/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/
|
||||
@@ -78,4 +72,3 @@ 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
|
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
|
1600
CHANGELOG.md
1600
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
132
CONTRIBUTING.md
132
CONTRIBUTING.md
@@ -11,9 +11,7 @@
|
||||
- [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)
|
||||
- [Sign-off your work](#sign-off-your-work)
|
||||
- [Release Cycle](#release-cycle)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Owners](#owners)
|
||||
@@ -66,33 +64,20 @@ 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 continuous testing, following [these
|
||||
instructions](http://docs.drone.io/cli-installation/). After that,
|
||||
you can simply call `drone exec --local --build-event "pull_request"` 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).
|
||||
managing updates via [dep](https://github.com/golang/dep).
|
||||
|
||||
Pull requests should only include `vendor/` updates if they are part of
|
||||
the same change, be it a bugfix or a feature addition.
|
||||
@@ -101,7 +86,7 @@ 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).
|
||||
You can find more information on how to get started with it on the [dep project website](https://golang.github.io/dep/docs/introduction.html).
|
||||
|
||||
## Translation
|
||||
|
||||
@@ -115,15 +100,13 @@ 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.
|
||||
An exception are the tools to build the CSS 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 CSS: Install [Node.js](https://nodejs.org/en/download/package-manager)
|
||||
with `npm` and then run `npm install` and `make generate-stylesheets`.
|
||||
- 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/)
|
||||
|
||||
## Code review
|
||||
|
||||
Changes to Gitea must be reviewed before they are accepted—no matter who
|
||||
@@ -163,74 +146,22 @@ import (
|
||||
)
|
||||
```
|
||||
|
||||
## Design guideline
|
||||
## Sign-off 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-off your
|
||||
commit automatically with `git commit -s`.
|
||||
|
||||
## Release Cycle
|
||||
|
||||
@@ -272,7 +203,7 @@ 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.
|
||||
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/
|
||||
|
||||
@@ -316,12 +247,7 @@ they served:
|
||||
* 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>
|
||||
* [Matti Ranta](https://github.com/techknowlogick) <matti@mdranta.net>
|
||||
|
||||
## Versions
|
||||
|
||||
@@ -344,10 +270,10 @@ be reviewed by two maintainers and must pass the automatic tests.
|
||||
* 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`.
|
||||
* 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.
|
||||
* Send PR to [blog repository](https://github.com/go-gitea/blog) announcing the release.
|
||||
|
||||
## Copyright
|
||||
|
||||
|
13
Dockerfile
13
Dockerfile
@@ -1,17 +1,14 @@
|
||||
|
||||
###################################
|
||||
#Build stage
|
||||
FROM golang:1.13-alpine3.11 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
FROM golang:1.11-alpine3.8 AS build-env
|
||||
|
||||
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
|
||||
RUN apk --no-cache add build-base git
|
||||
|
||||
#Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
@@ -19,9 +16,9 @@ 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
|
||||
&& make clean generate build
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.8
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 22 3000
|
||||
@@ -59,6 +56,6 @@ VOLUME ["/data"]
|
||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker/root /
|
||||
COPY docker /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
RUN ln -s /app/gitea/gitea /usr/local/bin/gitea
|
||||
|
1224
Gopkg.lock
generated
Normal file
1224
Gopkg.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
122
Gopkg.toml
Normal file
122
Gopkg.toml
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
ignored = ["google.golang.org/appengine*"]
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
non-go = true
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "code.gitea.io/git"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "code.gitea.io/sdk"
|
||||
|
||||
[[constraint]]
|
||||
# branch = "master"
|
||||
revision = "c74e08f039e56cef576e4336382b2a2d12d9e026"
|
||||
name = "github.com/blevesearch/bleve"
|
||||
#Not targetting v0.7.0 since standard where use only just after this tag
|
||||
|
||||
[[constraint]]
|
||||
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
|
||||
[[constraint]]
|
||||
revision = "2bf8f2a19ec09c670e931282edfe6567f6be21c9"
|
||||
name = "golang.org/x/text"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-xorm/xorm"
|
||||
revision = "1cd2662be938bfee0e34af92fe448513e0560fb1"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-xorm/builder"
|
||||
version = "0.3.3"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/mattn/go-sqlite3"
|
||||
revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/gorilla/mux"
|
||||
revision = "757bef944d0f21880861c2dd9c871ca543023cba"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/context"
|
||||
version = "1.1.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/lafriks/xormstore"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/lunny/dingtalk_webhook"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/markbates/goth"
|
||||
version = "1.47.2"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/mcuadros/go-version"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/russross/blackfriday"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/tstranex/u2f"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/editorconfig/editorconfig-core-go.v1"
|
||||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/gomail.v2"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/ini.v1"
|
||||
version = "1.31.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/ldap.v3"
|
||||
version = "3.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/macaron.v1"
|
||||
version = "1.2.4"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/testfixtures.v2"
|
||||
version = "2.0.0"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/boltdb/bolt"
|
||||
revision = "ccd680d8c1a0179ac3d68f692b01e1a1589cbfc7"
|
||||
source = "github.com/go-gitea/bolt"
|
||||
|
||||
[[override]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
version = "0.9.0"
|
12
MAINTAINERS
12
MAINTAINERS
@@ -19,20 +19,10 @@ 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)
|
||||
Matti Ranta <matti@mdranta.net> (@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)
|
||||
|
382
Makefile
382
Makefile
@@ -1,80 +1,55 @@
|
||||
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
|
||||
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
|
||||
endif
|
||||
|
||||
BINDATA := modules/{options,public,templates}/bindata.go
|
||||
GOFILES := $(shell find . -name "*.go" -type f ! -path "./vendor/*" ! -path "*/bindata.go")
|
||||
GOFMT ?= gofmt -s
|
||||
|
||||
GOFLAGS := -v
|
||||
GOFLAGS := -i -v
|
||||
EXTRA_GOFLAGS ?=
|
||||
|
||||
MAKE_VERSION := $(shell $(MAKE) -v | head -n 1)
|
||||
|
||||
ifneq ($(DRONE_TAG),)
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
GITEA_VERSION ?= $(VERSION)
|
||||
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//')
|
||||
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)"
|
||||
LDFLAGS := -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
|
||||
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
|
||||
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\'
|
||||
SWAGGER_SPEC_S_TMPL := s|"basePath":\s*"/api/v1"|"basePath": "{{AppSubUrl}}/api/v1"|g
|
||||
SWAGGER_SPEC_S_JSON := s|"basePath":\s*"{{AppSubUrl}}/api/v1"|"basePath": "/api/v1"|g
|
||||
|
||||
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
|
||||
@@ -84,6 +59,12 @@ TEST_MSSQL_DBNAME ?= gitea
|
||||
TEST_MSSQL_USERNAME ?= sa
|
||||
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
EXECUTABLE := gitea.exe
|
||||
else
|
||||
EXECUTABLE := gitea
|
||||
endif
|
||||
|
||||
# $(call strip-suffix,filename)
|
||||
strip-suffix = $(firstword $(subst ., ,$(1)))
|
||||
|
||||
@@ -92,61 +73,14 @@ 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: git-check
|
||||
git-check:
|
||||
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
||||
echo "Gitea requires git with lfs support to run tests." ; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: node-check
|
||||
node-check:
|
||||
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?' | tr '.' ' ');))
|
||||
$(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) \
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) \
|
||||
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
|
||||
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ integrations/gitea-integration-mssql/ \
|
||||
integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite integrations/indexers-mssql \
|
||||
integrations/mysql.ini integrations/pgsql.ini integrations/mssql.ini
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
@@ -157,14 +91,19 @@ vet:
|
||||
$(GO) vet $(PACKAGES)
|
||||
|
||||
.PHONY: generate
|
||||
generate: js css
|
||||
GO111MODULE=on $(GO) generate -mod=vendor $(PACKAGES)
|
||||
generate:
|
||||
@hash go-bindata > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/jteeuwen/go-bindata/go-bindata; \
|
||||
fi
|
||||
$(GO) generate $(PACKAGES)
|
||||
|
||||
.PHONY: generate-swagger
|
||||
generate-swagger:
|
||||
$(SWAGGER) generate spec -o './$(SWAGGER_SPEC)'
|
||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
|
||||
fi
|
||||
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
|
||||
@@ -177,8 +116,11 @@ swagger-check: generate-swagger
|
||||
|
||||
.PHONY: swagger-validate
|
||||
swagger-validate:
|
||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
|
||||
fi
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
|
||||
$(SWAGGER) validate './$(SWAGGER_SPEC)'
|
||||
swagger validate './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: errcheck
|
||||
@@ -190,10 +132,6 @@ errcheck:
|
||||
|
||||
.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; \
|
||||
fi
|
||||
@@ -204,7 +142,7 @@ 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)
|
||||
misspell -error -i unknwon $(GOFILES)
|
||||
|
||||
.PHONY: misspell
|
||||
misspell:
|
||||
@@ -225,11 +163,7 @@ fmt-check:
|
||||
|
||||
.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)
|
||||
$(GO) test -tags='sqlite sqlite_unlock_notify' $(PACKAGES)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
@@ -240,11 +174,14 @@ coverage:
|
||||
|
||||
.PHONY: unit-test-coverage
|
||||
unit-test-coverage:
|
||||
GO111MODULE=on $(GO) test -mod=vendor -tags='sqlite sqlite_unlock_notify' -cover -coverprofile coverage.out $(PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||
for PKG in $(PACKAGES); do $(GO) test -tags='sqlite sqlite_unlock_notify' -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
|
||||
.PHONY: vendor
|
||||
vendor:
|
||||
GO111MODULE=on $(GO) mod tidy && GO111MODULE=on $(GO) mod vendor
|
||||
@hash dep > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u github.com/golang/dep/cmd/dep; \
|
||||
fi
|
||||
dep ensure -vendor-only
|
||||
|
||||
.PHONY: test-vendor
|
||||
test-vendor: vendor
|
||||
@@ -254,157 +191,66 @@ test-vendor: vendor
|
||||
echo "$${diff}"; \
|
||||
exit 1; \
|
||||
fi;
|
||||
#TODO add dep status -missing when implemented
|
||||
|
||||
.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:
|
||||
generate-ini:
|
||||
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
|
||||
|
||||
.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
|
||||
|
||||
.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-mysql
|
||||
test-mysql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.test
|
||||
|
||||
.PHONY: test-pgsql
|
||||
test-pgsql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test
|
||||
|
||||
.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
|
||||
|
||||
test-mssql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.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 .
|
||||
bench-mysql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.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 .
|
||||
bench-pgsql: integrations.test generate-ini
|
||||
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||
|
||||
|
||||
.PHONY: integration-test-coverage
|
||||
integration-test-coverage: integrations.cover.test generate-ini-mysql
|
||||
integration-test-coverage: integrations.cover.test generate-ini
|
||||
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.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -o integrations.test
|
||||
|
||||
integrations.mysql8.test: $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -o integrations.mysql8.test
|
||||
integrations.sqlite.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
|
||||
|
||||
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: git-check $(GO_SOURCES)
|
||||
GO111MODULE=on $(GO) test -mod=vendor -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
||||
|
||||
.PHONY: migrations.mysql.test
|
||||
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'
|
||||
integrations.cover.test: $(SOURCES)
|
||||
$(GO) test -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
||||
|
||||
.PHONY: check
|
||||
check: test
|
||||
@@ -414,13 +260,13 @@ install: $(wildcard *.go)
|
||||
$(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 $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
.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-compress release-check
|
||||
|
||||
.PHONY: release-dirs
|
||||
release-dirs:
|
||||
@@ -429,87 +275,68 @@ 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;
|
||||
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
|
||||
|
||||
.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)/binaries/$(EXECUTABLE)-*),gxz -k -9 $(notdir $(file));)
|
||||
|
||||
.PHONY: javascripts
|
||||
javascripts:
|
||||
echo "'make javascripts' is deprecated, please use 'make js'"
|
||||
$(MAKE) js
|
||||
javascripts: public/js/index.js
|
||||
|
||||
.IGNORE: public/js/index.js
|
||||
public/js/index.js: $(JAVASCRIPTS)
|
||||
cat $< >| $@
|
||||
|
||||
.PHONY: stylesheets-check
|
||||
stylesheets-check:
|
||||
echo "'make stylesheets-check' is deprecated, please use 'make css'"
|
||||
$(MAKE) css
|
||||
stylesheets-check: generate-stylesheets
|
||||
@diff=$$(git diff public/css/*); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make generate-stylesheets' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
exit 1; \
|
||||
fi;
|
||||
|
||||
.PHONY: generate-stylesheets
|
||||
generate-stylesheets:
|
||||
echo "'make generate-stylesheets' is deprecated, please use 'make css'"
|
||||
$(MAKE) css
|
||||
node_modules/.bin/lessc --clean-css public/less/index.less public/css/index.css
|
||||
$(foreach file, $(filter-out public/less/themes/_base.less, $(wildcard public/less/themes/*)),node_modules/.bin/lessc --clean-css public/less/themes/$(notdir $(file)) > public/css/theme-$(notdir $(call strip-suffix,$(file))).css;)
|
||||
|
||||
.PHONY: swagger-ui
|
||||
swagger-ui:
|
||||
@@ -546,25 +373,12 @@ generate-images:
|
||||
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
|
||||
zopflipng $(TMPDIR)/images/128-raw.png $(TMPDIR)/images/128.png
|
||||
zopflipng $(TMPDIR)/images/64-raw.png $(TMPDIR)/images/64.png
|
||||
zopflipng $(TMPDIR)/images/32-raw.png $(TMPDIR)/images/32.png
|
||||
zopflipng $(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
|
||||
|
19
README.md
19
README.md
@@ -1,6 +1,6 @@
|
||||
[简体中文](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)
|
||||
@@ -10,9 +10,7 @@
|
||||
[](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://opencollective.com/gitea)
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -31,7 +29,7 @@ This project has been
|
||||
|
||||
From the root of the source tree, run:
|
||||
|
||||
TAGS="bindata" make build
|
||||
TAGS="bindata" make generate all
|
||||
|
||||
More info: https://docs.gitea.io/en-us/install-from-source/
|
||||
|
||||
@@ -105,8 +103,9 @@ for the full license text.
|
||||
## Screenshots
|
||||
Looking for an overview of the interface? Check it out!
|
||||
|
||||
||||
|
||||
| | | |
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
24
README_ZH.md
24
README_ZH.md
@@ -1,18 +1,15 @@
|
||||
[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://discord.gg/NsatcWJ)
|
||||
[](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://opencollective.com/gitea)
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -28,7 +25,7 @@ Gitea 的首要目标是创建一个极易安装,运行非常快速,安装
|
||||
|
||||
## 文档
|
||||
|
||||
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/gitea) 和 QQ群 328432459 来和我们交流。
|
||||
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/NsatcWJ) 和 QQ群 328432459 来和我们交流。
|
||||
|
||||
## 贡献流程
|
||||
|
||||
@@ -46,8 +43,9 @@ Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## 截图
|
||||
|
||||
||||
|
||||
| | | |
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|
167
cmd/admin.go
167
cmd/admin.go
@@ -11,12 +11,11 @@ import (
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth/oauth2"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
"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"
|
||||
@@ -43,10 +42,6 @@ var (
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Username. DEPRECATED: use username instead",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username",
|
||||
Usage: "Username",
|
||||
},
|
||||
cli.StringFlag{
|
||||
@@ -61,23 +56,24 @@ var (
|
||||
Name: "admin",
|
||||
Usage: "User is an admin",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
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)",
|
||||
Usage: "Force the user to change his/her password after initial login",
|
||||
},
|
||||
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",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -96,6 +92,11 @@ var (
|
||||
Value: "",
|
||||
Usage: "New password to set for user",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -118,12 +119,26 @@ var (
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
microcmdRegenKeys = cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
subcmdAuth = cli.Command{
|
||||
@@ -132,10 +147,6 @@ var (
|
||||
Subcommands: []cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
cmdAuthAddLdapBindDn,
|
||||
cmdAuthUpdateLdapBindDn,
|
||||
cmdAuthAddLdapSimpleAuth,
|
||||
cmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthList,
|
||||
microcmdAuthDelete,
|
||||
},
|
||||
@@ -145,21 +156,40 @@ var (
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
idFlag = cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
Usage: "ID of OAuth authentication source",
|
||||
}
|
||||
|
||||
microcmdAuthDelete = cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
idFlag,
|
||||
},
|
||||
}
|
||||
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
@@ -232,12 +262,14 @@ func runChangePassword(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -247,7 +279,6 @@ func runChangePassword(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
user.HashPassword(c.String("password"))
|
||||
|
||||
if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -257,47 +288,38 @@ func runChangePassword(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runCreateUser(c *cli.Context) error {
|
||||
if err := argsSet(c, "email"); err != nil {
|
||||
if err := argsSet(c, "name", "email"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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("password") && c.IsSet("random-password") {
|
||||
return errors.New("cannot set both -random-password and -password flags")
|
||||
}
|
||||
|
||||
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"))
|
||||
password, err = generate.GetRandomString(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")
|
||||
}
|
||||
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// always default to true
|
||||
var changePassword = true
|
||||
|
||||
@@ -311,34 +333,18 @@ func runCreateUser(c *cli.Context) error {
|
||||
changePassword = c.Bool("must-change-password")
|
||||
}
|
||||
|
||||
u := &models.User{
|
||||
Name: username,
|
||||
if err := models.CreateUser(&models.User{
|
||||
Name: c.String("name"),
|
||||
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 {
|
||||
}); 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
|
||||
}
|
||||
|
||||
@@ -375,22 +381,19 @@ func runRepoSyncReleases(c *cli.Context) error {
|
||||
}
|
||||
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
||||
|
||||
if err = repository.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||
if err = models.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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,6 +410,10 @@ func getReleaseCount(id int64) (int64, error) {
|
||||
}
|
||||
|
||||
func runRegenerateHooks(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -414,6 +421,10 @@ func runRegenerateHooks(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runRegenerateKeys(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -442,6 +453,10 @@ func parseOAuth2Config(c *cli.Context) *models.OAuth2Config {
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -455,6 +470,10 @@ func runAddOauth(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
@@ -491,7 +510,7 @@ func runUpdateOauth(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
var customURLMapping = &oauth2.CustomURLMapping{}
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
@@ -522,6 +541,10 @@ func runUpdateOauth(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -534,9 +557,9 @@ func runListAuth(c *cli.Context) error {
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled")
|
||||
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)
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t", source.ID, source.Name, models.LoginNames[source.Type], source.IsActived)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
@@ -544,6 +567,10 @@ func runListAuth(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
@@ -1,366 +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.BoolFlag{
|
||||
Name: "allow-deactivate-all",
|
||||
Usage: "Allow empty search results to deactivate all users.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username-attribute",
|
||||
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
||||
},
|
||||
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")
|
||||
}
|
||||
if c.IsSet("allow-deactivate-all") {
|
||||
config.Source.AllowDeactivateAll = c.Bool("allow-deactivate-all")
|
||||
}
|
||||
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
21
cmd/cert.go
21
cmd/cert.go
@@ -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
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ func initDB() error {
|
||||
|
||||
func initDBDisableConsole(disableConsole bool) error {
|
||||
setting.NewContext()
|
||||
setting.InitDBConfig()
|
||||
models.LoadConfigs()
|
||||
|
||||
setting.NewXORMLogService(disableConsole)
|
||||
if err := models.SetEngine(); err != 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
|
||||
}
|
108
cmd/dump.go
108
cmd/dump.go
@@ -8,17 +8,17 @@ 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 +31,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 +48,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,107 +66,92 @@ 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-")
|
||||
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)
|
||||
}
|
||||
|
||||
reposDump := path.Join(tmpWorkDir, "gitea-repo.zip")
|
||||
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)
|
||||
}
|
||||
|
||||
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 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 com.IsExist(setting.LogRootPath) {
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
fatal("Failed to include log: %v", err)
|
||||
}
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
@@ -40,10 +40,9 @@ var (
|
||||
}
|
||||
|
||||
microcmdGenerateLfsJwtSecret = cli.Command{
|
||||
Name: "JWT_SECRET",
|
||||
Aliases: []string{"LFS_JWT_SECRET"},
|
||||
Usage: "Generate a new JWT_SECRET",
|
||||
Action: runGenerateLfsJwtSecret,
|
||||
Name: "LFS_JWT_SECRET",
|
||||
Usage: "Generate a new LFS_JWT_SECRET",
|
||||
Action: runGenerateLfsJwtSecret,
|
||||
}
|
||||
|
||||
microcmdGenerateSecretKey = cli.Command{
|
||||
@@ -64,7 +63,7 @@ func runGenerateInternalToken(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
JWTSecretBase64, err := generate.NewJwtSecret()
|
||||
JWTSecretBase64, err := generate.NewLfsJwtSecret()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
424
cmd/hook.go
424
cmd/hook.go
@@ -8,31 +8,33 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"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,
|
||||
@@ -60,141 +62,33 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type delayWriter struct {
|
||||
internal io.Writer
|
||||
buf *bytes.Buffer
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
func newDelayWriter(internal io.Writer, delay time.Duration) *delayWriter {
|
||||
timer := time.NewTimer(delay)
|
||||
return &delayWriter{
|
||||
internal: internal,
|
||||
buf: &bytes.Buffer{},
|
||||
timer: timer,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *delayWriter) Write(p []byte) (n int, err error) {
|
||||
if d.buf != nil {
|
||||
select {
|
||||
case <-d.timer.C:
|
||||
_, err := d.internal.Write(d.buf.Bytes())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
d.buf = nil
|
||||
return d.internal.Write(p)
|
||||
default:
|
||||
return d.buf.Write(p)
|
||||
}
|
||||
}
|
||||
return d.internal.Write(p)
|
||||
}
|
||||
|
||||
func (d *delayWriter) WriteString(s string) (n int, err error) {
|
||||
if d.buf != nil {
|
||||
select {
|
||||
case <-d.timer.C:
|
||||
_, err := d.internal.Write(d.buf.Bytes())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
d.buf = nil
|
||||
return d.internal.Write([]byte(s))
|
||||
default:
|
||||
return d.buf.WriteString(s)
|
||||
}
|
||||
}
|
||||
return d.internal.Write([]byte(s))
|
||||
}
|
||||
|
||||
func (d *delayWriter) Close() error {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
stopped := d.timer.Stop()
|
||||
if stopped {
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-d.timer.C:
|
||||
default:
|
||||
}
|
||||
if d.buf == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := d.internal.Write(d.buf.Bytes())
|
||||
d.buf = nil
|
||||
return err
|
||||
}
|
||||
|
||||
type nilWriter struct{}
|
||||
|
||||
func (n *nilWriter) Write(p []byte) (int, error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (n *nilWriter) WriteString(s string) (int, error) {
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
func runHookPreReceive(c *cli.Context) error {
|
||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
setup("hooks/pre-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
|
||||
}
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
setup("hooks/pre-receive.log")
|
||||
|
||||
// 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))
|
||||
|
||||
hookOptions := private.HookOptions{
|
||||
UserID: userID,
|
||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||
ProtectedBranchID: prID,
|
||||
IsDeployKey: isDeployKey,
|
||||
}
|
||||
userIDStr := os.Getenv(models.EnvPusherID)
|
||||
repoPath := models.RepoPath(username, reponame)
|
||||
|
||||
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
|
||||
|
||||
var out io.Writer
|
||||
out = &nilWriter{}
|
||||
if setting.Git.VerbosePush {
|
||||
if setting.Git.VerbosePushDelay > 0 {
|
||||
dWriter := newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
||||
defer dWriter.Close()
|
||||
out = dWriter
|
||||
} else {
|
||||
out = os.Stdout
|
||||
}
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
buf.Write(scanner.Bytes())
|
||||
buf.WriteByte('\n')
|
||||
|
||||
// TODO: support news feeds for wiki
|
||||
if isWiki {
|
||||
continue
|
||||
@@ -208,127 +102,85 @@ 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(out, "*")
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
||||
if err != nil {
|
||||
fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
|
||||
}
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||
|
||||
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
|
||||
if protectBranch != nil && protectBranch.IsProtected() {
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
}
|
||||
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect force push: %v", err)
|
||||
} else if len(output) > 0 {
|
||||
fail(fmt.Sprintf("branch %s is protected from force push", branchName), "")
|
||||
}
|
||||
}
|
||||
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(out, ".")
|
||||
}
|
||||
if lastline >= hookBatchSize {
|
||||
fmt.Fprintf(out, "\n")
|
||||
lastline = 0
|
||||
}
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(out, " Checking %d branches\n", count)
|
||||
|
||||
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(out, "\n")
|
||||
lastline = 0
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "Checked %d references in total\n", total)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
// Update is empty and is kept only for backwards compatibility
|
||||
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")
|
||||
}
|
||||
|
||||
setup("hooks/update.log")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookPostReceive(c *cli.Context) error {
|
||||
if os.Getenv(models.EnvIsInternal) == "true" {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
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
|
||||
}
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
setting.CustomConf = c.GlobalString("config")
|
||||
}
|
||||
|
||||
var out io.Writer
|
||||
var dWriter *delayWriter
|
||||
out = &nilWriter{}
|
||||
if setting.Git.VerbosePush {
|
||||
if setting.Git.VerbosePushDelay > 0 {
|
||||
dWriter = newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
||||
defer dWriter.Close()
|
||||
out = dWriter
|
||||
} else {
|
||||
out = os.Stdout
|
||||
}
|
||||
}
|
||||
setup("hooks/post-receive.log")
|
||||
|
||||
// the environment setted on serv command
|
||||
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
|
||||
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)
|
||||
|
||||
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
|
||||
@@ -339,93 +191,63 @@ Gitea or set your environment appropriately.`, "")
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, ".")
|
||||
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++
|
||||
oldCommitID := string(fields[0])
|
||||
newCommitID := string(fields[1])
|
||||
refFullName := string(fields[2])
|
||||
|
||||
if count >= hookBatchSize {
|
||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
count = 0
|
||||
if err := private.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 == 0 {
|
||||
if wasEmpty && masterPushed {
|
||||
// We need to tell the repo to reset the default branch to master
|
||||
err := private.SetDefaultBranch(repoUser, repoName, "master")
|
||||
if newCommitID != git.EmptySHA && strings.HasPrefix(refFullName, git.BranchPrefix) {
|
||||
branch := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
repo, pullRequestAllowed, err := private.GetRepository(repoID)
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||
log.GitLogger.Error(2, "get repo: %v", err)
|
||||
break
|
||||
}
|
||||
if !pullRequestAllowed {
|
||||
break
|
||||
}
|
||||
|
||||
baseRepo := repo
|
||||
if repo.IsFork {
|
||||
baseRepo = repo.BaseRepo
|
||||
}
|
||||
|
||||
if !repo.IsFork && branch == baseRepo.DefaultBranch {
|
||||
break
|
||||
}
|
||||
|
||||
pr, err := private.ActivePullRequest(baseRepo.ID, repo.ID, baseRepo.DefaultBranch, branch)
|
||||
if err != nil {
|
||||
log.GitLogger.Error(2, "get active pr: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if pr == nil {
|
||||
if repo.IsFork {
|
||||
branch = fmt.Sprintf("%s:%s", repo.OwnerName, branch)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
|
||||
fmt.Fprintf(os.Stderr, " %s/compare/%s...%s\n", baseRepo.HTMLURL(), url.QueryEscape(baseRepo.DefaultBranch), url.QueryEscape(branch))
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s/pulls/%d\n", baseRepo.HTMLURL(), pr.Index)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
}
|
||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
return nil
|
||||
}
|
||||
|
||||
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
||||
hookOptions.NewCommitIDs = newCommitIDs[:count]
|
||||
hookOptions.RefFullNames = refFullNames[:count]
|
||||
|
||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||
|
||||
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
|
||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
_ = dWriter.Close()
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
20
cmd/keys.go
20
cmd/keys.go
@@ -9,7 +9,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@@ -40,10 +41,19 @@ var CmdKeys = cli.Command{
|
||||
Value: "",
|
||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runKeys(c *cli.Context) error {
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("No username provided")
|
||||
}
|
||||
@@ -62,12 +72,14 @@ func runKeys(c *cli.Context) error {
|
||||
return errors.New("No key type and content provided")
|
||||
}
|
||||
|
||||
setup("keys.log", false)
|
||||
if err := initDBDisableConsole(true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authorizedString, err := private.AuthorizedPublicKeyByContent(content)
|
||||
publicKey, err := models.SearchPublicKeyByContent(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(strings.TrimSpace(authorizedString))
|
||||
fmt.Println(publicKey.AuthorizedString())
|
||||
return nil
|
||||
}
|
||||
|
@@ -5,8 +5,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -21,9 +19,20 @@ var CmdMigrate = cli.Command{
|
||||
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,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runMigrate(ctx *cli.Context) error {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -32,10 +41,10 @@ func runMigrate(ctx *cli.Context) error {
|
||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||
log.Trace("Custom path: %s", setting.CustomPath)
|
||||
log.Trace("Log path: %s", setting.LogRootPath)
|
||||
setting.InitDBConfig()
|
||||
models.LoadConfigs()
|
||||
|
||||
if err := models.NewEngine(context.Background(), migrations.Migrate); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
if err := models.NewEngine(migrations.Migrate); err != nil {
|
||||
log.Fatal(4, "Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
230
cmd/serv.go
230
cmd/serv.go
@@ -8,26 +8,27 @@ package cmd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"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"
|
||||
version "github.com/mcuadros/go-version"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
accessDenied = "Repository does not exist or you do not have access"
|
||||
lfsAuthenticateVerb = "git-lfs-authenticate"
|
||||
)
|
||||
|
||||
@@ -38,23 +39,41 @@ var CmdServ = cli.Command{
|
||||
Description: `Serv provide access auth for repositories`,
|
||||
Action: runServ,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "enable-pprof",
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: "custom/conf/app.ini",
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Name: "enable-pprof",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func setup(logPath string, debug bool) {
|
||||
if !debug {
|
||||
_ = log.DelLogger("console")
|
||||
func checkLFSVersion() {
|
||||
if setting.LFS.StartServer {
|
||||
//Disable LFS client hooks if installed for the current OS user
|
||||
//Needs at least git v2.1.2
|
||||
binVersion, err := git.BinVersion()
|
||||
if err != nil {
|
||||
fail(fmt.Sprintf("Error retrieving git version: %v", err), fmt.Sprintf("Error retrieving git version: %v", err))
|
||||
}
|
||||
|
||||
if !version.Compare(binVersion, "2.1.2", ">=") {
|
||||
setting.LFS.StartServer = false
|
||||
println("LFS server support needs at least Git v2.1.2, disabled")
|
||||
} else {
|
||||
git.GlobalCommandArgs = append(git.GlobalCommandArgs, "-c", "filter.lfs.required=",
|
||||
"-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setup(logPath string) {
|
||||
log.DelLogger("console")
|
||||
setting.NewContext()
|
||||
if debug {
|
||||
setting.ProdMode = false
|
||||
}
|
||||
checkLFSVersion()
|
||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||
}
|
||||
|
||||
func parseCmd(cmd string) (string, string) {
|
||||
@@ -81,14 +100,19 @@ 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")
|
||||
}
|
||||
setup("serv.log")
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
println("Gitea: SSH has been disabled")
|
||||
@@ -96,29 +120,13 @@ 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)
|
||||
}
|
||||
cli.ShowSubcommandHelp(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -152,19 +160,41 @@ func runServ(c *cli.Context) error {
|
||||
fail("Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
||||
}
|
||||
|
||||
stopCPUProfiler, err := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "Unable to start CPU profile: %v", err)
|
||||
}
|
||||
stopCPUProfiler := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||
defer func() {
|
||||
stopCPUProfiler()
|
||||
err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
fail("Internal Server Error", "Unable to dump Mem Profile: %v", err)
|
||||
}
|
||||
pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||
}()
|
||||
}
|
||||
|
||||
var (
|
||||
isWiki bool
|
||||
unitType = models.UnitTypeCode
|
||||
unitName = "code"
|
||||
)
|
||||
if strings.HasSuffix(reponame, ".wiki") {
|
||||
isWiki = true
|
||||
unitType = models.UnitTypeWiki
|
||||
unitName = "wiki"
|
||||
reponame = reponame[:len(reponame)-5]
|
||||
}
|
||||
|
||||
os.Setenv(models.EnvRepoUsername, username)
|
||||
if isWiki {
|
||||
os.Setenv(models.EnvRepoIsWiki, "true")
|
||||
} else {
|
||||
os.Setenv(models.EnvRepoIsWiki, "false")
|
||||
}
|
||||
os.Setenv(models.EnvRepoName, reponame)
|
||||
|
||||
repo, err := private.GetRepositoryByOwnerAndName(username, reponame)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Failed to get repository: repository does not exist") {
|
||||
fail(accessDenied, "Repository does not exist: %s/%s", username, reponame)
|
||||
}
|
||||
fail("Internal error", "Failed to get repository: %v", err)
|
||||
}
|
||||
|
||||
requestedMode, has := allowedCommands[verb]
|
||||
if !has {
|
||||
fail("Unknown git command", "Unknown git command %s", verb)
|
||||
@@ -180,39 +210,97 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
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 || setting.Service.RequireSignInView {
|
||||
keys := strings.Split(c.Args()[0], "-")
|
||||
if len(keys) != 2 {
|
||||
fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
}
|
||||
|
||||
key, err := private.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 {
|
||||
// Now we have to get the deploy key for this repo
|
||||
deployKey, err := private.GetDeployKey(key.ID, repo.ID)
|
||||
if err != nil {
|
||||
fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
if deployKey == nil {
|
||||
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
if deployKey.Mode < requestedMode {
|
||||
fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
|
||||
}
|
||||
|
||||
// Update deploy key activity.
|
||||
if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
|
||||
fail("Internal error", "UpdateDeployKey: %v", err)
|
||||
}
|
||||
|
||||
// FIXME: Deploy keys aren't really the owner of the repo pushing changes
|
||||
// however we don't have good way of representing deploy keys in hook.go
|
||||
// so for now use the owner
|
||||
os.Setenv(models.EnvPusherName, username)
|
||||
os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
|
||||
} else {
|
||||
user, err = private.GetUserByKeyID(key.ID)
|
||||
if err != nil {
|
||||
fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
|
||||
}
|
||||
|
||||
if !user.IsActive || user.ProhibitLogin {
|
||||
fail("Your account is not active or has been disabled by Administrator",
|
||||
"User %s is disabled and have no access to repository %s",
|
||||
user.Name, repoPath)
|
||||
}
|
||||
|
||||
mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
|
||||
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's "+unitName,
|
||||
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, username, repo.Name)
|
||||
|
||||
now := time.Now()
|
||||
claims := jwt.MapClaims{
|
||||
"repo": results.RepoID,
|
||||
"repo": repo.ID,
|
||||
"op": lfsVerb,
|
||||
"exp": now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
|
||||
"nbf": now.Unix(),
|
||||
"user": results.UserID,
|
||||
}
|
||||
if user != nil {
|
||||
claims["user"] = user.ID
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
@@ -233,6 +321,7 @@ func runServ(c *cli.Context) error {
|
||||
if err != nil {
|
||||
fail("Internal error", "Failed to encode LFS json response: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -248,6 +337,13 @@ func runServ(c *cli.Context) error {
|
||||
} else {
|
||||
gitcmd = exec.Command(verb, repoPath)
|
||||
}
|
||||
if isWiki {
|
||||
if err = private.InitWiki(repo.ID); err != nil {
|
||||
fail("Internal error", "Failed to init wiki repo: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
os.Setenv(models.ProtectedBranchRepoID, fmt.Sprintf("%d", repo.ID))
|
||||
|
||||
gitcmd.Dir = setting.RepoRootPath
|
||||
gitcmd.Stdout = os.Stdout
|
||||
@@ -258,9 +354,9 @@ 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 {
|
||||
if err = private.UpdatePublicKeyUpdated(keyID); err != nil {
|
||||
fail("Internal error", "UpdatePublicKey: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
95
cmd/web.go
95
cmd/web.go
@@ -5,21 +5,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
context2 "github.com/gorilla/context"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
ini "gopkg.in/ini.v1"
|
||||
@@ -38,6 +40,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",
|
||||
@@ -59,10 +66,10 @@ func runHTTPRedirector() {
|
||||
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
|
||||
})
|
||||
|
||||
var err = runHTTP("tcp", source, context2.ClearHandler(handler))
|
||||
var err = runHTTP(source, context2.ClearHandler(handler))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Failed to start port redirection: %v", err)
|
||||
log.Fatal(4, "Failed to start port redirection: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,13 +82,19 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
|
||||
}
|
||||
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)))
|
||||
var err = http.ListenAndServe(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||
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 start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||
}
|
||||
}()
|
||||
return runHTTPSWithTLSConfig("tcp", listenAddr, certManager.TLSConfig(), context2.ClearHandler(m))
|
||||
server := &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
TLSConfig: &tls.Config{
|
||||
GetCertificate: certManager.GetCertificate,
|
||||
},
|
||||
}
|
||||
return server.ListenAndServeTLS("", "")
|
||||
}
|
||||
|
||||
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -97,25 +110,18 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
external.RegisterParsers()
|
||||
|
||||
// Set up Macaron
|
||||
m := routes.NewMacaron()
|
||||
routes.RegisterRoutes(m)
|
||||
|
||||
@@ -127,7 +133,6 @@ func runWeb(ctx *cli.Context) error {
|
||||
switch setting.Protocol {
|
||||
case setting.UnixSocket:
|
||||
case setting.FCGI:
|
||||
case setting.FCGIUnix:
|
||||
default:
|
||||
// Save LOCAL_ROOT_URL if port changed
|
||||
cfg := ini.Empty()
|
||||
@@ -155,7 +160,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
listenAddr := setting.HTTPAddr
|
||||
if setting.Protocol != setting.UnixSocket && setting.Protocol != setting.FCGIUnix {
|
||||
if setting.Protocol != setting.UnixSocket {
|
||||
listenAddr += ":" + setting.HTTPPort
|
||||
}
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||
@@ -174,8 +179,7 @@ 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))
|
||||
@@ -183,29 +187,38 @@ func runWeb(ctx *cli.Context) error {
|
||||
}
|
||||
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))
|
||||
listener, err := net.Listen("tcp", listenAddr)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to bind %s", listenAddr, err)
|
||||
}
|
||||
defer listener.Close()
|
||||
err = fcgi.Serve(listener, 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,38 @@ 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)
|
||||
}
|
@@ -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,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)
|
||||
}
|
||||
}
|
@@ -2,42 +2,10 @@
|
||||
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
|
||||
##
|
||||
###
|
||||
#After=mysqld.service
|
||||
#After=postgresql.service
|
||||
#After=memcached.service
|
||||
#After=redis.service
|
||||
|
||||
[Service]
|
||||
# Modify these two values and uncomment them if you have
|
||||
@@ -51,18 +19,14 @@ 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
|
||||
ExecStart=/usr/local/bin/gitea web -c /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
|
||||
# If you want to bind Gitea to a port below 1024 uncomment
|
||||
# the two values below
|
||||
###
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
#AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
###
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
@@ -1,4 +1,3 @@
|
||||
|
||||
; 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.
|
||||
@@ -32,16 +31,8 @@ PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||
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
|
||||
@@ -72,73 +63,6 @@ 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
|
||||
@@ -161,17 +85,6 @@ MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
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
|
||||
@@ -195,9 +108,8 @@ 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.
|
||||
; 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 the extensions with a comma. To render files without any extension as markdown, just put a comma
|
||||
@@ -208,8 +120,6 @@ FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
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
|
||||
@@ -275,9 +185,8 @@ DISABLE_ROUTER_LOG = false
|
||||
; not forget to export the private key):
|
||||
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
|
||||
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
||||
; Paths are relative to CUSTOM_PATH
|
||||
CERT_FILE = https/cert.pem
|
||||
KEY_FILE = https/key.pem
|
||||
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 =
|
||||
@@ -291,8 +200,7 @@ ENABLE_GZIP = false
|
||||
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, can be "home", "explore", or "organizations"
|
||||
LANDING_PAGE = home
|
||||
; Enables git-lfs support. true or false, default is false.
|
||||
LFS_START_SERVER = false
|
||||
@@ -302,17 +210,6 @@ LFS_CONTENT_PATH = data/lfs
|
||||
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]
|
||||
@@ -332,9 +229,6 @@ 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
|
||||
@@ -343,91 +237,25 @@ SQLITE_TIMEOUT = 500
|
||||
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)
|
||||
; How long to remember that an user is logged in before requiring relogin (in days)
|
||||
LOGIN_REMEMBER_DAYS = 7
|
||||
COOKIE_USERNAME = gitea_awesome
|
||||
COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
@@ -440,16 +268,6 @@ MIN_PASSWORD_LENGTH = 6
|
||||
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]
|
||||
;
|
||||
@@ -503,10 +321,6 @@ ALLOW_ONLY_EXTERNAL_REGISTRATION = false
|
||||
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
|
||||
@@ -519,27 +333,15 @@ CAPTCHA_TYPE = image
|
||||
; 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
|
||||
@@ -553,18 +355,7 @@ 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
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
|
||||
[webhook]
|
||||
; Hook task queue length, increase if webhook shooting starts hanging
|
||||
@@ -575,17 +366,13 @@ DELIVER_TIMEOUT = 5
|
||||
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 =
|
||||
; Name displayed in mail title
|
||||
SUBJECT = %(APP_NAME)s
|
||||
; Mail server
|
||||
; Gmail: smtp.gmail.com:587
|
||||
; QQ: smtp.qq.com:465
|
||||
@@ -611,8 +398,8 @@ USER =
|
||||
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
|
||||
; Enable sendmail (override SMTP)
|
||||
USE_SENDMAIL = false
|
||||
; Specify an alternative sendmail binary
|
||||
SENDMAIL_PATH = sendmail
|
||||
; Specify any extra sendmail arguments
|
||||
@@ -653,18 +440,10 @@ 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.
|
||||
; 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
|
||||
@@ -692,9 +471,6 @@ MAX_FILES = 5
|
||||
; 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 =
|
||||
@@ -703,37 +479,16 @@ ROOT_PATH =
|
||||
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
|
||||
LEVEL = Trace
|
||||
|
||||
; 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
|
||||
@@ -744,10 +499,6 @@ MAX_SIZE_SHIFT = 28
|
||||
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]
|
||||
@@ -775,6 +526,14 @@ 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
|
||||
@@ -819,14 +578,7 @@ SCHEDULE = @every 24h
|
||||
; 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
|
||||
@@ -838,12 +590,9 @@ 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
|
||||
@@ -861,24 +610,6 @@ MIN_INTERVAL = 10m
|
||||
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
|
||||
@@ -910,12 +641,11 @@ 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/
|
||||
APP_ID = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
; Comma seperated list of truisted facets
|
||||
TRUSTED_FACETS = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
|
||||
; Extension mapping to highlight class
|
||||
; e.g. .toml=ini
|
||||
@@ -928,12 +658,6 @@ 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
|
||||
@@ -948,18 +672,3 @@ IS_INPUT_FILE = 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
|
||||
|
3
docker/Makefile
vendored
3
docker/Makefile
vendored
@@ -4,6 +4,7 @@ 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) .
|
||||
@@ -11,4 +12,4 @@ docker:
|
||||
|
||||
.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
|
||||
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
|
||||
|
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
|
46
docker/etc/s6/gitea/setup
Executable file
46
docker/etc/s6/gitea/setup
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/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
|
||||
|
||||
# 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"} \
|
||||
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 > /data/gitea/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
|
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,9 @@ ChallengeResponseAuthentication no
|
||||
PasswordAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
|
||||
AllowUsers ${USER}
|
||||
AllowUsers git
|
||||
|
||||
Banner none
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
|
||||
AcceptEnv GIT_PROTOCOL
|
||||
AcceptEnv GIT_PROTOCOL
|
@@ -17,8 +17,6 @@ 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]
|
||||
@@ -37,7 +35,6 @@ 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
|
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,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/*
|
@@ -3,14 +3,8 @@
|
||||
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}`"
|
||||
# switch sshd config to different user
|
||||
sed -i -e "s/AllowUsers git$/AllowUsers ${USER}/g" /etc/ssh/sshd_config
|
||||
fi
|
||||
|
||||
## Change GID for USER?
|
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
public/
|
||||
templates/swagger/v1_json.tmpl
|
||||
themes/
|
||||
resources/
|
||||
|
@@ -1,16 +1,20 @@
|
||||
# Gitea: Docs
|
||||
|
||||
[](https://discord.gg/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")
|
||||
|
||||
## Hosting
|
||||
|
||||
These pages are hosted using [netlifycms](https://www.netlifycms.org/) and get
|
||||
This page is hosted on our infrastructure within Docker containers, it gets
|
||||
automatically updated on every push to the `master` branch.
|
||||
|
||||
If you want to host this page on your own you can take our docker image
|
||||
[gitea/docs](https://hub.docker.com/r/gitea/docs/).
|
||||
|
||||
## Install
|
||||
|
||||
These pages use the [Hugo](https://gohugo.io/) static site generator.
|
||||
This pages uses the [Hugo](https://github.com/spf13/hugo) static site generator.
|
||||
If you are planning to contribute you'll want to download and install Hugo on
|
||||
your local machine.
|
||||
|
||||
|
@@ -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;
|
||||
}
|
@@ -6,7 +6,6 @@ theme: gitea
|
||||
defaultContentLanguage: en-us
|
||||
defaultContentLanguageInSubdir: true
|
||||
enableMissingTranslationPlaceholders: true
|
||||
enableEmoji: true
|
||||
|
||||
permalinks:
|
||||
post: /:year/:month/:title/
|
||||
@@ -18,13 +17,6 @@ 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:
|
||||
|
@@ -17,7 +17,7 @@ menu:
|
||||
|
||||
## Enabling/configuring API access
|
||||
|
||||
By default, `ENABLE_SWAGGER` is true, and
|
||||
By default, `ENABLE_SWAGGER_ENDPOINT` 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.
|
||||
@@ -31,26 +31,18 @@ Gitea supports these methods of API authentication:
|
||||
- `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
|
||||
All of these methods accept the same apiKey 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:
|
||||
You can create an apiKey token via your gitea install'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:
|
||||
the apiKey token in an authorization header, like this:
|
||||
|
||||
```
|
||||
Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675
|
||||
@@ -68,14 +60,6 @@ curl -X POST "http://localhost:4000/api/v1/repos/test1/test1/issues" \
|
||||
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
|
||||
@@ -90,12 +74,6 @@ $ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api
|
||||
[{"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.
|
||||
|
@@ -17,7 +17,7 @@ menu:
|
||||
|
||||
## 开启/配置 API 访问
|
||||
|
||||
通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat
|
||||
通常情况下, `ENABLE_SWAGGER_ENDPOINT` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat
|
||||
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) 中获取更多配置相关信息。
|
||||
|
||||
## 通过 API 认证
|
||||
|
@@ -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)
|
@@ -15,8 +15,8 @@ menu:
|
||||
|
||||
# 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.
|
||||
This is a cheat sheet for the Gitea configuration file. It contains most settings
|
||||
that can 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
|
||||
@@ -44,7 +44,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
|
||||
- `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`,
|
||||
- `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.
|
||||
@@ -62,75 +62,18 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
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`)
|
||||
|
||||
@@ -142,28 +85,18 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
## 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\]
|
||||
- `PROTOCOL`: **http**: \[http, https, 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.
|
||||
- If `PROTOCOL` is set to `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.
|
||||
@@ -177,16 +110,14 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `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`: **https/cert.pem**: Cert file path used for HTTPS. From 1.11 paths are relative to `CUSTOM_PATH`.
|
||||
- `KEY_FILE`: **https/key.pem**: Key file path used for HTTPS. From 1.11 paths are relative to `CUSTOM_PATH`.
|
||||
- `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\].
|
||||
- `LANDING_PAGE`: **home**: Landing page for unauthenticated users \[home, explore\].
|
||||
- `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.
|
||||
@@ -198,68 +129,25 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
- `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).
|
||||
- `HOST`: **127.0.0.1:3306**: Database host address and port.
|
||||
- `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_ENABLED`: **false**: Enables code search (uses a lot of disk space).
|
||||
- `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`)
|
||||
|
||||
@@ -275,18 +163,7 @@ relation to port exhaustion.
|
||||
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`)
|
||||
|
||||
@@ -306,42 +183,22 @@ relation to port exhaustion.
|
||||
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.
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default.
|
||||
- `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`)
|
||||
|
||||
@@ -349,8 +206,6 @@ relation to port exhaustion.
|
||||
- `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`)
|
||||
|
||||
@@ -364,15 +219,10 @@ relation to port exhaustion.
|
||||
- `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.
|
||||
- `USE_SENDMAIL`: **false** 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`.
|
||||
`FROM` and `SENDMAIL_PATH`.
|
||||
- `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.
|
||||
@@ -383,12 +233,11 @@ relation to port exhaustion.
|
||||
- `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.
|
||||
- Memache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, mysql, couchbase, memcache, nodb, postgres\].
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, mysql\].
|
||||
- `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.
|
||||
@@ -401,16 +250,7 @@ relation to port exhaustion.
|
||||
- `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.
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store local and cached files.
|
||||
|
||||
## Attachment (`attachment`)
|
||||
|
||||
@@ -424,64 +264,8 @@ relation to port exhaustion.
|
||||
## 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**
|
||||
- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values.
|
||||
- `LEVEL`: **Trace**: General log level. \[Trace, Debug, Info, Warn, Error, Critical\]
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
@@ -510,23 +294,14 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
|
||||
- `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
|
||||
- `VERBOSE_PUSH`: **true**: Print status information about pushes as they are being processed.
|
||||
- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.
|
||||
|
||||
## Git - Timeout settings (`git.timeout`)
|
||||
- `DEFAUlT`: **360**: Git operations default timeout seconds.
|
||||
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
||||
- `MIRROR`: **300**: Mirror external repositories timeout seconds.
|
||||
- `CLONE`: **300**: Git clone from internal repositories timeout seconds.
|
||||
@@ -535,24 +310,13 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
|
||||
|
||||
## Metrics (`metrics`)
|
||||
|
||||
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
||||
- `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.
|
||||
- `ENABLE_SWAGGER_ENDPOINT`: **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`)
|
||||
|
||||
@@ -594,13 +358,13 @@ Gitea can support Markup using external tools. The example below will add a mark
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = true
|
||||
ENABLED = false
|
||||
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.
|
||||
- ENABLED: **false** Enable markup support.
|
||||
- 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.
|
||||
@@ -610,41 +374,6 @@ 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.
|
||||
|
@@ -37,8 +37,7 @@ menu:
|
||||
|
||||
- `EXPLORE_PAGING_NUM`: 探索页面每页显示的仓库数量。
|
||||
- `ISSUE_PAGING_NUM`: 工单页面每页显示的工单数量。
|
||||
- `MEMBERS_PAGING_NUM`: **20**: 组织成员页面每页显示的成员数量。
|
||||
- `FEED_MAX_COMMIT_NUM`: 活动流页面显示的最大提交数量。
|
||||
- `FEED_MAX_COMMIT_NUM`: 活动流页面显示的最大提交树木。
|
||||
|
||||
### UI - Admin (`ui.admin`)
|
||||
|
||||
@@ -66,7 +65,6 @@ menu:
|
||||
- `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`。
|
||||
@@ -80,26 +78,9 @@ menu:
|
||||
- `NAME`: 数据库名称。
|
||||
- `USER`: 数据库用户名。
|
||||
- `PASSWD`: 数据库用户密码。
|
||||
- `SSL_MODE`: MySQL 或 PostgreSQL数据库是否启用SSL模式。
|
||||
- `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。
|
||||
- `SSL_MODE`: PostgreSQL数据库是否启用SSL模式。
|
||||
- `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`)
|
||||
|
||||
@@ -112,7 +93,7 @@ menu:
|
||||
|
||||
## Service (`service`)
|
||||
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: 登录验证码失效时间,单位分钟。
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: 登陆验证码失效时间,单位分钟。
|
||||
- `RESET_PASSWD_CODE_LIVE_MINUTES`: 重置密码失效时间,单位分钟。
|
||||
- `REGISTER_EMAIL_CONFIRM`: 启用注册邮件激活,前提是 `Mailer` 已经启用。
|
||||
- `DISABLE_REGISTRATION`: 禁用注册,启用后只能用管理员添加用户。
|
||||
@@ -130,8 +111,6 @@ menu:
|
||||
- `DELIVER_TIMEOUT`: 请求webhooks的超时时间,单位秒。
|
||||
- `SKIP_TLS_VERIFY`: 是否允许不安全的证书。
|
||||
- `PAGING_NUM`: 每页显示的Webhook 历史数量。
|
||||
- `PROXY_URL`: ****: 代理服务器网址,支持 http://, https//, socks://, 为空将使用环境变量中的 http_proxy/https_proxy 设置。
|
||||
- `PROXY_HOSTS`: ****: 逗号分隔的需要代理的域名或IP地址。支持 * 号匹配符,使用 ** 匹配所有域名和IP地址。
|
||||
|
||||
## Mailer (`mailer`)
|
||||
|
||||
@@ -148,12 +127,11 @@ menu:
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ADAPTER`: **memory**: 缓存引擎,可以为 `memory`, `redis` 或 `memcache`。
|
||||
- `INTERVAL`: **60**: 只对内存缓存有效,GC间隔,单位秒。
|
||||
- `HOST`: **\<empty\>**: 针对redis和memcache有效,主机地址和端口。
|
||||
- `ADAPTER`: 缓存引擎,可以为 `memory`, `redis` 或 `memcache`。
|
||||
- `INTERVAL`: 只对内存缓存有效,GC间隔,单位秒。
|
||||
- `HOST`: 针对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`)
|
||||
|
||||
@@ -176,20 +154,6 @@ menu:
|
||||
- `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`: 日志文件根目录。
|
||||
@@ -214,11 +178,7 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
||||
### 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** : 每次同步的间隔时间。此任务总是在启动时自动进行。
|
||||
- `SCHEDULE`: 藏亏统计时的Cron 语法,比如:`@every 24h`.
|
||||
|
||||
## Git (`git`)
|
||||
|
||||
@@ -228,24 +188,13 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
||||
- `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`)
|
||||
## markup (`markup`)
|
||||
|
||||
外部渲染工具支持,你可以用你熟悉的文档渲染工具. 比如一下将新增一个名字为 `asciidoc` 的渲染工具which is followed `markup.` ini section. And there are some config items below.
|
||||
|
||||
@@ -262,21 +211,7 @@ IS_INPUT_FILE = false
|
||||
- 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`)
|
||||
|
||||
|
@@ -15,28 +15,19 @@ menu:
|
||||
|
||||
# Customizing Gitea
|
||||
|
||||
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
||||
the `custom` folder from the running directory, but may be different if your build has
|
||||
set this differently. This is the central place to override configuration settings,
|
||||
templates, etc. You can check the `CustomPath` using `gitea help`. You can override
|
||||
the `CustomPath` by setting either the `GITEA_CUSTOM` environment variable or by
|
||||
using the `--custom-path` option on the `gitea` binary. (The option will override the
|
||||
environment variable.)
|
||||
Customizing Gitea is typically done using the `custom` folder. This is the central
|
||||
place to override configuration settings, templates, etc.
|
||||
|
||||
If Gitea is deployed from binary, all default paths will be relative to the Gitea
|
||||
If Gitea is deployed from binary, all default paths will be relative to the gitea
|
||||
binary. If installed from a distribution, these paths will likely be modified to
|
||||
the Linux Filesystem Standard. Gitea will attempt to create required folders, including
|
||||
`custom/`. Distributions may provide a symlink for `custom` using `/etc/gitea/`.
|
||||
|
||||
Application settings can be found in file `CustomConf` which is by default,
|
||||
`CustomPath/conf/app.ini` but may be different if your build has set this differently.
|
||||
Again `gitea help` will allow you review this variable and you can override it using the
|
||||
`--config` option on the `gitea` binary.
|
||||
the Linux Filesystem Standard. Gitea will create required folders, including `custom/`.
|
||||
Application settings are configured in `custom/conf/app.ini`. Distributions may
|
||||
provide a symlink for `custom` using `/etc/gitea/`.
|
||||
|
||||
- [Quick Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
||||
- [Complete List](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
|
||||
|
||||
If the `CustomPath` folder can't be found despite checking `gitea help`, check the `GITEA_CUSTOM`
|
||||
If the `custom` folder can't be found next to the binary, check the `GITEA_CUSTOM`
|
||||
environment variable; this can be used to override the default path to something else.
|
||||
`GITEA_CUSTOM` might, for example, be set by an init script.
|
||||
|
||||
@@ -44,6 +35,11 @@ environment variable; this can be used to override the default path to something
|
||||
|
||||
**Note:** Gitea must perform a full restart to see configuration changes.
|
||||
|
||||
## Customizing /robots.txt
|
||||
|
||||
To make Gitea serve a custom `/robots.txt` (default: empty 404), create a file called
|
||||
`robots.txt` in the `custom` folder with [expected contents](http://www.robotstxt.org/).
|
||||
|
||||
## Serving custom public files
|
||||
|
||||
To make Gitea serve custom public files (like pages and images), use the folder
|
||||
@@ -54,30 +50,24 @@ the url `http://gitea.domain.tld/image.png`.
|
||||
|
||||
## Changing the default avatar
|
||||
|
||||
Place the png image at the following path: `custom/public/img/avatar_default.png`
|
||||
Place the png image at the following path: `custom/public/img/avatar\_default.png`
|
||||
|
||||
## Customizing Gitea pages
|
||||
|
||||
The `custom/templates` folder allows changing every single page of Gitea. Templates
|
||||
to override can be found in the [`templates`](https://github.com/go-gitea/gitea/tree/master/templates) directory of Gitea source (Note: the example link is from `master` branch. Make sure to copy templates from same release you are using). Override by
|
||||
to override can be found in the `templates` directory of Gitea source. Override by
|
||||
making a copy of the file under `custom/templates` using a full path structure
|
||||
matching source.
|
||||
|
||||
Any statement contained inside `{{` and `}}` are Gitea's template syntax and
|
||||
shouldn't be touched without fully understanding these components.
|
||||
|
||||
### Customizing startpage / homepage
|
||||
|
||||
Copy [`home.tmpl`](https://github.com/go-gitea/gitea/blob/master/templates/home.tmpl) for your version of Gitea from `templates` to `custom/templates`.
|
||||
Edit as you wish.
|
||||
Dont forget to restart your gitea to apply the changes.
|
||||
|
||||
### Adding links and tabs
|
||||
|
||||
If all you want is to add extra links to the top navigation bar or footer, or extra tabs to the repository view, you can put them in `extra_links.tmpl` (links added to the navbar), `extra_links_footer.tmpl` (links added to the left side of footer), and `extra_tabs.tmpl` inside your `custom/templates/custom/` directory.
|
||||
If all you want is to add extra links to the top navigation bar, or extra tabs to the repository view, you can put them in `extra_links.tmpl` and `extra_tabs.tmpl` inside your `custom/templates/custom/` directory.
|
||||
|
||||
For instance, let's say you are in Germany and must add the famously legally-required "Impressum"/about page, listing who is responsible for the site's content:
|
||||
just place it under your "custom/public/" directory (for instance `custom/public/impressum.html`) and put a link to it in either `custom/templates/custom/extra_links.tmpl` or `custom/templates/custom/extra_links_footer.tmpl`.
|
||||
just place it under your "custom/public/" directory (for instance `custom/public/impressum.html`) and put a link to it in `custom/templates/custom/extra_links.tmpl`.
|
||||
|
||||
To match the current style, the link should have the class name "item", and you can use `{{AppSubUrl}}` to get the base URL:
|
||||
`<a class="item" href="{{AppSubUrl}}/impressum.html">Impressum</a>`
|
||||
@@ -98,20 +88,6 @@ Apart from `extra_links.tmpl` and `extra_tabs.tmpl`, there are other useful temp
|
||||
- `body_outer_post.tmpl`, before the bottom `<footer>` element.
|
||||
- `footer.tmpl`, right before the end of the `<body>` tag, a good place for additional Javascript.
|
||||
|
||||
## Customizing Gitea mails
|
||||
|
||||
The `custom/templates/mail` folder allows changing the body of every mail of Gitea.
|
||||
Templates to override can be found in the
|
||||
[`templates/mail`](https://github.com/go-gitea/gitea/tree/master/templates/mail)
|
||||
directory of Gitea source.
|
||||
Override by making a copy of the file under `custom/templates/mail` using a
|
||||
full path structure matching source.
|
||||
|
||||
Any statement contained inside `{{` and `}}` are Gitea's template
|
||||
syntax and shouldn't be touched without fully understanding these components.
|
||||
|
||||
|
||||
|
||||
## Adding Analytics to Gitea
|
||||
|
||||
Google Analytics, Matomo (previously Piwik), and other analytics services can be added to Gitea. To add the tracking code, refer to the `Other additions to the page` section of this document, and add the JavaScript to the `custom/templates/custom/header.tmpl` file.
|
||||
@@ -120,51 +96,6 @@ Google Analytics, Matomo (previously Piwik), and other analytics services can be
|
||||
|
||||
Place custom files in corresponding sub-folder under `custom/options`.
|
||||
|
||||
**NOTE:** The files should not have a file extension, e.g. `Labels` rather than `Labels.txt`
|
||||
|
||||
### gitignores
|
||||
|
||||
To add custom .gitignore, add a file with existing [.gitignore rules](https://git-scm.com/docs/gitignore) in it to `custom/options/gitignore`
|
||||
|
||||
### Labels
|
||||
|
||||
To add a custom label set, add a file that follows the [label format](https://github.com/go-gitea/gitea/blob/master/options/label/Default) to `custom/options/label`
|
||||
`#hex-color label name ; label description`
|
||||
|
||||
### Licenses
|
||||
|
||||
To add a custom license, add a file with the license text to `custom/options/license`
|
||||
|
||||
### Locales
|
||||
|
||||
Locales are managed via our [crowdin](https://crowdin.com/project/gitea).
|
||||
You can override a locale by placing an altered locale file in `custom/options/locale`.
|
||||
Gitea's default locale files can be found in the [`options/locale`](https://github.com/go-gitea/gitea/tree/master/options/locale) source folder and these should be used as examples for your changes.
|
||||
|
||||
To add a completely new locale, as well as placing the file in the above location, you will need to add the new lang and name to the `[i18n]` section in your `app.ini`. Keep in mind that Gitea will use those settings as **overrides**, so if you want to keep the other languages as well you will need to copy/paste the default values and add your own to them.
|
||||
|
||||
```
|
||||
[i18n]
|
||||
LANGS = en-US,foo-BAR
|
||||
NAMES = English,FooBar
|
||||
```
|
||||
|
||||
Locales may change between versions, so keeping track of your customized locales is highly encouraged.
|
||||
|
||||
### Readmes
|
||||
|
||||
To add a custom Readme, add a markdown formatted file (without an `.md` extension) to `custom/options/readme`
|
||||
|
||||
### Reactions
|
||||
|
||||
To change reaction emoji's you can set allowed reactions at app.ini
|
||||
```
|
||||
[ui]
|
||||
REACTIONS = +1, -1, laugh, confused, heart, hooray, eyes
|
||||
```
|
||||
A full list of supported emoji's is at [emoji list](https://gitea.com/gitea/gitea.com/issues/8)
|
||||
|
||||
## Customizing the look of Gitea
|
||||
|
||||
As of version 1.6.0 Gitea has built-in themes. The two built-in themes are, the default theme `gitea`, and a dark theme `arc-green`. To change the look of your Gitea install change the value of `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` to another one of the available options.
|
||||
As of version 1.8.0 Gitea also has per-user themes. The list of themes a user can choose from can be configured with the `THEMES` value in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` (defaults to `gitea` and `arc-green`, light and dark respectively)
|
||||
As of version 1.6.0 Gitea has built-in themes. The two built-in themes are, the default theme `gitea`, and a dark theme `arc-green`. To change the look of your Gitea install change the value of `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini` to another one of the available options.
|
||||
|
@@ -16,11 +16,10 @@ menu:
|
||||
# Custom files rendering configuration
|
||||
|
||||
Gitea supports custom file renderings (i.e., Jupyter notebooks, asciidoc, etc.) through external binaries,
|
||||
it is just a matter of:
|
||||
|
||||
it is just matter of:
|
||||
* installing external binaries
|
||||
* add some configuration to your `app.ini` file
|
||||
* restart your Gitea instance
|
||||
* restart your gitea instance
|
||||
|
||||
## Installing external binaries
|
||||
|
||||
@@ -28,13 +27,13 @@ In order to get file rendering through external binaries, their associated packa
|
||||
If you're using a Docker image, your `Dockerfile` should contain something along this lines:
|
||||
|
||||
```
|
||||
FROM gitea/gitea:{{< version >}}
|
||||
FROM gitea/gitea:1.6.0
|
||||
[...]
|
||||
|
||||
COPY custom/app.ini /data/gitea/conf/app.ini
|
||||
[...]
|
||||
|
||||
RUN apk --no-cache add asciidoctor freetype freetype-dev gcc g++ libpng python-dev py-pip python3-dev py3-pip py3-zmq
|
||||
RUN apk --no-cache add asciidoctor freetype freetype-dev gcc g++ libpng python-dev py-pip python3-dev py3-pip
|
||||
# install any other package you need for your external renderers
|
||||
|
||||
RUN pip3 install --upgrade pip
|
||||
@@ -51,7 +50,7 @@ add one `[markup.XXXXX]` section per external renderer on your custom `app.ini`:
|
||||
[markup.asciidoc]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoctor -e -a leveloffset=-1 --out-file=- -"
|
||||
RENDER_COMMAND = "asciidoctor --out-file=- -"
|
||||
; Input is not a standard input but a file
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
@@ -68,22 +67,4 @@ RENDER_COMMAND = rst2html.py
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
If your external markup relies on additional classes and attributes on the generated HTML elements, you might need to enable custom sanitizer policies. Gitea uses the [`bluemonday`](https://godoc.org/github.com/microcosm-cc/bluemonday) package as our HTML sanitizier. The example below will support [KaTeX](https://katex.org/) output from [`pandoc`](https://pandoc.org/).
|
||||
|
||||
```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+|$)))+
|
||||
|
||||
[markup.markdown]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .md,.markdown
|
||||
RENDER_COMMAND = pandoc -f markdown -t html --katex
|
||||
```
|
||||
|
||||
You may redefine `ELEMENT`, `ALLOW_ATTR`, and `REGEXP` multiple times; each time all three are defined is a single policy entry. All three must be defined, but `REGEXP` may be blank to allow unconditional whitelisting of that attribute.
|
||||
|
||||
Once your configuration changes have been made, restart Gitea to have changes take effect.
|
||||
|
@@ -15,279 +15,41 @@ menu:
|
||||
|
||||
# Hacking on Gitea
|
||||
|
||||
## Installing go and setting the GOPATH
|
||||
Familiarity with the existing [installation instructions](https://golang.org/doc/install)
|
||||
is required for this section.
|
||||
|
||||
You should [install go](https://golang.org/doc/install) and set up your go
|
||||
environment correctly. In particular, it is recommended to set the `$GOPATH`
|
||||
environment variable and to add the go bin directory or directories
|
||||
`${GOPATH//://bin:}/bin` to the `$PATH`. See the Go wiki entry for
|
||||
[GOPATH](https://github.com/golang/go/wiki/GOPATH).
|
||||
To contribute to Gitea, fork the project and work on the `master` branch.
|
||||
|
||||
Next, [install Node.js with npm](https://nodejs.org/en/download/) which is
|
||||
required to build the JavaScript and CSS files. The minimum supported Node.js
|
||||
version is 10 and the latest LTS version is recommended.
|
||||
Some internal packages are referenced using their respective Github URL. This can
|
||||
become problematic. To "trick" the Go tool into thinking this is a clone from the
|
||||
official repository, download the source code using "go get" and follow these instructions.
|
||||
|
||||
You will also need make.
|
||||
<a href='{{< relref "doc/advanced/make.en-us.md" >}}'>(See here how to get Make)</a>
|
||||
|
||||
**Note**: When executing make tasks that require external tools, like
|
||||
`make misspell-check`, Gitea will automatically download and build these as
|
||||
necessary. To be able to use these you must have the `"$GOPATH"/bin` directory
|
||||
on the executable path. If you don't add the go bin directory to the
|
||||
executable path you will have to manage this yourself.
|
||||
|
||||
**Note 2**: Go version 1.11 or higher is required; however, it is important
|
||||
to note that our continuous integration will check that the formatting of the
|
||||
source code is not changed by `gofmt` using `make fmt-check`. Unfortunately,
|
||||
the results of `gofmt` can differ by the version of `go`. It is therefore
|
||||
recommended to install the version of go that our continuous integration is
|
||||
running. At the time of writing this is Go version 1.12; however, this can be
|
||||
checked by looking at the
|
||||
[master `.drone.yml`](https://github.com/go-gitea/gitea/blob/master/.drone.yml)
|
||||
(At the time of writing
|
||||
[line 67](https://github.com/go-gitea/gitea/blob/8917d66571a95f3da232a0c27bc1300210d10fde/.drone.yml#L67)
|
||||
is the relevant line - but this may change.)
|
||||
|
||||
## Downloading and cloning the Gitea source code
|
||||
|
||||
Go is quite opinionated about where it expects its source code, and simply
|
||||
cloning the Gitea repository to an arbitrary path is likely to lead to
|
||||
problems - the fixing of which is out of scope for this document. Further, some
|
||||
internal packages are referenced using their respective GitHub URL and at
|
||||
present we use `vendor/` directories.
|
||||
|
||||
The recommended method of obtaining the source code is by using the `go get` command:
|
||||
|
||||
```bash
|
||||
```
|
||||
go get -d code.gitea.io/gitea
|
||||
cd "$GOPATH/src/code.gitea.io/gitea"
|
||||
```
|
||||
|
||||
This will clone the Gitea source code to: `"$GOPATH/src/code.gitea.io/gitea"`, or if `$GOPATH`
|
||||
is not set `"$HOME/go/src/code.gitea.io/gitea"`.
|
||||
Fork the [Gitea repository](https://github.com/go-gitea/gitea) on GitHub, it should
|
||||
then be possible to switch the source directory on the command line.
|
||||
|
||||
## Forking Gitea
|
||||
|
||||
As stated above, you cannot clone Gitea to an arbitrary path. Download the master Gitea source
|
||||
code as above. Then, fork the [Gitea repository](https://github.com/go-gitea/gitea) on GitHub,
|
||||
and either switch the git remote origin for your fork or add your fork as another remote:
|
||||
|
||||
```bash
|
||||
# Rename original Gitea origin to upstream
|
||||
cd "$GOPATH/src/code.gitea.io/gitea"
|
||||
git remote rename origin upstream
|
||||
git remote add origin "git@github.com:$GITHUB_USERNAME/gitea.git"
|
||||
git fetch --all --prune
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
# Add new remote for our fork
|
||||
cd "$GOPATH/src/code.gitea.io/gitea"
|
||||
git remote add "$FORK_NAME" "git@github.com:$GITHUB_USERNAME/gitea.git"
|
||||
git fetch --all --prune
|
||||
cd $GOPATH/src/code.gitea.io/gitea
|
||||
```
|
||||
|
||||
To be able to create pull requests, the forked repository should be added as a remote
|
||||
to the Gitea sources. Otherwise, changes can't be pushed.
|
||||
to the Gitea sources, otherwise changes can't be pushed.
|
||||
|
||||
## Building Gitea (Basic)
|
||||
|
||||
Take a look at our
|
||||
<a href='{{< relref "doc/installation/from-source.en-us.md" >}}'>instructions</a>
|
||||
for <a href='{{< relref "doc/installation/from-source.en-us.md" >}}'>building
|
||||
from source</a>.
|
||||
|
||||
The simplest recommended way to build from source is:
|
||||
|
||||
```bash
|
||||
TAGS="bindata sqlite sqlite_unlock_notify" make build
|
||||
```
|
||||
git remote rename origin upstream
|
||||
git remote add origin git@github.com:<USERNAME>/gitea.git
|
||||
git fetch --all --prune
|
||||
```
|
||||
|
||||
However, there are a number of additional make tasks you should be aware of.
|
||||
These are documented below but you can look at our
|
||||
[`Makefile`](https://github.com/go-gitea/gitea/blob/master/Makefile) for more,
|
||||
and look at our
|
||||
[`.drone.yml`](https://github.com/go-gitea/gitea/blob/master/.drone.yml) to see
|
||||
how our continuous integration works.
|
||||
This should provide a working development environment for Gitea. Take a look at
|
||||
the `Makefile` to get an overview about the available tasks. The most common tasks
|
||||
should be `make test` which will start our test environment and `make build` which
|
||||
will build a `gitea` binary into the working directory. Writing test cases is not
|
||||
mandatory to contribute, but it is highly encouraged and helps developers sleep
|
||||
at night.
|
||||
|
||||
### Formatting, code analysis and spell check
|
||||
|
||||
Our continous integration will reject PRs that are not properly formatted, fail
|
||||
code analysis or spell check.
|
||||
|
||||
You should format your code with `go fmt` using:
|
||||
|
||||
```bash
|
||||
make fmt
|
||||
```
|
||||
|
||||
and can test whether your changes would match the results with:
|
||||
|
||||
```bash
|
||||
make fmt-check # which runs make fmt internally
|
||||
```
|
||||
|
||||
**Note**: The results of `go fmt` are dependent on the version of `go` present.
|
||||
You should run the same version of go that is on the continuous integration
|
||||
server as mentioned above. `make fmt-check` will only check if your `go` would
|
||||
format differently - this may be different from the CI server version.
|
||||
|
||||
You should run revive, vet and spell-check on the code with:
|
||||
|
||||
```bash
|
||||
make revive vet misspell-check
|
||||
```
|
||||
|
||||
### Working on CSS
|
||||
|
||||
Edit files in `web_src/less` and run the linter and build the CSS files via:
|
||||
|
||||
```bash
|
||||
make css
|
||||
```
|
||||
|
||||
### Working on JS
|
||||
|
||||
Edit files in `web_src/js`, run the linter and build the JS files via:
|
||||
|
||||
```bash
|
||||
make js
|
||||
```
|
||||
|
||||
Note: When working on frontend code, it is advisable to set `USE_SERVICE_WORKER` to `false` in `app.ini` which will prevent undesirable caching of frontend assets.
|
||||
|
||||
### Updating the API
|
||||
|
||||
When creating new API routes or modifying existing API routes, you **MUST**
|
||||
update and/or create [Swagger](https://swagger.io/docs/specification/2-0/what-is-swagger/)
|
||||
documentation for these using [go-swagger](https://goswagger.io/) comments.
|
||||
The structure of these comments is described in the [specification](https://goswagger.io/use/spec.html#annotation-syntax).
|
||||
If you want more information about the Swagger structure, you can look at the
|
||||
[Swagger 2.0 Documentation](https://swagger.io/docs/specification/2-0/basic-structure/)
|
||||
or compare with a previous PR adding a new API endpoint, e.g. [PR #5483](https://github.com/go-gitea/gitea/pull/5843/files#diff-2e0a7b644cf31e1c8ef7d76b444fe3aaR20)
|
||||
|
||||
You should be careful not to break the API for downstream users which depend
|
||||
on a stable API. In general, this means additions are acceptable, but deletions
|
||||
or fundamental changes to the API will be rejected.
|
||||
|
||||
Once you have created or changed an API endpoint, please regenerate the Swagger
|
||||
documentation using:
|
||||
|
||||
```bash
|
||||
make generate-swagger
|
||||
```
|
||||
|
||||
You should validate your generated Swagger file and spell-check it with:
|
||||
|
||||
```bash
|
||||
make swagger-validate misspell-check
|
||||
```
|
||||
|
||||
You should commit the changed swagger JSON file. The continous integration
|
||||
server will check that this has been done using:
|
||||
|
||||
```bash
|
||||
make swagger-check
|
||||
```
|
||||
|
||||
**Note**: Please note you should use the Swagger 2.0 documentation, not the
|
||||
OpenAPI 3 documentation.
|
||||
|
||||
### Creating new configuration options
|
||||
|
||||
When creating new configuration options, it is not enough to add them to the
|
||||
`modules/setting` files. You should add information to `custom/conf/app.ini`
|
||||
and to the
|
||||
<a href='{{< relref "doc/advanced/config-cheat-sheet.en-us.md" >}}'>configuration cheat sheet</a>
|
||||
found in `docs/content/doc/advanced/config-cheat-sheet.en-us.md`
|
||||
|
||||
### Changing the logo
|
||||
|
||||
When changing the Gitea logo SVG, you will need to run and commit the results
|
||||
of:
|
||||
|
||||
```bash
|
||||
make generate-images
|
||||
```
|
||||
|
||||
This will create the necessary Gitea favicon and others.
|
||||
|
||||
### Database Migrations
|
||||
|
||||
If you make breaking changes to any of the database persisted structs in the
|
||||
`models/` directory, you will need to make a new migration. These can be found
|
||||
in `models/migrations/`. You can ensure that your migrations work for the main
|
||||
database types using:
|
||||
|
||||
```bash
|
||||
make test-sqlite-migration # with sqlite switched for the appropriate database
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
There are two types of test run by Gitea: Unit tests and Integration Tests.
|
||||
|
||||
```bash
|
||||
TAGS="bindata sqlite sqlite_unlock_notify" make test # Runs the unit tests
|
||||
```
|
||||
|
||||
Unit tests will not and cannot completely test Gitea alone. Therefore, we
|
||||
have written integration tests; however, these are database dependent.
|
||||
|
||||
```bash
|
||||
TAGS="bindata sqlite sqlite_unlock_notify" make build test-sqlite
|
||||
```
|
||||
|
||||
will run the integration tests in an sqlite environment. Other database tests
|
||||
are available but may need adjustment to the local environment.
|
||||
|
||||
Look at
|
||||
[`integrations/README.md`](https://github.com/go-gitea/gitea/blob/master/integrations/README.md)
|
||||
for more information and how to run a single test.
|
||||
|
||||
Our continuous integration will test the code passes its unit tests and that
|
||||
all supported databases will pass integration test in a Docker environment.
|
||||
Migration from several recent versions of Gitea will also be tested.
|
||||
|
||||
Please submit your PR with additional tests and integration tests as
|
||||
appropriate.
|
||||
|
||||
## Documentation for the website
|
||||
|
||||
Documentation for the website is found in `docs/`. If you change this you
|
||||
can test your changes to ensure that they pass continuous integration using:
|
||||
|
||||
```bash
|
||||
cd "$GOPATH/src/code.gitea.io/gitea/docs"
|
||||
make trans-copy clean build
|
||||
```
|
||||
|
||||
You will require a copy of [Hugo](https://gohugo.io/) to run this task. Please
|
||||
note: this may generate a number of untracked git objects, which will need to
|
||||
be cleaned up.
|
||||
|
||||
## Visual Studio Code
|
||||
|
||||
A `launch.json` and `tasks.json` are provided within `contrib/ide/vscode` for
|
||||
Visual Studio Code. Look at
|
||||
[`contrib/ide/README.md`](https://github.com/go-gitea/gitea/blob/master/contrib/ide/README.md)
|
||||
for more information.
|
||||
|
||||
## Submitting PRs
|
||||
|
||||
Once you're happy with your changes, push them up and open a pull request. It
|
||||
is recommended that you allow Gitea Managers and Owners to modify your PR
|
||||
branches as we will need to update it to master before merging and/or may be
|
||||
able to help fix issues directly.
|
||||
|
||||
Any PR requires two approvals from the Gitea maintainers and needs to pass the
|
||||
continous integration. Take a look at our
|
||||
[`CONTRIBUTING.md`](https://github.com/go-gitea/gitea/blob/master/CONTRIBUTING.md)
|
||||
document.
|
||||
|
||||
If you need more help pop on to [Discord](https://discord.gg/gitea) #Develop
|
||||
and chat there.
|
||||
|
||||
That's it! You are ready to hack on Gitea.
|
||||
That's it! You are ready to hack on Gitea. Test changes, push them to the repository,
|
||||
and open a pull request.
|
||||
|
@@ -1,390 +0,0 @@
|
||||
---
|
||||
date: "2019-04-02T17:06:00+01:00"
|
||||
title: "Advanced: Logging Configuration"
|
||||
slug: "logging-configuration"
|
||||
weight: 55
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Logging Configuration"
|
||||
weight: 55
|
||||
identifier: "logging-configuration"
|
||||
---
|
||||
|
||||
# Logging Configuration
|
||||
|
||||
The logging framework has been revamped in Gitea 1.9.0.
|
||||
|
||||
## Log Groups
|
||||
|
||||
The fundamental thing to be aware of in Gitea is that there are several
|
||||
log groups:
|
||||
|
||||
* The "Default" logger
|
||||
* The Macaron logger
|
||||
* The Router logger
|
||||
* The Access logger
|
||||
* The XORM logger
|
||||
|
||||
There is also the go log logger.
|
||||
|
||||
### The go log logger
|
||||
|
||||
Go provides its own extremely basic logger in the `log` package,
|
||||
however, this is not sufficient for our purposes as it does not provide
|
||||
a way of logging at multiple levels, nor does it provide a good way of
|
||||
controlling where these logs are logged except through setting of a
|
||||
writer.
|
||||
|
||||
We have therefore redirected this logger to our Default logger, and we
|
||||
will log anything that is logged using the go logger at the INFO level.
|
||||
|
||||
### The "Default" logger
|
||||
|
||||
Calls to `log.Info`, `log.Debug`, `log.Error` etc. from the `code.gitea.io/gitea/modules/log` package will log to this logger.
|
||||
|
||||
You can configure the outputs of this logger by setting the `MODE`
|
||||
value in the `[log]` section of the configuration.
|
||||
|
||||
Each output sublogger is configured in a separate `[log.sublogger]`
|
||||
section, but there are certain default values. These will not be inherited from the `[log]` section:
|
||||
|
||||
* `FLAGS` is `stdflags` (Equal to
|
||||
`date,time,medfile,shortfuncname,levelinitial`)
|
||||
* `FILE_NAME` will default to `%(ROOT_PATH)/gitea.log`
|
||||
* `EXPRESSION` will default to `""`
|
||||
* `PREFIX` will default to `""`
|
||||
|
||||
The provider type of the sublogger can be set using the `MODE` value in
|
||||
its subsection, but will default to the name. This allows you to have
|
||||
multiple subloggers that will log to files.
|
||||
|
||||
### The "Macaron" logger
|
||||
|
||||
By default Macaron will log to its own go `log` instance. This writes
|
||||
to `os.Stdout`. You can redirect this log to a Gitea configurable logger
|
||||
through setting the `REDIRECT_MACARON_LOG` setting in the `[log]`
|
||||
section which you can configure the outputs of by setting the `MACARON`
|
||||
value in the `[log]` section of the configuration. `MACARON` defaults
|
||||
to `file` if unset.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.macaron]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
* `FLAGS` is `stdflags` (Equal to
|
||||
`date,time,medfile,shortfuncname,levelinitial`)
|
||||
* `FILE_NAME` will default to `%(ROOT_PATH)/macaron.log`
|
||||
* `EXPRESSION` will default to `""`
|
||||
* `PREFIX` will default to `""`
|
||||
|
||||
NB: You can redirect the macaron logger to send its events to the gitea
|
||||
log using the value: `MACARON = ,`
|
||||
|
||||
### The "Router" logger
|
||||
|
||||
There are two types of Router log. By default Macaron send its own
|
||||
router log which will be directed to Macaron's go `log`, however if you
|
||||
`REDIRECT_MACARON_LOG` you will enable Gitea's router log. You can
|
||||
disable both types of Router log by setting `DISABLE_ROUTER_LOG`.
|
||||
|
||||
If you enable the redirect, you can configure the outputs of this
|
||||
router log by setting the `ROUTER` value in the `[log]` section of the
|
||||
configuration. `ROUTER` will default to `console` if unset. The Gitea
|
||||
Router logs the same data as the Macaron log but has slightly different
|
||||
coloring. It logs at the `Info` level by default, but this can be
|
||||
changed if desired by setting the `ROUTER_LOG_LEVEL` value.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.router]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
* `FILE_NAME` will default to `%(ROOT_PATH)/router.log`
|
||||
* `FLAGS` defaults to `date,time`
|
||||
* `EXPRESSION` will default to `""`
|
||||
* `PREFIX` will default to `""`
|
||||
|
||||
NB: You can redirect the router logger to send its events to the Gitea
|
||||
log using the value: `ROUTER = ,`
|
||||
|
||||
### The "Access" logger
|
||||
|
||||
The Access logger is a new logger for version 1.9. It provides a NCSA
|
||||
Common Log compliant log format. It's highly configurable but caution
|
||||
should be taken when changing its template. The main benefit of this
|
||||
logger is that Gitea can now log accesses in a standard log format so
|
||||
standard tools may be used.
|
||||
|
||||
You can enable this logger using `ENABLE_ACCESS_LOG`. Its outputs are
|
||||
configured by setting the `ACCESS` value in the `[log]` section of the
|
||||
configuration. `ACCESS` defaults to `file` if unset.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.access]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
* `FILE_NAME` will default to `%(ROOT_PATH)/access.log`
|
||||
* `FLAGS` defaults to `` or None
|
||||
* `EXPRESSION` will default to `""`
|
||||
* `PREFIX` will default to `""`
|
||||
|
||||
If desired the format of the Access logger can be changed by changing
|
||||
the value of the `ACCESS_LOG_TEMPLATE`.
|
||||
|
||||
NB: You can redirect the access logger to send its events to the Gitea
|
||||
log using the value: `ACCESS = ,`
|
||||
|
||||
#### The ACCESS_LOG_TEMPLATE
|
||||
|
||||
This value represent a go template. It's default value is:
|
||||
|
||||
`{{.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}}"`
|
||||
|
||||
The template is passed following options:
|
||||
|
||||
* `Ctx` is the `macaron.Context`
|
||||
* `Identity` is the `SignedUserName` or `"-"` if the user is not logged
|
||||
in
|
||||
* `Start` is the start time of the request
|
||||
* `ResponseWriter` is the `macaron.ResponseWriter`
|
||||
|
||||
Caution must be taken when changing this template as it runs outside of
|
||||
the standard panic recovery trap. The template should also be as simple
|
||||
as it runs for every request.
|
||||
|
||||
### The "XORM" logger
|
||||
|
||||
The XORM logger is a long-standing logger that exists to collect XORM
|
||||
log events. It is enabled by default but can be switched off by setting
|
||||
`ENABLE_XORM_LOG` to `false` in the `[log]` section. Its outputs are
|
||||
configured by setting the `XORM` value in the `[log]` section of the
|
||||
configuration. `XORM` defaults to `,` if unset, meaning it is redirected
|
||||
to the main Gitea log.
|
||||
|
||||
XORM will log SQL events by default. This can be changed by setting
|
||||
the `LOG_SQL` value to `false` in the `[database]` section.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.xorm]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
* `FILE_NAME` will default to `%(ROOT_PATH)/xorm.log`
|
||||
* `FLAGS` defaults to `date,time`
|
||||
* `EXPRESSION` will default to `""`
|
||||
* `PREFIX` will default to `""`
|
||||
|
||||
## Log outputs
|
||||
|
||||
Gitea provides 4 possible log outputs:
|
||||
|
||||
* `console` - Log to `os.Stdout` or `os.Stderr`
|
||||
* `file` - Log to a file
|
||||
* `conn` - Log to a keep-alive TCP connection
|
||||
* `smtp` - Log via email
|
||||
|
||||
Certain configuration is common to all modes of log output:
|
||||
|
||||
* `LEVEL` is the lowest level that this output will log. This value
|
||||
is inherited from `[log]` and in the case of the non-default loggers
|
||||
from `[log.sublogger]`.
|
||||
* `STACKTRACE_LEVEL` is the lowest level that this output will print
|
||||
a stacktrace. This value is inherited.
|
||||
* `MODE` is the mode of the log output. It will default to the sublogger
|
||||
name. Thus `[log.console.macaron]` will default to `MODE = console`.
|
||||
* `COLORIZE` will default to `true` for `console` as
|
||||
described, otherwise it will default to `false`.
|
||||
|
||||
### Non-inherited default values
|
||||
|
||||
There are several values which are not inherited as described above but
|
||||
rather default to those specific to type of logger, these are:
|
||||
`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`.
|
||||
|
||||
#### `EXPRESSION`
|
||||
|
||||
`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match.
|
||||
|
||||
Please note this expression will be run in the sublogger's goroutine
|
||||
not the logging event subroutine. Therefore it can be complicated.
|
||||
|
||||
#### `FLAGS`
|
||||
|
||||
`FLAGS` represents the preceding logging context information that is
|
||||
printed before each message. It is a comma-separated string set. The order of values does not matter.
|
||||
|
||||
Possible values are:
|
||||
|
||||
* `none` or `,` - No flags.
|
||||
* `date` - the date in the local time zone: `2009/01/23`.
|
||||
* `time` - the time in the local time zone: `01:23:23`.
|
||||
* `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes
|
||||
time.
|
||||
* `longfile` - full file name and line number: `/a/b/c/d.go:23`.
|
||||
* `shortfile` - final file name element and line number: `d.go:23`.
|
||||
* `funcname` - function name of the caller: `runtime.Caller()`.
|
||||
* `shortfuncname` - last part of the function name. Overrides
|
||||
`funcname`.
|
||||
* `utc` - if date or time is set, use UTC rather than the local time
|
||||
zone.
|
||||
* `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info.
|
||||
* `level` - Provided level in brackets `[INFO]`
|
||||
* `medfile` - Last 20 characters of the filename - equivalent to
|
||||
`shortfile,longfile`.
|
||||
* `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial`
|
||||
|
||||
### Console mode
|
||||
|
||||
For loggers in console mode, `COLORIZE` will default to `true` if not
|
||||
on windows, or the windows terminal can be set into ANSI mode or is a
|
||||
cygwin or Msys pipe.
|
||||
|
||||
If `STDERR` is set to `true` the logger will use `os.Stderr` instead of
|
||||
`os.Stdout`.
|
||||
|
||||
### File mode
|
||||
|
||||
The `FILE_NAME` defaults as described above. If set it will be relative
|
||||
to the provided `ROOT_PATH` in the master `[log]` section.
|
||||
|
||||
Other values:
|
||||
|
||||
* `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 mode
|
||||
|
||||
* `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 mode
|
||||
|
||||
It is not recommended to use this logger to send general logging
|
||||
messages. However, you could perhaps set this logger to work on `FATAL`.
|
||||
|
||||
* `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**
|
||||
|
||||
## Default Configuration
|
||||
|
||||
The default empty configuration is equivalent to:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
ROOT_PATH = %(GITEA_WORK_DIR)/log
|
||||
MODE = console
|
||||
LEVEL = Info
|
||||
STACKTRACE_LEVEL = None
|
||||
REDIRECT_MACARON_LOG = false
|
||||
ENABLE_ACCESS_LOG = false
|
||||
ENABLE_XORM_LOG = true
|
||||
XORM = ,
|
||||
|
||||
[log.console]
|
||||
MODE = console
|
||||
LEVEL = %(LEVEL)
|
||||
STACKTRACE_LEVEL = %(STACKTRACE_LEVEL)
|
||||
FLAGS = stdflags
|
||||
PREFIX =
|
||||
COLORIZE = true # Or false if your windows terminal cannot color
|
||||
```
|
||||
|
||||
This is equivalent to sending all logs to the console, with default go log being sent to the console log too.
|
||||
|
||||
## Log colorization
|
||||
|
||||
Logs to the console will be colorized by default when not running on
|
||||
Windows. Terminal sniffing will occur on Windows and if it is
|
||||
determined that we are running on a terminal capable of color we will
|
||||
colorize.
|
||||
|
||||
Further, on *nix it is becoming common to have file logs that are
|
||||
colored by default. Therefore file logs will be colorised by default
|
||||
when not running on Windows.
|
||||
|
||||
You can switch on or off colorization by using the `COLORIZE` value.
|
||||
|
||||
From a development point of view. If you write
|
||||
`log.Info("A %s string", "formatted")` the `formatted` part of the log
|
||||
message will be Bolded on colorized logs.
|
||||
|
||||
You can change this by either rendering the formatted string yourself.
|
||||
Or you can wrap the value in a `log.ColoredValue` struct.
|
||||
|
||||
The `log.ColoredValue` struct contains a pointer to value, a pointer to
|
||||
string of bytes which should represent a color and second set of reset
|
||||
bytes. Pointers were chosen to prevent copying of large numbers of
|
||||
values. There are several helper methods:
|
||||
|
||||
* `log.NewColoredValue` takes a value and 0 or more color attributes
|
||||
that represent the color. If 0 are provided it will default to a cached
|
||||
bold. Note, it is recommended that color bytes constructed from
|
||||
attributes should be cached if this is a commonly used log message.
|
||||
* `log.NewColoredValuePointer` takes a pointer to a value, and
|
||||
0 or more color attributes that represent the color.
|
||||
* `log.NewColoredValueBytes` takes a value and a pointer to an array
|
||||
of bytes representing the color.
|
||||
|
||||
These functions will not double wrap a `log.ColoredValue`. They will
|
||||
also set the `resetBytes` to the cached `resetBytes`.
|
||||
|
||||
The `colorBytes` and `resetBytes` are not exported to prevent
|
||||
accidental overwriting of internal values.
|
||||
|
||||
## ColorFormat & ColorFormatted
|
||||
|
||||
Structs may implement the `log.ColorFormatted` interface by implementing the `ColorFormat(fmt.State)` function.
|
||||
|
||||
If a `log.ColorFormatted` struct is logged with `%-v` format, its `ColorFormat` will be used instead of the usual `%v`. The full `fmt.State` will be passed to allow implementers to look at additional flags.
|
||||
|
||||
In order to help implementers provide `ColorFormat` methods. There is a
|
||||
`log.ColorFprintf(...)` function in the log module that will wrap values in `log.ColoredValue` and recognise `%-v`.
|
||||
|
||||
In general it is recommended not to make the results of this function too verbose to help increase its versatility. Usually this should simply be an `ID`:`Name`. If you wish to make a more verbose result, it is recommended to use `%-+v` as your marker.
|
||||
|
||||
## Log Spoofing protection
|
||||
|
||||
In order to protect the logs from being spoofed with cleverly
|
||||
constructed messages. Newlines are now prefixed with a tab and control
|
||||
characters except those used in an ANSI CSI are escaped with a
|
||||
preceding `\` and their octal value.
|
||||
|
||||
## Creating a new named logger group
|
||||
|
||||
Should a developer wish to create a new named logger, `NEWONE`. It is
|
||||
recommended to add an `ENABLE_NEWONE_LOG` value to the `[log]`
|
||||
section, and to add a new `NEWONE` value for the modes.
|
||||
|
||||
A function like `func newNewOneLogService()` is recommended to manage
|
||||
construction of the named logger. e.g.
|
||||
|
||||
```go
|
||||
func newNewoneLogService() {
|
||||
EnableNewoneLog = Cfg.Section("log").Key("ENABLE_NEWONE_LOG").MustBool(false)
|
||||
Cfg.Section("log").Key("NEWONE").MustString("file") // or console? or "," if you want to send this to default logger by default
|
||||
if EnableNewoneLog {
|
||||
options := newDefaultLogOptions()
|
||||
options.filename = filepath.Join(LogRootPath, "newone.log")
|
||||
options.flags = "stdflags"
|
||||
options.bufferLength = Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000)
|
||||
generateNamedLogger("newone", options)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You should then add `newOneLogService` to `NewServices()` in
|
||||
`modules/setting/setting.go`
|
@@ -1,276 +0,0 @@
|
||||
---
|
||||
date: "2019-10-23T17:00:00-03:00"
|
||||
title: "Mail templates"
|
||||
slug: "mail-templates"
|
||||
weight: 45
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Mail templates"
|
||||
weight: 45
|
||||
identifier: "mail-templates"
|
||||
---
|
||||
|
||||
# Mail templates
|
||||
|
||||
To craft the e-mail subject and contents for certain operations, Gitea can be customized by using templates. The templates
|
||||
for these functions are located under the [`custom` directory](https://docs.gitea.io/en-us/customizing-gitea/).
|
||||
Gitea has an internal template that serves as default in case there's no custom alternative.
|
||||
|
||||
Custom templates are loaded when Gitea starts. Changes made to them are not recognized until Gitea is restarted again.
|
||||
|
||||
## Mail notifications supporting templates
|
||||
|
||||
Currently, the following notification events make use of templates:
|
||||
|
||||
| Action name | Usage |
|
||||
|---------------|--------------------------------------------------------------------------------------------------------------|
|
||||
| `new` | A new issue or pull request was created. |
|
||||
| `comment` | A new comment was created in an existing issue or pull request. |
|
||||
| `close` | An issue or pull request was closed. |
|
||||
| `reopen` | An issue or pull request was reopened. |
|
||||
| `review` | The head comment of a review in a pull request. |
|
||||
| `approve` | The head comment of a approving review for a pull request. |
|
||||
| `reject` | The head comment of a review requesting changes for a pull request. |
|
||||
| `code` | A single comment on the code of a pull request. |
|
||||
| `assigned` | Used was assigned to an issue or pull request. |
|
||||
| `default` | Any action not included in the above categories, or when the corresponding category template is not present. |
|
||||
|
||||
The path for the template of a particular message type is:
|
||||
|
||||
```
|
||||
custom/templates/mail/{action type}/{action name}.tmpl
|
||||
```
|
||||
|
||||
Where `{action type}` is one of `issue` or `pull` (for pull requests), and `{action name}` is one of the names listed above.
|
||||
|
||||
For example, the specific template for a mail regarding a comment in a pull request is:
|
||||
```
|
||||
custom/templates/mail/pull/comment.tmpl
|
||||
```
|
||||
|
||||
However, creating templates for each and every action type/name combination is not required.
|
||||
A fallback system is used to choose the appropriate template for an event. The _first existing_
|
||||
template on this list is used:
|
||||
|
||||
* The specific template for the desired **action type** and **action name**.
|
||||
* The template for action type `issue` and the desired **action name**.
|
||||
* The template for the desired **action type**, action name `default`.
|
||||
* The template for action type `issue`, action name `default`.
|
||||
|
||||
The only mandatory template is action type `issue`, action name `default`, which is already embedded in Gitea
|
||||
unless it's overridden by the user in the `custom` directory.
|
||||
|
||||
## Template syntax
|
||||
|
||||
Mail templates are UTF-8 encoded text files that need to follow one of the following formats:
|
||||
|
||||
```
|
||||
Text and macros for the subject line
|
||||
------------
|
||||
Text and macros for the mail body
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
Text and macros for the mail body
|
||||
```
|
||||
|
||||
Specifying a _subject_ section is optional (and therefore also the dash line separator). When used, the separator between
|
||||
_subject_ and _mail body_ templates requires at least three dashes; no other characters are allowed in the separator line.
|
||||
|
||||
|
||||
_Subject_ and _mail body_ are parsed by [Golang's template engine](https://golang.org/pkg/text/template/) and
|
||||
are provided with a _metadata context_ assembled for each notification. The context contains the following elements:
|
||||
|
||||
| Name | Type | Available | Usage |
|
||||
|--------------------|------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `.FallbackSubject` | string | Always | A default subject line. See Below. |
|
||||
| `.Subject` | string | Only in body | The _subject_, once resolved. |
|
||||
| `.Body` | string | Always | The message of the issue, pull request or comment, parsed from Markdown into HTML and sanitized. Do not confuse with the _mail body_. |
|
||||
| `.Link` | string | Always | The address of the originating issue, pull request or comment. |
|
||||
| `.Issue` | models.Issue | Always | The issue (or pull request) originating the notification. To get data specific to a pull request (e.g. `HasMerged`), `.Issue.PullRequest` can be used, but care should be taken as this field will be `nil` if the issue is *not* a pull request. |
|
||||
| `.Comment` | models.Comment | If applicable | If the notification is from a comment added to an issue or pull request, this will contain the information about the comment. |
|
||||
| `.IsPull` | bool | Always | `true` if the mail notification is associated with a pull request (i.e. `.Issue.PullRequest` is not `nil`). |
|
||||
| `.Repo` | string | Always | Name of the repository, including owner name (e.g. `mike/stuff`) |
|
||||
| `.User` | models.User | Always | Owner of the repository from which the event originated. To get the user name (e.g. `mike`),`.User.Name` can be used. |
|
||||
| `.Doer` | models.User | Always | User that executed the action triggering the notification event. To get the user name (e.g. `rhonda`), `.Doer.Name` can be used. |
|
||||
| `.IsMention` | bool | Always | `true` if this notification was only generated because the user was mentioned in the comment, while not being subscribed to the source. It will be `false` if the recipient was subscribed to the issue or repository. |
|
||||
| `.SubjectPrefix` | string | Always | `Re: ` if the notification is about other than issue or pull request creation; otherwise an empty string. |
|
||||
| `.ActionType` | string | Always | `"issue"` or `"pull"`. Will correspond to the actual _action type_ independently of which template was selected. |
|
||||
| `.ActionName` | string | Always | It will be one of the action types described above (`new`, `comment`, etc.), and will correspond to the actual _action name_ independently of which template was selected. |
|
||||
| `.ReviewComments` | []models.Comment | Always | List of code comments in a review. The comment text will be in `.RenderedContent` and the referenced code will be in `.Patch`. |
|
||||
|
||||
All names are case sensitive.
|
||||
|
||||
### The _subject_ part of the template
|
||||
|
||||
The template engine used for the mail _subject_ is golang's [`text/template`](https://golang.org/pkg/text/template/).
|
||||
Please refer to the linked documentation for details about its syntax.
|
||||
|
||||
The _subject_ is built using the following steps:
|
||||
|
||||
* A template is selected according to the type of notification and to what templates are present.
|
||||
* The template is parsed and resolved (e.g. `{{.Issue.Index}}` is converted to the number of the issue
|
||||
or pull request).
|
||||
* All space-like characters (e.g. `TAB`, `LF`, etc.) are converted to normal spaces.
|
||||
* All leading, trailing and redundant spaces are removed.
|
||||
* The string is truncated to its first 256 runes (characters).
|
||||
|
||||
If the end result is an empty string, **or** no subject template was available (i.e. the selected template
|
||||
did not include a subject part), Gitea's **internal default** will be used.
|
||||
|
||||
The internal default (fallback) subject is the equivalent of:
|
||||
|
||||
```
|
||||
{{.SubjectPrefix}}[{{.Repo}}] {{.Issue.Title}} (#.Issue.Index)
|
||||
```
|
||||
|
||||
For example: `Re: [mike/stuff] New color palette (#38)`
|
||||
|
||||
Gitea's default subject can also be found in the template _metadata_ as `.FallbackSubject` from any of
|
||||
the two templates, even if a valid subject template is present.
|
||||
|
||||
### The _mail body_ part of the template
|
||||
|
||||
The template engine used for the _mail body_ is golang's [`html/template`](https://golang.org/pkg/html/template/).
|
||||
Please refer to the linked documentation for details about its syntax.
|
||||
|
||||
The _mail body_ is parsed after the mail subject, so there is an additional _metadata_ field which is
|
||||
the actual rendered subject, after all considerations.
|
||||
|
||||
The expected result is HTML (including structural elements like`<html>`, `<body>`, etc.). Styling
|
||||
through `<style>` blocks, `class` and `style` attributes is possible. However, `html/template`
|
||||
does some [automatic escaping](https://golang.org/pkg/html/template/#hdr-Contexts) that should be considered.
|
||||
|
||||
Attachments (such as images or external style sheets) are not supported. However, other templates can
|
||||
be referenced too, for example to provide the contents of a `<style>` element in a centralized fashion.
|
||||
The external template must be placed under `custom/mail` and referenced relative to that directory.
|
||||
For example, `custom/mail/styles/base.tmpl` can be included using `{{template styles/base}}`.
|
||||
|
||||
The mail is sent with `Content-Type: multipart/alternative`, so the body is sent in both HTML
|
||||
and text formats. The latter is obtained by stripping the HTML markup.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
How a mail is rendered is directly dependent on the capabilities of the mail application. Many mail
|
||||
clients don't even support HTML, so they show the text version included in the generated mail.
|
||||
|
||||
If the template fails to render, it will be noticed only at the moment the mail is sent.
|
||||
A default subject is used if the subject template fails, and whatever was rendered successfully
|
||||
from the the _mail body_ is used, disregarding the rest.
|
||||
|
||||
Please check [Gitea's logs](https://docs.gitea.io/en-us/logging-configuration/) for error messages in case of trouble.
|
||||
|
||||
## Example
|
||||
|
||||
`custom/templates/mail/issue/default.tmpl`:
|
||||
|
||||
```
|
||||
[{{.Repo}}] @{{.Doer.Name}}
|
||||
{{if eq .ActionName "new"}}
|
||||
created
|
||||
{{else if eq .ActionName "comment"}}
|
||||
commented on
|
||||
{{else if eq .ActionName "close"}}
|
||||
closed
|
||||
{{else if eq .ActionName "reopen"}}
|
||||
reopened
|
||||
{{else}}
|
||||
updated
|
||||
{{end}}
|
||||
{{if eq .ActionType "issue"}}
|
||||
issue
|
||||
{{else}}
|
||||
pull request
|
||||
{{end}}
|
||||
#{{.Issue.Index}}: {{.Issue.Title}}
|
||||
------------
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>{{.Subject}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{if .IsMention}}
|
||||
<p>
|
||||
You are receiving this because @{{.Doer.Name}} mentioned you.
|
||||
</p>
|
||||
{{end}}
|
||||
<p>
|
||||
<p>
|
||||
<a href="{{AppURL}}/{{.Doer.LowerName}}">@{{.Doer.Name}}</a>
|
||||
{{if not (eq .Doer.FullName "")}}
|
||||
({{.Doer.FullName}})
|
||||
{{end}}
|
||||
{{if eq .ActionName "new"}}
|
||||
created
|
||||
{{else if eq .ActionName "close"}}
|
||||
closed
|
||||
{{else if eq .ActionName "reopen"}}
|
||||
reopened
|
||||
{{else}}
|
||||
updated
|
||||
{{end}}
|
||||
<a href="{{.Link}}">{{.Repo}}#{{.Issue.Index}}</a>.
|
||||
</p>
|
||||
{{if not (eq .Body "")}}
|
||||
<h3>Message content:</h3>
|
||||
<hr>
|
||||
{{.Body | Str2html}}
|
||||
{{end}}
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
<a href="{{.Link}}">View it on Gitea</a>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
This template produces something along these lines:
|
||||
|
||||
#### Subject
|
||||
|
||||
> [mike/stuff] @rhonda commented on pull request #38: New color palette
|
||||
|
||||
#### Mail body
|
||||
|
||||
> [@rhonda](#) (Rhonda Myers) updated [mike/stuff#38](#).
|
||||
>
|
||||
> #### Message content:
|
||||
>
|
||||
> \__________________________________________________________________
|
||||
>
|
||||
> Mike, I think we should tone down the blues a little.
|
||||
> \__________________________________________________________________
|
||||
>
|
||||
> [View it on Gitea](#).
|
||||
|
||||
## Advanced
|
||||
|
||||
The template system contains several functions that can be used to further process and format
|
||||
the messages. Here's a list of some of them:
|
||||
|
||||
| Name | Parameters | Available | Usage |
|
||||
|----------------------|-------------|-----------|------------------------------------------------------------------------------|
|
||||
| `AppUrl` | - | Any | Gitea's URL |
|
||||
| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" |
|
||||
| `AppDomain` | - | Any | Gitea's host name |
|
||||
| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed |
|
||||
| `Str2html` | string | Body only | Sanitizes text by removing any HTML tags from it. |
|
||||
| `Safe` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. |
|
||||
|
||||
These are _functions_, not metadata, so they have to be used:
|
||||
|
||||
```
|
||||
Like this: {{Str2html "Escape<my>text"}}
|
||||
Or this: {{"Escape<my>text" | Str2html}}
|
||||
Or this: {{AppUrl}}
|
||||
But not like this: {{.AppUrl}}
|
||||
```
|
@@ -1,74 +0,0 @@
|
||||
---
|
||||
date: "2019-04-15T17:29:00+08:00"
|
||||
title: "Advanced: Migrations Interfaces"
|
||||
slug: "migrations-interfaces"
|
||||
weight: 30
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Migrations Interfaces"
|
||||
weight: 55
|
||||
identifier: "migrations-interfaces"
|
||||
---
|
||||
|
||||
# Migration Features
|
||||
|
||||
The new migration features were introduced in Gitea 1.9.0. It defines two interfaces to support migrating
|
||||
repositories data from other git host platforms to gitea or, in the future migrating gitea data to other
|
||||
git host platforms. Currently, only the migrations from github via APIv3 to Gitea is implemented.
|
||||
|
||||
First of all, Gitea defines some standard objects in packages `modules/migrations/base`. They are
|
||||
`Repository`, `Milestone`, `Release`, `Label`, `Issue`, `Comment`, `PullRequest`.
|
||||
|
||||
## Downloader Interfaces
|
||||
|
||||
To migrate from a new git host platform, there are two steps to be updated.
|
||||
|
||||
- You should implement a `Downloader` which will get all kinds of repository informations.
|
||||
- You should implement a `DownloaderFactory` which is used to detect if the URL matches and
|
||||
create a Downloader.
|
||||
- You'll need to register the `DownloaderFactory` via `RegisterDownloaderFactory` on init.
|
||||
|
||||
```Go
|
||||
type Downloader interface {
|
||||
GetRepoInfo() (*Repository, error)
|
||||
GetTopics() ([]string, error)
|
||||
GetMilestones() ([]*Milestone, error)
|
||||
GetReleases() ([]*Release, error)
|
||||
GetLabels() ([]*Label, error)
|
||||
GetIssues(start, limit int) ([]*Issue, error)
|
||||
GetComments(issueNumber int64) ([]*Comment, error)
|
||||
GetPullRequests(start, limit int) ([]*PullRequest, error)
|
||||
}
|
||||
```
|
||||
|
||||
```Go
|
||||
type DownloaderFactory interface {
|
||||
Match(opts MigrateOptions) (bool, error)
|
||||
New(opts MigrateOptions) (Downloader, error)
|
||||
}
|
||||
```
|
||||
|
||||
## Uploader Interface
|
||||
|
||||
Currently, only a `GiteaLocalUploader` is implemented, so we only save downloaded
|
||||
data via this `Uploader` on the local Gitea instance. Other uploaders are not supported
|
||||
and will be implemented in future.
|
||||
|
||||
```Go
|
||||
// Uploader uploads all the informations
|
||||
type Uploader interface {
|
||||
CreateRepo(repo *Repository, includeWiki bool) error
|
||||
CreateMilestone(milestone *Milestone) error
|
||||
CreateRelease(release *Release) error
|
||||
CreateLabel(label *Label) error
|
||||
CreateIssue(issue *Issue) error
|
||||
CreateComment(issueNumber int64, comment *Comment) error
|
||||
CreatePullRequest(pr *PullRequest) error
|
||||
Rollback() error
|
||||
Close()
|
||||
}
|
||||
|
||||
```
|
@@ -1,92 +0,0 @@
|
||||
---
|
||||
date: "2019-04-19:44:00+01:00"
|
||||
title: "OAuth2 provider"
|
||||
slug: "oauth2-provider"
|
||||
weight: 41
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "OAuth2 Provider"
|
||||
weight: 41
|
||||
identifier: "oauth2-provider"
|
||||
---
|
||||
|
||||
|
||||
# OAuth2 provider
|
||||
|
||||
Gitea supports acting as an OAuth2 provider to allow third party applications to access its resources with the user's consent. This feature is available since release 1.8.0.
|
||||
|
||||
## Endpoints
|
||||
|
||||
|
||||
Endpoint | URL
|
||||
-----------------------|----------------------------
|
||||
Authorization Endpoint | `/login/oauth/authorize`
|
||||
Access Token Endpoint | `/login/oauth/access_token`
|
||||
|
||||
|
||||
## Supported OAuth2 Grants
|
||||
|
||||
At the moment Gitea only supports the [**Authorization Code Grant**](https://tools.ietf.org/html/rfc6749#section-1.3.1) standard with additional support of the [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636) extension.
|
||||
|
||||
|
||||
To use the Authorization Code Grant as a third party application it is required to register a new application via the "Settings" (`/user/settings/applications`) section of the settings.
|
||||
|
||||
## Scopes
|
||||
|
||||
Currently Gitea does not support scopes (see [#4300](https://github.com/go-gitea/gitea/issues/4300)) and all third party applications will be granted access to all resources of the user and his/her organizations.
|
||||
|
||||
## Example
|
||||
|
||||
**Note:** This example does not use PKCE.
|
||||
|
||||
1. Redirect to user to the authorization endpoint in order to get his/her consent for accessing the resources:
|
||||
|
||||
```curl
|
||||
https://[YOUR-GITEA-URL]/login/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI& response_type=code&state=STATE
|
||||
```
|
||||
|
||||
The `CLIENT_ID` can be obtained by registering an application in the settings. The `STATE` is a random string that will be send back to your application after the user authorizes. The `state` parameter is optional but should be used to prevent CSRF attacks.
|
||||
|
||||
|
||||

|
||||
|
||||
The user will now be asked to authorize your application. If they authorize it, the user will be redirected to the `REDIRECT_URL`, for example:
|
||||
|
||||
```curl
|
||||
https://[REDIRECT_URI]?code=RETURNED_CODE&state=STATE
|
||||
```
|
||||
|
||||
2. Using the provided `code` from the redirect, you can request a new application and refresh token. The access token endpoints accepts POST requests with `application/json` and `application/x-www-form-urlencoded` body, for example:
|
||||
|
||||
```curl
|
||||
POST https://[YOUR-GITEA-URL]/login/oauth/access_token
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "YOUR_CLIENT_ID",
|
||||
"client_secret": "YOUR_CLIENT_SECRET",
|
||||
"code": "RETURNED_CODE",
|
||||
"grant_type": "authorization_code",
|
||||
"redirect_uri": "REDIRECT_URI"
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"access_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjowLCJleHAiOjE1NTUxNzk5MTIsImlhdCI6MTU1NTE3NjMxMn0.0-iFsAwBtxuckA0sNZ6QpBQmywVPz129u75vOM7wPJecw5wqGyBkmstfJHAjEOqrAf_V5Z-1QYeCh_Cz4RiKug",
|
||||
"token_type":"bearer",
|
||||
"expires_in":3600,
|
||||
"refresh_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJnbnQiOjIsInR0IjoxLCJjbnQiOjEsImV4cCI6MTU1NzgwNDMxMiwiaWF0IjoxNTU1MTc2MzEyfQ.S_HZQBy4q9r5SEzNGNIoFClT43HPNDbUdHH-GYNYYdkRfft6XptJBkUQscZsGxOW975Yk6RbgtGvq1nkEcklOw"
|
||||
}
|
||||
```
|
||||
|
||||
The `CLIENT_SECRET` is the unique secret code generated for this application. Please note that the secret will only be visible after you created/registered the application with Gitea and cannot be recovered. If you lose the secret you must regenerate the secret via the application's settings.
|
||||
|
||||
The `REDIRECT_URI` in the `access_token` request must match the `REDIRECT_URI` in the `authorize` request.
|
||||
|
||||
3. Use the `access_token` to make [API requests](https://docs.gitea.io/en-us/api-usage#oauth2) to access the user's resources.
|
@@ -1,58 +0,0 @@
|
||||
---
|
||||
date: "2019-09-06T01:35:00-03:00"
|
||||
title: "Repository indexer"
|
||||
slug: "repo-indexer"
|
||||
weight: 45
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Repository indexer"
|
||||
weight: 45
|
||||
identifier: "repo-indexer"
|
||||
---
|
||||
|
||||
# Repository indexer
|
||||
|
||||
## Setting up the repository indexer
|
||||
|
||||
Gitea can search through the files of the repositories by enabling this function in your [`app.ini`](https://docs.gitea.io/en-us/config-cheat-sheet/):
|
||||
|
||||
```
|
||||
[indexer]
|
||||
; ...
|
||||
REPO_INDEXER_ENABLED = true
|
||||
REPO_INDEXER_PATH = indexers/repos.bleve
|
||||
UPDATE_BUFFER_LEN = 20
|
||||
MAX_FILE_SIZE = 1048576
|
||||
REPO_INDEXER_INCLUDE =
|
||||
REPO_INDEXER_EXCLUDE = resources/bin/**
|
||||
```
|
||||
|
||||
Please bear in mind that indexing the contents can consume a lot of system resources, especially when the index is created for the first time or globally updated (e.g. after upgrading Gitea).
|
||||
|
||||
### Choosing the files for indexing by size
|
||||
|
||||
The `MAX_FILE_SIZE` option will make the indexer skip all files larger than the specified value.
|
||||
|
||||
### Choosing the files for indexing by path
|
||||
|
||||
Gitea applies glob pattern matching from the [`gobwas/glob` library](https://github.com/gobwas/glob) to choose which files will be included in the index.
|
||||
|
||||
Limiting the list of files prevents the indexes from becoming polluted with derived or irrelevant files (e.g. lss, sym, map, etc.), so the search results are more relevant. It can also help reduce the index size.
|
||||
|
||||
`REPO_INDEXER_INCLUDE` (default: empty) is a comma separated list of glob patterns to **include** in the index. An empty list means "_include all files_".
|
||||
`REPO_INDEXER_EXCLUDE` (default: empty) is a comma separated list of glob patterns to **exclude** from the index. Files that match this list will not be indexed. `REPO_INDEXER_EXCLUDE` takes precedence over `REPO_INDEXER_INCLUDE`.
|
||||
|
||||
Pattern matching works as follows:
|
||||
|
||||
* To match all files with a `.txt` extension no matter what directory, use `**.txt`.
|
||||
* To match all files with a `.txt` extension _only at the root level of the repository_, use `*.txt`.
|
||||
* To match all files inside `resources/bin` and below, use `resources/bin/**`.
|
||||
* To match all files _immediately inside_ `resources/bin`, use `resources/bin/*`.
|
||||
* To match all files named `Makefile`, use `**Makefile`.
|
||||
* Matching a directory has no effect; the pattern `resources/bin` will not include/exclude files inside that directory; `resources/bin/**` will.
|
||||
* All files and patterns are normalized to lower case, so `**Makefile`, `**makefile` and `**MAKEFILE` are equivalent.
|
||||
|
||||
|
@@ -1,39 +0,0 @@
|
||||
---
|
||||
date: "2019-12-31T13:55:00+05:00"
|
||||
title: "Advanced: Search Engines Indexation"
|
||||
slug: "search-engines-indexation"
|
||||
weight: 30
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Search Engines Indexation"
|
||||
weight: 60
|
||||
identifier: "search-engines-indexation"
|
||||
---
|
||||
|
||||
# Search engines indexation of your Gitea installation
|
||||
|
||||
By default your Gitea installation will be indexed by search engines.
|
||||
If you don't want your repository to be visible for search engines read further.
|
||||
|
||||
## Block search engines indexation using robots.txt
|
||||
|
||||
To make Gitea serve a custom `robots.txt` (default: empty 404) for top level installations,
|
||||
create a file called `robots.txt` in the [`custom` folder or `CustomPath`]({{< relref "doc/advanced/customizing-gitea.en-us.md" >}})
|
||||
|
||||
Examples on how to configure the `robots.txt` can be found at [https://moz.com/learn/seo/robotstxt](https://moz.com/learn/seo/robotstxt).
|
||||
|
||||
|
||||
```txt
|
||||
User-agent: *
|
||||
Disallow: /
|
||||
```
|
||||
|
||||
If you installed Gitea in a subdirectory, you will need to create or edit the `robots.txt` in the top level directory.
|
||||
|
||||
```txt
|
||||
User-agent: *
|
||||
Disallow: /gitea/
|
||||
```
|
@@ -1,163 +0,0 @@
|
||||
---
|
||||
date: "2019-08-17T10:20:00+01:00"
|
||||
title: "GPG Commit Signatures"
|
||||
slug: "signing"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "GPG Commit Signatures"
|
||||
weight: 20
|
||||
identifier: "signing"
|
||||
---
|
||||
|
||||
# GPG Commit Signatures
|
||||
|
||||
Gitea will verify GPG commit signatures in the provided tree by
|
||||
checking if the commits are signed by a key within the gitea database,
|
||||
or if the commit matches the default key for git.
|
||||
|
||||
Keys are not checked to determine if they have expired or revoked.
|
||||
Keys are also not checked with keyservers.
|
||||
|
||||
A commit will be marked with a grey unlocked icon if no key can be
|
||||
found to verify it. If a commit is marked with a red unlocked icon,
|
||||
it is reported to be signed with a key with an id.
|
||||
|
||||
Please note: The signer of a commit does not have to be an author or
|
||||
committer of a commit.
|
||||
|
||||
This functionality requires git >= 1.7.9 but for full functionality
|
||||
this requires git >= 2.0.0.
|
||||
|
||||
## Automatic Signing
|
||||
|
||||
There are a number of places where Gitea will generate commits itself:
|
||||
|
||||
* Repository Initialisation
|
||||
* Wiki Changes
|
||||
* CRUD actions using the editor or the API
|
||||
* Merges from Pull Requests
|
||||
|
||||
Depending on configuration and server trust you may want Gitea to
|
||||
sign these commits.
|
||||
|
||||
## General Configuration
|
||||
|
||||
Gitea's configuration for signing can be found with the
|
||||
`[repository.signing]` section of `app.ini`:
|
||||
|
||||
```ini
|
||||
...
|
||||
[repository.signing]
|
||||
SIGNING_KEY = default
|
||||
SIGNING_NAME =
|
||||
SIGNING_EMAIL =
|
||||
INITIAL_COMMIT = always
|
||||
CRUD_ACTIONS = pubkey, twofa, parentsigned
|
||||
WIKI = never
|
||||
MERGES = pubkey, twofa, basesigned, commitssigned
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
### `SIGNING_KEY`
|
||||
|
||||
The first option to discuss is the `SIGNING_KEY`. There are three main
|
||||
options:
|
||||
|
||||
* `none` - this prevents Gitea from signing any commits
|
||||
* `default` - Gitea will default to the key configured within
|
||||
`git config`
|
||||
* `KEYID` - Gitea will sign commits with the gpg key with the ID
|
||||
`KEYID`. In this case you should provide a `SIGNING_NAME` and
|
||||
`SIGNING_EMAIL` to be displayed for this key.
|
||||
|
||||
The `default` option will interrogate `git config` for
|
||||
`commit.gpgsign` option - if this is set, then it will use the results
|
||||
of the `user.signingkey`, `user.name` and `user.email` as appropriate.
|
||||
|
||||
Please note: by adjusting git's `config` file within Gitea's
|
||||
repositories, `SIGNING_KEY=default` could be used to provide different
|
||||
signing keys on a per-repository basis. However, this is cleary not an
|
||||
ideal UI and therefore subject to change.
|
||||
|
||||
### `INITIAL_COMMIT`
|
||||
|
||||
This option determines whether Gitea should sign the initial commit
|
||||
when creating a repository. The possible values are:
|
||||
|
||||
* `never`: Never sign
|
||||
* `pubkey`: Only sign if the user has a public key
|
||||
* `twofa`: Only sign if the user logs in with two factor authentication
|
||||
* `always`: Always sign
|
||||
|
||||
Options other than `never` and `always` can be combined as a comma
|
||||
separated list.
|
||||
|
||||
### `WIKI`
|
||||
|
||||
This options determines if Gitea should sign commits to the Wiki.
|
||||
The possible values are:
|
||||
|
||||
* `never`: Never sign
|
||||
* `pubkey`: Only sign if the user has a public key
|
||||
* `twofa`: Only sign if the user logs in with two factor authentication
|
||||
* `parentsigned`: Only sign if the parent commit is signed.
|
||||
* `always`: Always sign
|
||||
|
||||
Options other than `never` and `always` can be combined as a comma
|
||||
separated list.
|
||||
|
||||
### `CRUD_ACTIONS`
|
||||
|
||||
This option determines if Gitea should sign commits from the web
|
||||
editor or API CRUD actions. The possible values are:
|
||||
|
||||
* `never`: Never sign
|
||||
* `pubkey`: Only sign if the user has a public key
|
||||
* `twofa`: Only sign if the user logs in with two factor authentication
|
||||
* `parentsigned`: Only sign if the parent commit is signed.
|
||||
* `always`: Always sign
|
||||
|
||||
Options other than `never` and `always` can be combined as a comma
|
||||
separated list.
|
||||
|
||||
### `MERGES`
|
||||
|
||||
This option determines if Gitea should sign merge commits from PRs.
|
||||
The possible options are:
|
||||
|
||||
* `never`: Never sign
|
||||
* `pubkey`: Only sign if the user has a public key
|
||||
* `twofa`: Only sign if the user logs in with two factor authentication
|
||||
* `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.
|
||||
* `approved`: Only sign approved merges to a protected branch.
|
||||
* `always`: Always sign
|
||||
|
||||
Options other than `never` and `always` can be combined as a comma
|
||||
separated list.
|
||||
|
||||
## Installing and generating a GPG key for Gitea
|
||||
|
||||
It is up to a server administrator to determine how best to install
|
||||
a signing key. Gitea generates all its commits using the server `git`
|
||||
command at present - and therefore the server `gpg` will be used for
|
||||
signing (if configured.) Administrators should review best-practices
|
||||
for gpg - in particular it is probably advisable to only install a
|
||||
signing secret subkey without the master signing and certifying secret
|
||||
key.
|
||||
|
||||
## Obtaining the Public Key of the Signing Key
|
||||
|
||||
The public key used to sign Gitea's commits can be obtained from the API at:
|
||||
|
||||
```/api/v1/signing-key.gpg```
|
||||
|
||||
In cases where there is a repository specific key this can be obtained from:
|
||||
|
||||
```/api/v1/repos/:username/:reponame/signing-key.gpg```
|
@@ -59,7 +59,7 @@ For documentation about each of the variables available, refer to the
|
||||
* `HOST`: Host Macaron will listen on
|
||||
* `PORT`: Port Macaron will listen on
|
||||
* `MACARON_ENV`: global variable to provide special functionality for development environments
|
||||
vs. production environments. If MACARON_ENV is set to "" or "development", then templates will
|
||||
vs. production environments. If MACARON_ENV is set to "" or "development" then templates will
|
||||
be recompiled on every request. For more performance, set the MACARON_ENV environment variable
|
||||
to "production".
|
||||
|
||||
|
@@ -1,40 +0,0 @@
|
||||
---
|
||||
date: "2018-05-22T11:00:00+00:00"
|
||||
title: "Advanced: Third Party Tools"
|
||||
slug: "third-party-tools"
|
||||
weight: 50
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "Third Party Tools"
|
||||
weight: 50
|
||||
identifier: "third-party-tools"
|
||||
---
|
||||
|
||||
# List of third-party tools
|
||||
**NOTE:** These tools are not endorsed by Gitea. They are listed here for convenience only.
|
||||
|
||||
*This is by no means a complete list, so feel free to ask about adding more!*
|
||||
|
||||
### Continuous Integration
|
||||
|
||||
Check our [CI/CD page]({{< relref "doc/advanced/ci-cd.en-us.md" >}})
|
||||
|
||||
### Internationalization
|
||||
[Weblate](https://docs.weblate.org/en/latest/admin/continuous.html#gitea-setup)
|
||||
|
||||
### Migrating
|
||||
[Installation script for Gitea](https://git.coolaj86.com/coolaj86/gitea-installer.sh)
|
||||
[GitHub Migrator](https://gitea.com/gitea/migrator)
|
||||
|
||||
|
||||
### Mobile
|
||||
[GitNex for Android](https://gitlab.com/mmarif4u/gitnex)
|
||||
|
||||
### Editor Extensions
|
||||
- [Gitea Extension for Visual Studio](https://github.com/maikebing/Gitea.VisualStudio) Download from [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=MysticBoy.GiteaExtensionforVisualStudio)
|
||||
|
||||
### Project Management
|
||||
- [YouTrack by JetBrains](https://blog.jetbrains.com/youtrack/2019/12/whats-new-in-youtrack-2019-3/)
|
@@ -1,36 +0,0 @@
|
||||
---
|
||||
date: "2019-03-11T21:45:00+00:00"
|
||||
title: "高级: 第三方工具"
|
||||
slug: "third-party-tools"
|
||||
weight: 50
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "advanced"
|
||||
name: "第三方工具"
|
||||
weight: 50
|
||||
identifier: "third-party-tools"
|
||||
---
|
||||
|
||||
# 第三方工具列表
|
||||
**注意:** 这些工具并没有经过Gitea的检验,在这里列出它们只是为了便捷.
|
||||
|
||||
*此列表并不是完整的列表,可以随时咨询如何添加!*
|
||||
|
||||
### 持续集成
|
||||
[BuildKite 连接器](https://github.com/techknowlogick/gitea-buildkite-connector)
|
||||
[Jenkins 插件](https://github.com/jenkinsci/gitea-plugin)
|
||||
[Gitea搭配Drone](https://docs.drone.io/installation/gitea)
|
||||
|
||||
|
||||
### 迁移
|
||||
[Gitea安装脚本](https://git.coolaj86.com/coolaj86/gitea-installer.sh)
|
||||
[GitHub迁移](https://gitea.com/gitea/migrator)
|
||||
|
||||
|
||||
### 移动端
|
||||
[安卓客户端GitNex](https://gitlab.com/mmarif4u/gitnex)
|
||||
|
||||
### 编辑器扩展
|
||||
- [Gitea的Visual Studio扩展](https://github.com/maikebing/Gitea.VisualStudio) 从 [Visual Studio 扩展市场](https://marketplace.visualstudio.com/items?itemName=MysticBoy.GiteaExtensionforVisualStudio) 下载
|
@@ -91,7 +91,7 @@ Both the LDAP via BindDN and the simple auth LDAP share the following fields:
|
||||
name given on sign-in form.
|
||||
- Example: `(&(objectClass=posixAccount)(uid=%s))`
|
||||
- Example for Microsoft Active Directory (AD): `(&(objectCategory=Person)(memberOf=CN=user-group,OU=example,DC=example,DC=org)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))`
|
||||
- To substitute more than once, `%[1]s` should be used instead, e.g. when
|
||||
- To substitute more than once `%[1]s` should be used instead, e.g. when
|
||||
matching supplied login name against multiple attributes such as user
|
||||
identifier, email or even phone number.
|
||||
- Example: `(&(objectClass=Person)(|(uid=%[1]s)(mail=%[1]s)(mobile=%[1]s)))`
|
||||
@@ -115,10 +115,6 @@ Both the LDAP via BindDN and the simple auth LDAP share the following fields:
|
||||
- Example: `cn=%s,ou=Users,dc=mydomain,dc=com`
|
||||
- Example: `uid=%s,ou=Users,dc=mydomain,dc=com`
|
||||
|
||||
- User Search Base (optional)
|
||||
- The LDAP base at which user accounts will be searched for.
|
||||
- Example: `ou=Users,dc=mydomain,dc=com`
|
||||
|
||||
- User Filter **(required)**
|
||||
- An LDAP filter declaring when a user should be allowed to log in. The `%s`
|
||||
matching parameter will be substituted with login name given on sign-in
|
||||
@@ -185,7 +181,7 @@ configure this, set the fields below:
|
||||
|
||||
## FreeIPA
|
||||
|
||||
- In order to log in to Gitea using FreeIPA credentials, a bind account needs to
|
||||
- In order to log in to Gitea using FreeIPA credentials,a bind account needs to
|
||||
be created for Gitea:
|
||||
|
||||
- On the FreeIPA server, create a `gitea.ldif` file, replacing `dc=example,dc=com`
|
||||
@@ -216,42 +212,3 @@ configure this, set the fields below:
|
||||
|
||||
- Log in to Gitea as an Administrator and click on "Authentication" under Admin Panel.
|
||||
Then click `Add New Source` and fill in the details, changing all where appropriate.
|
||||
|
||||
## SPNEGO with SSPI (Kerberos/NTLM, for Windows only)
|
||||
|
||||
Gitea supports SPNEGO single sign-on authentication (the scheme defined by RFC4559) for the web part of the server via the Security Support Provider Interface (SSPI) built in Windows. SSPI works only in Windows environments - when both the server and the clients are running Windows.
|
||||
|
||||
Before activating SSPI single sign-on authentication (SSO) you have to prepare your environment:
|
||||
|
||||
- Create a separate user account in active directory, under which the `gitea.exe` process will be running (eg. `user` under domain `domain.local`):
|
||||
|
||||
- Create a service principal name for the host where `gitea.exe` is running with class `HTTP`:
|
||||
- Start `Command Prompt` or `PowerShell` as a priviledged domain user (eg. Domain Administrator)
|
||||
- Run the command below, replacing `host.domain.local` with the fully qualified domain name (FQDN) of the server where the web application will be running, and `domain\user` with the name of the account created in the previous step:
|
||||
```
|
||||
setspn -A HTTP/host.domain.local domain\user
|
||||
```
|
||||
|
||||
- Sign in (*sign out if you were already signed in*) with the user created
|
||||
|
||||
- Make sure that `ROOT_URL` in the `[server]` section of `custom/conf/app.ini` is the fully qualified domain name of the server where the web application will be running - the same you used when creating the service principal name (eg. `host.domain.local`)
|
||||
|
||||
- Start the web server (`gitea.exe web`)
|
||||
|
||||
- Enable SSPI authentication by adding an `SPNEGO with SSPI` authentication source in `Site Administration -> Authentication Sources`
|
||||
|
||||
- Sign in to a client computer in the same domain with any domain user (client computer, different from the server running `gitea.exe`)
|
||||
|
||||
- If you are using Chrome, Edge or Internet Explorer, add the URL of the web app to the Local intranet sites (`Internet Options -> Security -> Local intranet -> Sites`)
|
||||
|
||||
- Start Chrome, Edge or Internet Explorer and navigate to the FQDN URL of gitea (eg. `http://host.domain.local:3000`)
|
||||
|
||||
- Click the `Sign In` button on the dashboard and choose SSPI to be automatically logged in with the same user that is currently logged on to the computer
|
||||
|
||||
- If it does not work, make sure that:
|
||||
- You are not running the web browser on the same server where gitea is running. You should be running the web browser on a domain joined computer (client) that is different from the server. If both the client and server are runnning on the same computer NTLM will be prefered over Kerberos.
|
||||
- There is only one `HTTP/...` SPN for the host
|
||||
- The SPN contains only the hostname, without the port
|
||||
- You have added the URL of the web app to the `Local intranet zone`
|
||||
- The clocks of the server and client should not differ with more than 5 minutes (depends on group policy)
|
||||
- `Integrated Windows Authentication` should be enabled in Internet Explorer (under `Advanced settings`)
|
||||
|
@@ -15,9 +15,9 @@ menu:
|
||||
|
||||
# Gitea compared to other Git hosting options
|
||||
|
||||
To help decide if Gitea is suited for your needs, here is how it compares to other Git self hosted options.
|
||||
To help decide if Gitea is suited for your needs here is how it compares to other Git self hosted options.
|
||||
|
||||
Be warned that we don't regularly check for feature changes in other products, so this list may be outdated. If you find anything that needs to be updated in the table below, please report it in an [issue on GitHub](https://github.com/go-gitea/gitea/issues).
|
||||
Be warned that we don't regularly check for feature changes in other products so this list can be outdated. If you find anything that needs to be updated in table below please report [issue on Github](https://github.com/go-gitea/gitea/issues).
|
||||
|
||||
_Symbols used in table:_
|
||||
|
||||
@@ -40,11 +40,11 @@ _Symbols used in table:_
|
||||
| Orgmode support | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ? |
|
||||
| CSV support | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ? |
|
||||
| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ? |
|
||||
| Static Git-powered pages | [✘](https://github.com/go-gitea/gitea/issues/302) | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Static Git-powered pages | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Integrated Git-powered wiki | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||
| Built-in Container Registry | [✘](https://github.com/go-gitea/gitea/issues/2316) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Built-in Container Registry | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| External git mirroring | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
|
||||
| FIDO U2F (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Built-in CI/CD | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
@@ -62,13 +62,12 @@ _Symbols used in table:_
|
||||
| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Verified Committer | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
|
||||
| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Reject unsigned commits | [✘](https://github.com/go-gitea/gitea/issues/2770) | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||
| Reject unsigned commits | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||
| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Branch manager | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Create new branches | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Web code editor | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Commit graph | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Template Repositories | [✓](https://github.com/go-gitea/gitea/pull/8768) | ✘ | ✓ | ✘ | ✓ | ✓ | ✘ |
|
||||
|
||||
#### Issue Tracker
|
||||
|
||||
@@ -82,15 +81,13 @@ _Symbols used in table:_
|
||||
| Related issues | ✘ | ✘ | ⁄ | ✘ | ✓ | ✘ | ✘ |
|
||||
| Confidential issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Comment reactions | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Lock Discussion | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Lock Discussion | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Batch issue handling | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue Boards | [✘](https://github.com/go-gitea/gitea/issues/3476) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue Boards | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Create new branches from issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Global issue search | [✘](https://github.com/go-gitea/gitea/issues/2434) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Global issue search | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Issue dependency | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
||||
| Create issue via email | [✘](https://github.com/go-gitea/gitea/issues/6226) | [✘](https://github.com/gogs/gogs/issues/2602) | ✘ | ✘ | ✓ | ✓ | ✘ |
|
||||
| Service Desk | [✘](https://github.com/go-gitea/gitea/issues/6219) | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ |
|
||||
|
||||
#### Pull/Merge requests
|
||||
|
||||
@@ -101,12 +98,11 @@ _Symbols used in table:_
|
||||
| Rebase merging | ✓ | ✓ | ✓ | ✘ | ⁄ | ✘ | ✓ |
|
||||
| Pull/Merge request inline comments | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Pull/Merge request approval | ✓ | ✘ | ⁄ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Merge conflict resolution | [✘](https://github.com/go-gitea/gitea/issues/5158) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Merge conflict resolution | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Restrict push and merge access to certain users | ✓ | ✘ | ✓ | ⁄ | ✓ | ✓ | ✓ |
|
||||
| Revert specific commits or a merge request | [✘](https://github.com/go-gitea/gitea/issues/5158) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Revert specific commits or a merge request | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Pull/Merge requests templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Cherry-picking changes | [✘](https://github.com/go-gitea/gitea/issues/5158) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Download Patch | ✓ | ✘ | ✓ | ✓ | ✓ | [/](https://jira.atlassian.com/plugins/servlet/mobile#issue/BCLOUD-8323) | ✘ |
|
||||
| Cherry-picking changes | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
|
||||
|
||||
#### 3rd-party integrations
|
||||
@@ -120,9 +116,8 @@ _Symbols used in table:_
|
||||
| LDAP user synchronization | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| OpenId Connect support | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ |
|
||||
| OAuth 2.0 integration (external authorization) | ✓ | ✘ | ⁄ | ✓ | ✓ | ? | ✓ |
|
||||
| Act as OAuth 2.0 provider | [✓](https://github.com/go-gitea/gitea/pull/5378) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Act as OAuth 2.0 provider | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Two factor authentication (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Mattermost/Slack integration | ✓ | ✓ | ⁄ | ✓ | ✓ | ⁄ | ✓ |
|
||||
| Discord integration | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Microsoft Teams integration | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| External CI/CD status display | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
|
@@ -1,127 +0,0 @@
|
||||
---
|
||||
date: "2019-02-14T11:51:04+08:00"
|
||||
title: "横向对比 Gitea 与其它 Git 托管工具"
|
||||
slug: "comparison"
|
||||
weight: 5
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "features"
|
||||
name: "横向对比"
|
||||
weight: 5
|
||||
identifier: "comparison"
|
||||
---
|
||||
|
||||
# 横向对比 Gitea 与其它 Git 托管工具
|
||||
|
||||
这里列出了 Gitea 与其它一些 Git 托管工具之间的异同,以便确认 Gitea 是否能够满足您的需求。
|
||||
|
||||
请注意,此列表中的某些表项可能已经过时,因为我们并没有定期检查其它产品的功能是否有所更改。你可以前往 [Github issue](https://github.com/go-gitea/gitea/issues) 来帮助我们更新过时的内容,感谢!
|
||||
|
||||
_表格中的符号含义:_
|
||||
|
||||
* _✓ - 支持_
|
||||
|
||||
* _⁄ - 部分支持_
|
||||
|
||||
* _✘ - 不支持_
|
||||
|
||||
* _? - 不确定_
|
||||
|
||||
#### 主要特性
|
||||
|
||||
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
|
||||
|-----------------------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| 开源免费 | ✓ | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ |
|
||||
| 低资源开销 (RAM/CPU) | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
||||
| 支持多种数据库 | ✓ | ✓ | ✘ | ⁄ | ⁄ | ✓ | ✓ |
|
||||
| 支持多种操作系统 | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ |
|
||||
| 升级简便 | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ |
|
||||
| 支持 Markdown | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 支持 Orgmode | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ? |
|
||||
| 支持 CSV | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ? |
|
||||
| 支持第三方渲染工具 | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ? |
|
||||
| Git 驱动的静态 pages | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Git 驱动的集成化 wiki | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 部署令牌 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 仓库写权限令牌 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||
| 内置容器 Registry | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 外部 Git 镜像 | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
|
||||
| FIDO U2F (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 内置 CI/CD | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 子组织:组织内的组织 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ |
|
||||
|
||||
#### 代码管理
|
||||
|
||||
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
|
||||
|------------------------------------------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| 仓库主题描述 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 仓库内代码搜索 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 全局代码搜索 | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ |
|
||||
| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ |
|
||||
| 组织里程碑 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 细粒度用户角色 (例如 Code, Issues, Wiki) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 提交人的身份验证 | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
|
||||
| GPG 签名的提交 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 拒绝未用通过验证的提交 | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||
| 仓库活跃度页面 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 分支管理 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 建立新分支 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 在线代码编辑 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 提交的统计图表 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
|
||||
#### Issue 管理
|
||||
|
||||
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
|
||||
|----------------------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| 跟踪 Issue | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Issue 模板 | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 标签 | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 跟踪时间 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue 可有多个负责人 | ✓ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ |
|
||||
| 关联的 issues | ✘ | ✘ | ⁄ | ✘ | ✓ | ✘ | ✘ |
|
||||
| 私密 issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 评论反馈 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 锁定讨论 | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue 批量处理 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue 看板 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 从 issues 创建分支 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
| Issue 搜索 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 全局 Issue 搜索 | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Issue 依赖 | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
||||
| 通过 Email 创建工单 | [✘](https://github.com/go-gitea/gitea/issues/6226) | [✘](https://github.com/gogs/gogs/issues/2602) | ✘ | ✘ | ✓ | ✓ | ✘ |
|
||||
| Service Desk | [✘](https://github.com/go-gitea/gitea/issues/6219) | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ |
|
||||
|
||||
#### Pull/Merge requests
|
||||
|
||||
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
|
||||
|--------------------------------------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| Pull/Merge requests | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Squash merging | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ |
|
||||
| Rebase merging | ✓ | ✓ | ✓ | ✘ | ⁄ | ✘ | ✓ |
|
||||
| 评论 Pull/Merge request 中的某行代码 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 指定 Pull/Merge request 的审核人 | ✓ | ✘ | ⁄ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 解决 Merge 冲突 | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 限制某些用户的 push 和 merge 权限 | ✓ | ✘ | ✓ | ⁄ | ✓ | ✓ | ✓ |
|
||||
| 回退某些 commits 或 merge request | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| Pull/Merge requests 模板 | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 查看 Cherry-picking 的更改 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||
|
||||
|
||||
#### 第三方集成
|
||||
|
||||
| 特性 | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
|
||||
|----------------------------|-------|------|-----------|-----------|-----------|-----------|--------------|
|
||||
| 支持 Webhook | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 自定义 Git 钩子 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 集成 AD / LDAP | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 支持多个 LDAP / AD 服务 | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
|
||||
| LDAP 用户同步 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| 支持 OpenId 连接 | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ |
|
||||
| 集成 OAuth 2.0(外部授权) | ✓ | ✘ | ⁄ | ✓ | ✓ | ? | ✓ |
|
||||
| 作为 OAuth 2.0 provider | [✓](https://github.com/go-gitea/gitea/pull/5378) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 二次验证 (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
|
||||
| 集成 Mattermost/Slack | ✓ | ✓ | ⁄ | ✓ | ✓ | ⁄ | ✓ |
|
||||
| 集成 Discord | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
|
||||
| 显示外部 CI/CD 的状态 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
@@ -1,56 +0,0 @@
|
||||
---
|
||||
date: "2019-11-28:00:00+02:00"
|
||||
title: "The .gitea Directory"
|
||||
slug: "gitea-directory"
|
||||
weight: 40
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "features"
|
||||
name: "The .gitea Directory"
|
||||
weight: 50
|
||||
identifier: "gitea-directory"
|
||||
---
|
||||
|
||||
# The .gitea directory
|
||||
Gitea repositories can include a `.gitea` directory at their base which will store settings/configurations for certain features.
|
||||
|
||||
## Templates
|
||||
Gitea includes template repositories, and one feature implemented with them is auto-expansion of specific variables within your template files.
|
||||
To tell Gitea which files to expand, you must include a `template` file inside the `.gitea` directory of the template repository.
|
||||
Gitea uses [gobwas/glob](https://github.com/gobwas/glob) for its glob syntax. It closely resembles a traditional `.gitignore`, however there may be slight differences.
|
||||
|
||||
### Example `.gitea/template` file
|
||||
All paths are relative to the base of the repository
|
||||
```gitignore
|
||||
# All .go files, anywhere in the repository
|
||||
**.go
|
||||
|
||||
# All text files in the text directory
|
||||
text/*.txt
|
||||
|
||||
# A specific file
|
||||
a/b/c/d.json
|
||||
|
||||
# Batch files in both upper or lower case can be matched
|
||||
**.[bB][aA][tT]
|
||||
```
|
||||
**NOTE:** The `template` file will be removed from the `.gitea` directory when a repository is generated from the template.
|
||||
|
||||
### Variable Expansion
|
||||
In any file matched by the above globs, certain variables will be expanded.
|
||||
All variables must be of the form `$VAR` or `${VAR}`. To escape an expansion, use a double `$$`, such as `$$VAR` or `$${VAR}`
|
||||
|
||||
| Variable | Expands To |
|
||||
|----------------------|-----------------------------------------------------|
|
||||
| REPO_NAME | The name of the generated repository |
|
||||
| TEMPLATE_NAME | The name of the template repository |
|
||||
| REPO_DESCRIPTION | The description of the generated repository |
|
||||
| TEMPLATE_DESCRIPTION | The description of the template repository |
|
||||
| REPO_LINK | The URL to the generated repository |
|
||||
| TEMPLATE_LINK | The URL to the template repository |
|
||||
| REPO_HTTPS_URL | The HTTP(S) clone link for the generated repository |
|
||||
| TEMPLATE_HTTPS_URL | The HTTP(S) clone link for the template repository |
|
||||
| REPO_SSH_URL | The SSH clone link for the generated repository |
|
||||
| TEMPLATE_SSH_URL | The SSH clone link for the template repository |
|
@@ -15,17 +15,9 @@ menu:
|
||||
|
||||
# Webhooks
|
||||
|
||||
Gitea supports web hooks for repository events. This can be found in the settings
|
||||
page `/:username/:reponame/settings/hooks`. All event pushes are POST requests.
|
||||
The methods currently supported are:
|
||||
|
||||
- Gitea
|
||||
- Gogs
|
||||
- Slack
|
||||
- Discord
|
||||
- Dingtalk
|
||||
- Telegram
|
||||
- Microsoft Teams
|
||||
Gitea supports web hooks for repository events, this can be found in the settings
|
||||
page(`/:username/:reponame/settings/hooks`). All event pushes are POST requests.
|
||||
The two methods currently supported are Gitea and Slack.
|
||||
|
||||
### Event information
|
||||
|
||||
@@ -34,8 +26,8 @@ a Payload URL:
|
||||
|
||||
|
||||
```
|
||||
X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
|
||||
X-GitHub-Event: push
|
||||
X-Github-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
|
||||
X-Github-Event: push
|
||||
X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
|
||||
X-Gogs-Event: push
|
||||
X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
|
||||
@@ -112,75 +104,3 @@ X-Gitea-Event: push
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
This is an example of how to use webhooks to run a php script upon push requests to the repository.
|
||||
In your repository Settings, under Webhooks, Setup a Gitea webhook as follows:
|
||||
|
||||
- Target URL: http://mydomain.com/webhook.php
|
||||
- HTTP Method: POST
|
||||
- POST Content Type: application/json
|
||||
- Secret: 123
|
||||
- Trigger On: Push Events
|
||||
- Active: Checked
|
||||
|
||||
Now on your server create the php file webhook.php
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
$secret_key = '123';
|
||||
|
||||
// check for POST request
|
||||
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||
error_log('FAILED - not POST - '. $_SERVER['REQUEST_METHOD']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// get content type
|
||||
$content_type = isset($_SERVER['CONTENT_TYPE']) ? strtolower(trim($_SERVER['CONTENT_TYPE'])) : '';
|
||||
|
||||
if ($content_type != 'application/json') {
|
||||
error_log('FAILED - not application/json - '. $content_type);
|
||||
exit();
|
||||
}
|
||||
|
||||
// get payload
|
||||
$payload = trim(file_get_contents("php://input"));
|
||||
|
||||
if (empty($payload)) {
|
||||
error_log('FAILED - no payload');
|
||||
exit();
|
||||
}
|
||||
|
||||
// get header signature
|
||||
$header_signature = isset($_SERVER['HTTP_X_GITEA_SIGNATURE']) ? $_SERVER['HTTP_X_GITEA_SIGNATURE'] : '';
|
||||
|
||||
if (empty($header_signature)) {
|
||||
error_log('FAILED - header signature missing');
|
||||
exit();
|
||||
}
|
||||
|
||||
// calculate payload signature
|
||||
$payload_signature = hash_hmac('sha256', $payload, $secret_key, false);
|
||||
|
||||
// check payload signature against header signature
|
||||
if ($header_signature != $payload_signature) {
|
||||
error_log('FAILED - payload signature');
|
||||
exit();
|
||||
}
|
||||
|
||||
// convert json to array
|
||||
$decoded = json_decode($payload, true);
|
||||
|
||||
// check for json decode errors
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
error_log('FAILED - json decode - '. json_last_error());
|
||||
exit();
|
||||
}
|
||||
|
||||
// success, do something
|
||||
```
|
||||
|
||||
There is a Test Delivery button in the webhook settings that allows to test the configuration as well as a list of the most Recent Deliveries.
|
||||
|
@@ -2,12 +2,12 @@
|
||||
date: "2017-01-20T15:00:00+08:00"
|
||||
title: "Help"
|
||||
slug: "help"
|
||||
weight: 5
|
||||
weight: 50
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Help"
|
||||
weight: 5
|
||||
weight: 50
|
||||
identifier: "help"
|
||||
---
|
||||
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2017-01-20T15:00:00+08:00"
|
||||
title: "Aide"
|
||||
slug: "help"
|
||||
weight: 5
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Aide"
|
||||
weight: 5
|
||||
identifier: "help"
|
||||
---
|
@@ -2,12 +2,12 @@
|
||||
date: "2017-01-20T15:00:00+08:00"
|
||||
title: "帮助"
|
||||
slug: "help"
|
||||
weight: 5
|
||||
weight: 50
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "帮助"
|
||||
weight: 5
|
||||
weight: 50
|
||||
identifier: "help"
|
||||
---
|
||||
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2017-01-20T15:00:00+08:00"
|
||||
title: "救命"
|
||||
slug: "help"
|
||||
weight: 5
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "救命"
|
||||
weight: 5
|
||||
identifier: "help"
|
||||
---
|
@@ -1,293 +0,0 @@
|
||||
---
|
||||
date: "2019-04-05T16:00:00+02:00"
|
||||
title: "FAQ"
|
||||
slug: "faq"
|
||||
weight: 5
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "help"
|
||||
name: "FAQ"
|
||||
weight: 5
|
||||
identifier: "faq"
|
||||
---
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
This page contains some common questions and answers.
|
||||
Also see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}})
|
||||
|
||||
* [Difference between 1.x and 1.x.x downloads](#difference-between-1-x-and-1-x-x-downloads)
|
||||
* [How to migrate from Gogs/GitHub/etc. to Gitea](#how-to-migrate-from-gogs-github-etc-to-gitea)
|
||||
* [Where does Gitea store "x" file](#where-does-gitea-store-x-file)
|
||||
* [Not seeing a clone URL or the clone URL being incorrect](#not-seeing-a-clone-url-or-the-clone-url-being-incorrect)
|
||||
* [Custom Templates not loading or working incorrectly](#custom-templates-not-loading-or-working-incorrectly)
|
||||
* [Active user vs login prohibited user](#active-user-vs-login-prohibited-user)
|
||||
* [Setting up logging](#setting-up-logging)
|
||||
* [What is Swagger?](#what-is-swagger)
|
||||
* [Adjusting your server for public/private use](#adjusting-your-server-for-public-private-use)
|
||||
* [Preventing spammers](#preventing-spammers)
|
||||
* [Only allow certain email domains](#only-allow-certain-email-domains)
|
||||
* [Only allow/block certain OpenID providers](#only-allow-block-certain-openid-providers)
|
||||
* [Issue only users](#issue-only-users)
|
||||
* [Enable Fail2ban](#enable-fail2ban)
|
||||
* [Adding custom themes](#how-to-add-use-custom-themes)
|
||||
* [SSHD vs built-in SSH](#sshd-vs-built-in-ssh)
|
||||
* [Gitea is running slow](#gitea-is-running-slow)
|
||||
* [Can't create repositories/files](#cant-create-repositories-files)
|
||||
* [Translation is incorrect/how to add more translations](#translation-is-incorrect-how-to-add-more-translations)
|
||||
* [Hooks aren't running](#hooks-aren-t-running)
|
||||
* [SSH Issues](#ssh-issues)
|
||||
* [SSH Common Errors](#ssh-common-errors)
|
||||
* [Missing releases after migration repository with tags](#missing-releases-after-migrating-repository-with-tags)
|
||||
* [LFS Issues](#lfs-issues)
|
||||
* [How can I create users before starting Gitea](#how-can-i-create-users-before-starting-gitea)
|
||||
* [How can I enable password reset](#how-can-i-enable-password-reset)
|
||||
* [How can a user's password be changed](#how-can-a-user-s-password-be-changed)
|
||||
|
||||
|
||||
## Difference between 1.x and 1.x.x downloads
|
||||
Version 1.7.x will be used for this example.
|
||||
**NOTE:** this example applies to Docker images as well!
|
||||
|
||||
On our [downloads page](https://dl.gitea.io/gitea/) you will see a 1.7 directory, as well as directories for 1.7.0, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, and 1.7.6.
|
||||
The 1.7 and 1.7.0 directories are **not** the same. The 1.7 directory is built on each merged commit to the [`release/v1.7`](https://github.com/go-gitea/gitea/tree/release/v1.7) branch.
|
||||
The 1.7.0 directory, however, is a build that was created when the [`v1.7.0`](https://github.com/go-gitea/gitea/releases/tag/v1.7.0) tag was created.
|
||||
|
||||
This means that 1.x downloads will change as commits are merged to their respective branch (think of it as a separate "master" branch for each release).
|
||||
On the other hand, 1.x.x downloads should never change.
|
||||
|
||||
## How to migrate from Gogs/GitHub/etc. to Gitea
|
||||
To migrate from Gogs to Gitea:
|
||||
|
||||
* [Gogs version 0.9.146 or less]({{< relref "doc/upgrade/from-gogs.en-us.md" >}})
|
||||
* [Gogs version 0.11.46.0418](https://github.com/go-gitea/gitea/issues/4286)
|
||||
|
||||
To migrate from GitHub to Gitea, you can use Gitea's [Migrator tool](https://gitea.com/gitea/migrator)
|
||||
|
||||
To migrate from Gitlab to Gitea, you can use this non-affiliated tool:
|
||||
https://github.com/loganinak/MigrateGitlabToGogs
|
||||
|
||||
## Where does Gitea store "x" file
|
||||
* WorkPath
|
||||
* Environment variable `GITEA_WORK_DIR`
|
||||
* Else binary location
|
||||
* AppDataPath (default for database, indexers, etc.)
|
||||
* `APP_DATA_PATH` from `app.ini`
|
||||
* Else `%(WorkPath)/data`
|
||||
* CustomPath (custom templates)
|
||||
* Environment variable `GITEA_CUSTOM`
|
||||
* Else `%(WorkPath)/custom`
|
||||
* HomeDir
|
||||
* Unix: Environment variable `HOME`
|
||||
* Windows: Environment variable `USERPROFILE`, else environment variables `HOMEDRIVE`+`HOMEPATH`
|
||||
* RepoRootPath
|
||||
* `ROOT` in `app.ini`
|
||||
* Else `%(HomeDir)/gitea-repositories`
|
||||
* INI (config file)
|
||||
* `-c` flag
|
||||
* Else `%(CustomPath)/conf/app.ini`
|
||||
* SQLite Database
|
||||
* `PATH` in `database` section of `app.ini`
|
||||
* Else `%(AppDataPath)/gitea.db`
|
||||
|
||||
## Not seeing a clone URL or the clone URL being incorrect
|
||||
There are a few places that could make this show incorrectly.
|
||||
|
||||
1. If using a reverse proxy, make sure you have followed the correction directions in the [reverse proxy guide]({{< relref "doc/usage/reverse-proxies.en-us.md" >}})
|
||||
2. Make sure you have correctly set `ROOT_URL` in the `server` section of your `app.ini`
|
||||
|
||||
If certain clone options aren't showing up (HTTP/S or SSH), the following options can be checked in your `app.ini`
|
||||
|
||||
`DISABLE_HTTP_GIT`: if set to true, there will be no HTTP/HTTPS link
|
||||
`DISABLE_SSH`: if set to true, there will be no SSH link
|
||||
`SSH_EXPOSE_ANONYMOUS`: if set to false, SSH links will be hidden for anonymous users
|
||||
|
||||
|
||||
## Custom Templates not loading or working incorrectly
|
||||
Gitea's custom templates must be added to the correct location or Gitea will not find and use them.
|
||||
The correct path for the template(s) will be relative to the `CustomPath`
|
||||
|
||||
1. To find `CustomPath`, look for Custom File Root Path in Site Administration -> Configuration
|
||||
* If that doesn't exist, you can try `echo $GITEA_CUSTOM`
|
||||
2. If you are still unable to find a path, the default can be [calculated above](#where-does-gitea-store-x-file)
|
||||
3. Once you have figured out the correct custom path, you can refer to the [customizing Gitea]({{< relref "doc/advanced/customizing-gitea.en-us.md" >}}) page to add your template to the correct location.
|
||||
|
||||
## Active user vs login prohibited user
|
||||
In Gitea, an "active" user refers to a user that has activated their account via email.
|
||||
A "login prohibited" user is a user that is not allowed to log in to Gitea anymore
|
||||
|
||||
## Setting up logging
|
||||
* [Official Docs]({{< relref "doc/advanced/logging-documentation.en-us.md" >}})
|
||||
|
||||
## What is Swagger?
|
||||
[Swagger](https://swagger.io/) is what Gitea uses for its API.
|
||||
All Gitea instances have the built-in API, though it can be disabled by setting `ENABLE_SWAGGER` to `false` in the `api` section of your `app.ini`
|
||||
For more information, refer to Gitea's [API docs]({{< relref "doc/advanced/api-usage.en-us.md" >}})
|
||||
|
||||
[Swagger Example](https://try.gitea.io/api/swagger)
|
||||
|
||||
## Adjusting your server for public/private use
|
||||
|
||||
### Preventing spammers
|
||||
There are multiple things you can combine to prevent spammers.
|
||||
|
||||
1. By only whitelisting certain domains with OpenID (see below)
|
||||
2. Setting `ENABLE_CAPTCHA` to `true` in your `app.ini` and properly configuring `RECAPTCHA_SECRET` and `RECAPTCHA_SITEKEY`
|
||||
3. Settings `DISABLE_REGISTRATION` to `true` and creating new users via the [CLI]({{< relref "doc/usage/command-line.en-us.md" >}}), [API]({{< relref "doc/advanced/api-usage.en-us.md" >}}), or Gitea's Admin UI
|
||||
|
||||
### Only allow certain email domains
|
||||
You can configure `EMAIL_DOMAIN_WHITELIST` in your app.ini under `[service]`
|
||||
|
||||
### Only allow/block certain OpenID providers
|
||||
You can configure `WHITELISTED_URIS` or `BLACKLISTED_URIS` under `[openid]` in your `app.ini`
|
||||
**NOTE:** whitelisted takes precedence, so if it is non-blank then blacklisted is ignored
|
||||
|
||||
### Issue only users
|
||||
The current way to achieve this is to create/modify a user with a max repo creation limit of 0.
|
||||
|
||||
### Enable Fail2ban
|
||||
|
||||
Use [Fail2Ban]({{ relref "doc/usage/fail2ban-setup.md" >}}) to monitor and stop automated login attempts or other malicious behavior based on log patterns
|
||||
|
||||
## How to add/use custom themes
|
||||
Gitea supports two official themes right now, `gitea` and `arc-green` (`light` and `dark` respectively)
|
||||
To add your own theme, currently the only way is to provide a complete theme (not just color overrides)
|
||||
|
||||
As an example, let's say our theme is `arc-blue` (this is a real theme, and can be found [in this issue](https://github.com/go-gitea/gitea/issues/6011))
|
||||
Name the `.css` file `theme-arc-blue.css` and add it to your custom folder in `custom/pulic/css`
|
||||
Allow users to use it by adding `arc-blue` to the list of `THEMES` in your `app.ini`
|
||||
|
||||
## SSHD vs built-in SSH
|
||||
SSHD is the built-in SSH server on most Unix systems.
|
||||
Gitea also provides its own SSH server, for usage when SSHD is not available.
|
||||
|
||||
## Gitea is running slow
|
||||
The most common culprit for this is loading federated avatars.
|
||||
This can be turned off by setting `ENABLE_FEDERATED_AVATAR` to `false` in your `app.ini`
|
||||
Another option that may need to be changed is setting `DISABLE_GRAVATAR` to `true` in your `app.ini`
|
||||
|
||||
## Can't create repositories/files
|
||||
Make sure that Gitea has sufficient permissions to write to its home directory and data directory.
|
||||
See [AppDataPath and RepoRootPath](#where-does-gitea-store-x-file)
|
||||
|
||||
**Note for Arch users:** At the time of writing this, there is an issue with the Arch package's systemd file including this line:
|
||||
`ReadWritePaths=/etc/gitea/app.ini`
|
||||
Which makes all other paths non-writeable to Gitea.
|
||||
|
||||
## Translation is incorrect/how to add more translations
|
||||
Our translations are currently crowd-sourced on our [Crowdin project](https://crowdin.com/project/gitea)
|
||||
Whether you want to change a translation or add a new one, it will need to be there as all translations are overwritten in our CI via the Crowdin integration.
|
||||
|
||||
## Hooks aren't running
|
||||
If Gitea is not running hooks, a common cause is incorrect setup of SSH keys.
|
||||
See [SSH Issues](#ssh-issues) for more information.
|
||||
|
||||
You can also try logging into the administration panel and running the `Resynchronize pre-receive, update and post-receive hooks of all repositories.` option.
|
||||
|
||||
## SSH issues
|
||||
If you cannot reach repositories over `ssh`, but `https` works fine, consider looking into the following.
|
||||
|
||||
First, make sure you can access Gitea via SSH.
|
||||
`ssh git@myremote.example`
|
||||
|
||||
If the connection is successful, you should receive an error message like the following:
|
||||
```
|
||||
Hi there, You've successfully authenticated, but Gitea does not provide shell access.
|
||||
If this is unexpected, please log in with password and setup Gitea under another user.
|
||||
```
|
||||
|
||||
If you do not get the above message but still connect, it means your SSH key is **not** being managed by Gitea. This means hooks won't run, among other potential problems.
|
||||
|
||||
If you cannot connect at all, your SSH key may not be configured correctly locally.
|
||||
This is specific to SSH and not Gitea, so will not be covered here.
|
||||
|
||||
### SSH Common Errors
|
||||
|
||||
```
|
||||
Permission denied (publickey).
|
||||
fatal: Could not read from remote repository.
|
||||
```
|
||||
|
||||
This error signifies that the server rejected a log in attempt, check the
|
||||
following things:
|
||||
|
||||
* On the client:
|
||||
* Ensure the public and private ssh keys are added to the correct Gitea user.
|
||||
* Make sure there are no issues in the remote url. In particular, ensure the name of the
|
||||
git user (before the `@`) is spelled correctly.
|
||||
* Ensure public and private ssh keys are correct on client machine.
|
||||
* On the server:
|
||||
* Make sure the repository exists and is correctly named.
|
||||
* Check the permissions of the `.ssh` directory in the system user's home directory.
|
||||
* Verify that the correct public keys are added to `.ssh/authorized_keys`.
|
||||
Try to run `Rewrite '.ssh/authorized_keys' file (for Gitea SSH keys)` on the
|
||||
Gitea admin panel.
|
||||
* Read Gitea logs.
|
||||
* Read /var/log/auth (or similar).
|
||||
* Check permissions of repositories.
|
||||
|
||||
The following is an example of a missing public SSH key where authentication
|
||||
succeeded, but some other setting is preventing SSH from reaching the correct
|
||||
repository.
|
||||
|
||||
```
|
||||
fatal: Could not read from remote repository.
|
||||
|
||||
Please make sure you have the correct access rights
|
||||
and the repository exists.
|
||||
```
|
||||
|
||||
In this case, look into the following settings:
|
||||
|
||||
* On the server:
|
||||
* Make sure that the `git` system user has a usable shell set
|
||||
* Verify this with `getent passwd git | cut -d: -f7`
|
||||
* `usermod` or `chsh` can be used to modify this.
|
||||
* Ensure that the `gitea serv` command in `.ssh/authorized_keys` uses the
|
||||
correct configuration file.
|
||||
|
||||
## Missing releases after migrating repository with tags
|
||||
|
||||
To migrate an repository *with* all tags, you need to do two things:
|
||||
|
||||
* Push tags to the repository:
|
||||
```
|
||||
git push --tags
|
||||
```
|
||||
|
||||
* (Re-)sync tags of all repositories within Gitea:
|
||||
```
|
||||
gitea admin repo-sync-releases
|
||||
```
|
||||
|
||||
## LFS Issues
|
||||
|
||||
For issues concerning LFS data upload
|
||||
|
||||
```
|
||||
batch response: Authentication required: Authorization error: <GITEA_LFS_URL>/info/lfs/objects/batch
|
||||
Check that you have proper access to the repository
|
||||
error: failed to push some refs to '<GIT_REPO_URL>'
|
||||
```
|
||||
Check the value of `LFS_HTTP_AUTH_EXPIRY` in your `app.ini` file.
|
||||
By default, your LFS token will expire after 20 minutes. If you have a slow connection or a large file (or both), it may not finish uploading within the time limit.
|
||||
|
||||
You may want to set this value to `60m` or `120m`.
|
||||
|
||||
## How can I create users before starting Gitea
|
||||
Gitea provides a sub-command `gitea migrate` to initialize the database, after which you can use the [admin CLI commands]({{< relref "doc/usage/command-line.en-us.md#admin" >}}) to add users like normal.
|
||||
|
||||
## How can I enable password reset
|
||||
There is no setting for password resets. It is enabled when a [mail service]({{< relref "doc/usage/email-setup.en-us.md" >}}) is configured, and disabled otherwise.
|
||||
|
||||
## How can a user's password be changed
|
||||
- As an **admin**, you can change any user's password (and optionally force them to change it on next login)...
|
||||
- By navigating to your `Site Administration -> User Accounts` page and editing a user.
|
||||
- By using the [admin CLI commands]({{< relref "doc/usage/command-line.en-us.md#admin" >}}).
|
||||
Keep in mind most commands will also need a [global flag]({{< relref "doc/usage/command-line.en-us.md#global-options" >}}) to point the CLI at the correct configuration.
|
||||
- As a **user** you can change it...
|
||||
- In your account `Settings -> Account` page (this method **requires** you to know your current password).
|
||||
- By using the `Forgot Password` link.
|
||||
If the `Forgot Password/Account Recovery` page is disabled, please contact your administrator to configure a [mail service]({{< relref "doc/usage/email-setup.en-us.md" >}}).
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
date: "2019-11-12T16:00:00+02:00"
|
||||
title: "Search"
|
||||
slug: "search"
|
||||
weight: 4
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "help"
|
||||
name: "Search"
|
||||
weight: 4
|
||||
identifier: "search"
|
||||
sitemap:
|
||||
priority : 0.1
|
||||
layout: "search"
|
||||
---
|
||||
|
||||
|
||||
This file exists solely to respond to /search URL with the related `search` layout template.
|
||||
|
||||
No content shown here is rendered, all content is based in the template layouts/doc/search.html
|
||||
|
||||
Setting a very low sitemap priority will tell search engines this is not important content.
|
||||
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
date: "2019-11-12T16:00:00+02:00"
|
||||
title: "Chercher"
|
||||
slug: "search"
|
||||
weight: 4
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "help"
|
||||
name: "Chercher"
|
||||
weight: 4
|
||||
identifier: "search"
|
||||
sitemap:
|
||||
priority : 0.1
|
||||
layout: "search"
|
||||
---
|
||||
|
||||
|
||||
This file exists solely to respond to /search URL with the related `search` layout template.
|
||||
|
||||
No content shown here is rendered, all content is based in the template layouts/doc/search.html
|
||||
|
||||
Setting a very low sitemap priority will tell search engines this is not important content.
|
||||
|
@@ -1,25 +0,0 @@
|
||||
---
|
||||
date: "2019-11-12T16:00:00+02:00"
|
||||
title: "搜索"
|
||||
slug: "search"
|
||||
weight: 4
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "help"
|
||||
name: "搜索"
|
||||
weight: 4
|
||||
identifier: "search"
|
||||
sitemap:
|
||||
priority : 0.1
|
||||
layout: "search"
|
||||
---
|
||||
|
||||
|
||||
This file exists solely to respond to /search URL with the related `search` layout template.
|
||||
|
||||
No content shown here is rendered, all content is based in the template layouts/doc/search.html
|
||||
|
||||
Setting a very low sitemap priority will tell search engines this is not important content.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user